Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .github/workflows/quality.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ jobs:
# An in-tree checkout would land under the all-files hooks.
- name: Install the pinned rune
env:
RUNE_CLI_REV: eb6cec352ea6f0f60893d9ec6555348190853001
RUNE_CLI_REV: 1cea8c7995591518df25687bc1203e45524ce624
run: |
cargo install --quiet --git https://github.com/runedeck/cli --rev "$RUNE_CLI_REV" rune-cli
rune --version
Expand Down Expand Up @@ -150,6 +150,10 @@ jobs:
# The prek CLI is called directly: the wrapper action logs at
# TRACE level and buries the failing hook's output. REQUIRE_GATES
# turns a missing linter into a failure instead of a skip.
# The idea snapshot check reads the owner's vault through the
# Obsidian CLI, which no runner has, so it stays a local gate:
# a fresh branch's first push checks every file and would fail
# on it under REQUIRE_GATES.
- name: Commit-stage checks
env:
REQUIRE_GATES: "1"
Expand All @@ -158,9 +162,9 @@ jobs:
TO_REF: ${{ steps.check-range.outputs.to }}
run: |
if [ "$RANGE_USABLE" = "true" ]; then
prek run --from-ref "$FROM_REF" --to-ref "$TO_REF"
prek run --skip sync-idea --from-ref "$FROM_REF" --to-ref "$TO_REF"
else
prek run --all-files
prek run --skip sync-idea --all-files
fi

# Scan the same range at the pre-push stage. Without a usable base,
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/safetyfirst.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
with:
repository: runedeck/cli
ref: 7412b6acf037420129c8ac45759d4c75af0e96af
ref: 1cea8c7995591518df25687bc1203e45524ce624
path: .validation-cli
persist-credentials: false
- uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable
Expand Down
9 changes: 6 additions & 3 deletions .vale/styles/Core/UndefinedTerm.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
# the text counts as the definition, and italics alone are emphasis. The
# nouns are the TERMS subset of OVERUSE, so one list serves this rule and
# STE.Overused*. Raw scope, because Vale strips the markers before any
# other scope.
# other scope. A hyphenated name such as review-lanes is a name, not
# the noun, in prose and in link text, and a link whose text ends in
# the noun (agentic review lane) defines it. The first pattern matches
# the stem alone, so a plural use counts as defined by its singular link.
extends: conditional
message: "'%s' is never defined here. Link it to its glossary page at first use, or say which check, file, or flag it is (rule Deslop)."
level: warning
ignorecase: true
scope: raw
first: '\b(arm|gate|knob|landscape|lane|surface)s?\b'
second: '(?:\[(?<a>arm|gate|knob|landscape|lane|surface)s?\]\[|[*_`](?<a>arm|gate|knob|landscape|lane|surface)s?[*_`])'
first: '(?<![\w-])(arm|gate|knob|landscape|lane|surface)(?=s?(?![\w-]))'
second: '(?:\[[^\]]*?(?<![\w-])(?<a>arm|gate|knob|landscape|lane|surface)s?\]\[|\*\*(?<a>arm|gate|knob|landscape|lane|surface)s?\*\*|__(?<a>arm|gate|knob|landscape|lane|surface)s?__|`(?<a>arm|gate|knob|landscape|lane|surface)s?`)'
3 changes: 2 additions & 1 deletion .vale/styles/Core/UnexplainedAbbreviation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ message: "'%s' is an abbreviation with no explanation here. Spell it out at firs
level: suggestion
scope: text
ignorecase: false
first: '\b([A-Z]{2,})\b'
# A roman numeral (Part II, chapter IV) is a number, not an abbreviation.
first: '\b(?![IVXLC]+\b)([A-Z]{2,})\b'
second: '(?:\((?<a>[A-Z]{2,})\)|\b(?<a>[A-Z]{2,})(?=\s*\([A-Za-z]))'
exceptions:
- MUST
Expand Down
1 change: 1 addition & 0 deletions docs/changes/agentic-first-pipeline-rules/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ A requirement names a role. This table names the command or link form behind eac
|---|---|---|
| Pushback before scaffold | `rune spec propose` | Creates the change directory once the challenge pass leaves a sharpened intent standing. |
| Any medium, one entry point | `obsidian://` | The link form a drawing in the owner's vault arrives in. The Obsidian CLI reads it. |

A requirement names a role. This table names the program and hook behind each requirement, so nothing is lost when a command moves out of a requirement.

| Requirement | Command | Notes |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ For Claude Code, the *[basis parameters][BASISPARAMETERS]* add an argument hint
| environment-variables-supported-syntax | Value Sources Have One Order | missed requirement: no check runs the loader against a fixture that sets all four sources |
| environment-variables-supported-syntax | The Loader Exports Environment Variables | missed requirement: no loader exists yet |
| environment-variables-supported-syntax | The Shell Resolves the Variable | missed requirement: no check finds a named variable that no step reads, carried over from the foundations' coverage table |
| environment-variables-supported-syntax | Each Harness Runs the Loader | missed requirement: the assembler writes no loader step and no context line yet |
| environment-variables-supported-syntax | Each [Harness][HARNESS] Runs the Loader | missed requirement: the [assembler][ASSEMBLER] writes no loader step and no context line yet |
| environment-variables-supported-syntax | Provenance Shows the Parameters | missed requirement: `scripts/check-provenance` checks that the sidecar exists, and no check reads a parameters field yet |

## Commands
Expand Down
28 changes: 14 additions & 14 deletions docs/changes/one-domain-one-plugin/adr.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,33 +31,33 @@ change: one-domain-one-plugin
## Context and Problem Statement

A *[rune][RUNE]* is the unit the deck is made of, and this record says what one is.
The foundations define the *[instruction][INSTRUCTION]*, the file a *[harness][HARNESS]* loads to steer a *[model][MODEL]*, and require that one source serves every harness and model.
A governed instruction has three kinds of part: what is written once, what varies by harness and model, and what records where an *[instance][INSTANCE]* came from.
Anthropic's glossary calls rules instruction files, and says that Claude Code is the harness and Claude the model inside it ([Claude Code glossary][CC-GLOSSARY]).
Its hooks are settings entries, and a hook rune is the Markdown source that *[assembly][ASSEMBLY]* renders into such an entry.
The foundations define the *[instruction][INSTRUCTION]*, the file a *[harness][HARNESS]* loads to steer a *[model][MODEL]*, and require that one source serves every [harness][HARNESS] and [model][MODEL].
A governed [instruction][INSTRUCTION] has three kinds of part: what is written once, what varies by [harness][HARNESS] and [model][MODEL], and what records where an *[instance][INSTANCE]* came from.
Anthropic's glossary calls rules [instruction][INSTRUCTION] files, and says that Claude Code is the [harness][HARNESS] and Claude the [model][MODEL] inside it ([Claude Code glossary][CC-GLOSSARY]).
Its hooks are settings entries, and a hook [rune][RUNE] is the Markdown source that *[assembly][ASSEMBLY]* renders into such an entry.

## Considered Options

1. Leave the term to the ontology comment. Then nothing records why a rune has these parts and not others.
2. Write one record that defines the parts and the rule for each: one *[canon][CANON]*, *[companions][COMPANION]* for what one harness needs, *[variants][VARIANT]* for what one harness or model needs, a *[sidecar][SIDECAR]* for provenance, and assembly as the only way to make an instance.
1. Leave the term to the ontology comment. Then nothing records why a [rune][RUNE] has these parts and not others.
2. Write one record that defines the parts and the rule for each: one *[canon][CANON]*, *[companions][COMPANION]* for what one [harness][HARNESS] needs, *[variants][VARIANT]* for what one [harness][HARNESS] or [model][MODEL] needs, a *[sidecar][SIDECAR]* for provenance, and [assembly][ASSEMBLY] as the only way to make an [instance][INSTANCE].

## Decision Outcome

Option 2.

- A rune MUST be one instruction: a Markdown file with YAML frontmatter, of kind skill, agent, rule, or hook. A hook rune is the source of a harness's hook configuration. The rendered configuration is not a rune.
- A rune MUST have exactly one [canon][CANON], the vendor-neutral entrypoint, and the canon MUST NOT contain a harness-specific instruction.
- A harness-specific instruction MUST live in a [companion][COMPANION].
- A [rune][RUNE] MUST be one [instruction][INSTRUCTION]: a Markdown file with YAML frontmatter, of kind skill, agent, rule, or hook. A hook [rune][RUNE] is the source of a [harness][HARNESS]'s hook configuration. The rendered configuration is not a [rune][RUNE].
- A [rune][RUNE] MUST have exactly one [canon][CANON], the vendor-neutral entrypoint, and the [canon][CANON] MUST NOT contain a harness-specific [instruction][INSTRUCTION].
- A harness-specific [instruction][INSTRUCTION] MUST live in a [companion][COMPANION].
- A harness-, model-, or user-specific alternative MUST live in a [variant][VARIANT].
- An instance MUST come from [assembly][ASSEMBLY], one for each harness and model, and MUST NOT be edited in its *[target][TARGET]*.
- An [instance][INSTANCE] MUST come from [assembly][ASSEMBLY], one for each [harness][HARNESS] and [model][MODEL], and MUST NOT be edited in its *[target][TARGET]*.
- Provenance MUST live in the [sidecar][SIDECAR] under `.provenance/`, the one exception to metadata inside the file (CORE-0002).

### Consequences

- [+] Every requirement that says rune now points at one definition, and the term check refuses a prose use with no ontology entry.
- [+] A new harness costs companions and nothing in a canon.
- [-] A canon that contains harness wording fails the rule, and that wording belongs in a companion.
- [-] Model is a second assembly dimension, and resolving it needs the harness to say which model runs.
- [+] Every requirement that says [rune][RUNE] now points at one definition, and the term check refuses a prose use with no ontology entry.
- [+] A new [harness][HARNESS] costs [companions][COMPANION] and nothing in a [canon][CANON].
- [-] A [canon][CANON] that contains [harness][HARNESS] wording fails the rule, and that wording belongs in a [companion][COMPANION].
- [-] [Model][MODEL] is a second [assembly][ASSEMBLY] dimension, and resolving it needs the [harness][HARNESS] to say which [model][MODEL] runs.

[INSTRUCTION]: ../../specs/glossary/instruction.md
[CC-GLOSSARY]: https://code.claude.com/docs/en/glossary
Expand Down
12 changes: 6 additions & 6 deletions docs/changes/one-domain-one-plugin/proposal.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ decisions:

A deck grows by domains, and each domain brings its own *[instructions][INSTRUCTION]*, defaults, and checks. Without a unit that keeps those together, every addition touches shared configuration, and every tool reads every file to find what it needs.

That unit is the *[module][MODULE]*. Parnas gave the criterion for splitting a system in 1972: each module hides one design decision that is likely to change, and no other module depends on it ([Parnas][PARNAS]). Ousterhout adds the measure: a good module is deep, a small interface over a large implementation, so the cost of a caller does not grow with the module ([Ousterhout][OUSTERHOUT]). Both arguments hold for instructions as they hold for code. A domain that owns its defaults, its checks, and its instructions can be added, replaced, or removed without a change anywhere else.
That unit is the *[module][MODULE]*. Parnas gave the criterion for splitting a system in 1972: each [module][MODULE] hides one design decision that is likely to change, and no other [module][MODULE] depends on it ([Parnas][PARNAS]). Ousterhout adds the measure: a good [module][MODULE] is deep, a small interface over a large implementation, so the cost of a caller does not grow with the [module][MODULE] ([Ousterhout][OUSTERHOUT]). Both arguments hold for [instructions][INSTRUCTION] as they hold for code. A domain that owns its defaults, its checks, and its [instructions][INSTRUCTION] can be added, replaced, or removed without a change anywhere else.

Three properties make a domain a module here:
Three properties make a domain a [module][MODULE] here:

- It carries its own defaults, and a user overrides them without editing the committed file.
- Every check it needs runs through one shared hook configuration, locally and in CI, so a module cannot pass on one machine and fail on another.
- Every check it needs runs through one shared hook configuration, locally and in CI, so a [module][MODULE] cannot pass on one machine and fail on another.
- Anything it fetches from the network runs only after its digest matches one committed in the repository.

## What Changes

Define module and *[rune][RUNE]* in the ontology. State the configuration overlay, one checker per concern, one validation path, and verified remote execution as the requirements of one capability. The record `adr.md` defines the parts of a rune: one *[canon][CANON]*, *[companions][COMPANION]* for a *[harness][HARNESS]*, *[variants][VARIANT]*, a provenance *[sidecar][SIDECAR]*, and *[assembly][ASSEMBLY]*.
Define [module][MODULE] and *[rune][RUNE]* in the ontology. State the configuration overlay, one checker per concern, one validation path, and verified remote execution as the requirements of one capability. The record `adr.md` defines the parts of a [rune][RUNE]: one *[canon][CANON]*, *[companions][COMPANION]* for a *[harness][HARNESS]*, *[variants][VARIANT]*, a provenance *[sidecar][SIDECAR]*, and *[assembly][ASSEMBLY]*.

## Capabilities

### New Capabilities

- `one-domain-one-plugin`: a module has defaults a user overlays, runs every check through one shared hook configuration, and verifies anything it fetches before it runs.
- `one-domain-one-plugin`: a [module][MODULE] has defaults a user overlays, runs every check through one shared hook configuration, and verifies anything it fetches before it runs.

## Impact

Expand All @@ -39,7 +39,7 @@ Define module and *[rune][RUNE]* in the ontology. State the configuration overla
## Sources

- [On the Criteria To Be Used in Decomposing Systems into Modules][PARNAS], D. L. Parnas, Communications of the ACM 15(12), 1972
- [A Philosophy of Software Design][OUSTERHOUT], John Ousterhout, 2018, on deep modules
- [A Philosophy of Software Design][OUSTERHOUT], John Ousterhout, 2018, on deep [modules][MODULE]

[MODULE]: ../../specs/glossary/module.md
[INSTRUCTION]: ../../specs/glossary/instruction.md
Expand Down
20 changes: 10 additions & 10 deletions docs/changes/one-instance-per-model/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,34 @@

## Approach

Two halves: variants at build time, activation at runtime. The *[assembler][ASSEMBLER]* builds a *[variant][VARIANT]* for each *[model][MODEL]* it knows, because the differences are known before a session. A *[hook][HOOK]* reads the active [model][MODEL] at session start and on a [model][MODEL] change. The [model][MODEL] is chosen at runtime and can change in a session, so build time cannot know it.
Two halves: *[variants][VARIANT]* at build time, activation at runtime. The *[assembler][ASSEMBLER]* builds a [variant][VARIANT] for each *[model][MODEL]* it knows, because the differences are known before a session. A *[hook][HOOK]* reads the active [model][MODEL] at session start and on a [model][MODEL] change. The [model][MODEL] is chosen at runtime and can change in a session, so build time cannot know it.

The alternative was one *[instance][INSTANCE]* for each *[harness][HARNESS]* and [model][MODEL], deployed side by side. It lost twice: it breaks One Instance per Harness, and it still cannot change with the [model][MODEL] in a session. The owner chose the swap: the [hook][HOOK] puts the active [model][MODEL]'s [variant][VARIANT] in place of the one [instance][INSTANCE].
The alternative was one *[instance][INSTANCE]* for each *[harness][HARNESS]* and [model][MODEL], deployed side by side. It lost twice: it breaks One [Instance][INSTANCE] per [Harness][HARNESS], and it still cannot change with the [model][MODEL] in a session. The owner chose the swap: the [hook][HOOK] puts the active [model][MODEL]'s [variant][VARIANT] in place of the one [instance][INSTANCE].

## Coverage table

| Capability | Requirement | Check or missed requirement |
|---|---|---|
| one-instance-per-model | A Variant per Known Model | missed requirement: the assembler builds no model variant yet |
| one-instance-per-model | Variant Resolution Has One Order | missed requirement: no fixture holds a user variant, a harness and model variant, and a harness variant of one instruction |
| one-instance-per-model | A Runtime Hook Activates the Variant | missed requirement: no hook reads the active model yet |
| one-instance-per-model | A [Variant][VARIANT] per Known [Model][MODEL] | missed requirement: the [assembler][ASSEMBLER] builds no [model][MODEL] [variant][VARIANT] yet |
| one-instance-per-model | [Variant][VARIANT] Resolution Has One Order | missed requirement: no fixture holds a user [variant][VARIANT], a [harness][HARNESS] and [model][MODEL] [variant][VARIANT], and a [harness][HARNESS] [variant][VARIANT] of one instruction |
| one-instance-per-model | A Runtime [Hook][HOOK] Activates the [Variant][VARIANT] | missed requirement: no [hook][HOOK] reads the active [model][MODEL] yet |

## Commands

No command implements this change yet. When the cli change that builds it exists, this table names the command, flags, hook, and diagnostic ids for each requirement.
No command implements this change yet. When the cli change that builds it exists, this table names the command, flags, [hook][HOOK], and diagnostic ids for each requirement.

## Decisions

- Reusable Across Harnesses and Models stays in the foundations, with "and models" backed by this change (voice review, 2026-10-18).
- One Instance per Harness stays as written. The [hook][HOOK] swaps in the [model][MODEL]'s [variant][VARIANT] instead of a second [instance][INSTANCE] for each [model][MODEL].
- Reusable Across [Harnesses][HARNESS] and [Models][MODEL] stays in the foundations, with "and [models][MODEL]" backed by this change (voice review, 2026-10-18).
- One [Instance][INSTANCE] per [Harness][HARNESS] stays as written. The [hook][HOOK] swaps in the [model][MODEL]'s [variant][VARIANT] instead of a second [instance][INSTANCE] for each [model][MODEL].
- The ontology's [variant][VARIANT] term already states the resolution order: user, then [harness][HARNESS] and [model][MODEL], then [harness][HARNESS], then the base *[rune][RUNE]*. This change makes the [assembler][ASSEMBLER] and the [hook][HOOK] apply it.
- Companions Earn Their Place decides whether a [model][MODEL] [variant][VARIANT] stays. It beats the *[canon][CANON]* alone on an evaluation for its [harness][HARNESS] and [model][MODEL], or it goes.

## Risks

- A [harness][HARNESS] may not tell a [hook][HOOK] which [model][MODEL] is active, or may not fire a hook on a model change. Guard: where a swap is impossible, the [hook][HOOK] injects the [variant][VARIANT]'s difference as context. Where neither works, the [harness][HARNESS] gets its [harness][HARNESS] [variant][VARIANT] only, and the coverage table says so.
- A [harness][HARNESS] may not tell a [hook][HOOK] which [model][MODEL] is active, or may not fire a [hook][HOOK] on a [model][MODEL] change. Guard: where a swap is impossible, the [hook][HOOK] injects the [variant][VARIANT]'s difference as context. Where neither works, the [harness][HARNESS] gets its [harness][HARNESS] [variant][VARIANT] only, and the coverage table says so.
- A swap in a session leaves the deployment manifest naming the base [instance][INSTANCE]. Guard: the swap is a runtime overlay that the next deployment resets, and the deployment check reads the manifest and ignores the overlay.
- Variants multiply files. Guard: Companions Earn Their Place removes a [variant][VARIANT] that does not beat the canon on an evaluation.
- [Variants][VARIANT] multiply files. Guard: Companions Earn Their Place removes a [variant][VARIANT] that does not beat the [canon][CANON] on an evaluation.

[ASSEMBLER]: ../../specs/glossary/assembler.md
[VARIANT]: ../../specs/glossary/variant.md
Expand Down
Loading
Loading