Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
104 commits
Select commit Hold shift + click to select a range
3bc411f
chore: capture iss-2609290419119456 — home-deleting spellings the gua…
REPPL Sep 29, 2026
ad44726
fix(guard): read the home through continuations, brace groups and ope…
REPPL Sep 29, 2026
2db3cf7
chore: capture and defer iss-2609290426544292 — a default's own word
REPPL Sep 29, 2026
0c75443
chore: resolve iss-2609290419119456 — the guard reads the three home …
REPPL Sep 29, 2026
2fa327b
refactor(guard): name the value-keeping operators as one set
REPPL Sep 29, 2026
d98439d
chore: capture iss-2609290521415701 — the guard tokenizer panics on a…
REPPL Sep 29, 2026
1de705c
fix(guard): read a nested subscript, a sequence's terms and an altern…
REPPL Sep 29, 2026
627a73a
fix(guard): a pending here-document inside an unterminated substitution
REPPL Sep 29, 2026
f8a2396
chore: resolve iss-2609290521415701 — no panic on a pending here-docu…
REPPL Sep 29, 2026
31fe179
chore: restate iss-2609290419119456's resolution to what the guard reads
REPPL Sep 29, 2026
1776c04
chore: capture iss-2609290541525428 — RedactRefusal misses a word-glu…
REPPL Sep 29, 2026
d53e21c
test(termsafe): name unknown.go's backtick scan in the code-span allo…
REPPL Sep 29, 2026
4e70636
fix(scanner): RedactRefusal seals a token glued behind a word character
REPPL Sep 29, 2026
772a0f2
chore: capture iss-2609290551363398 — ScanText misses a word-glued token
REPPL Sep 29, 2026
7f032b9
fix(scanner): ScanText finds a secret token glued behind a word chara…
REPPL Sep 29, 2026
2265aa9
chore: resolve iss-2609290541525428 — RedactRefusal seals a word-glue…
REPPL Sep 29, 2026
ff10470
chore: resolve iss-2609290551363398 — ScanText finds a word-glued token
REPPL Sep 29, 2026
4d31718
fix(reading): list the local tier through the repository root in the …
REPPL Sep 29, 2026
e04f1aa
refactor(frontmatter): one reader strips a quoted scalar before decod…
REPPL Sep 29, 2026
e037d98
docs(reading): state the include table's one case rule
REPPL Sep 29, 2026
0e8ab1c
feat(lint): prose_citation_resolves reads the whole durable record
REPPL Sep 29, 2026
eb65d93
docs(record): index the optional config overrides and every root record
REPPL Sep 29, 2026
cdacf59
fix(docs-lint): the harness rules catch a host named in a path or an …
REPPL Sep 29, 2026
edaf963
docs: say the union merge driver holds for a local merge only
REPPL Sep 29, 2026
459a317
docs(brief): the meta chapter names maxAgentTokens as a staged key
REPPL Sep 29, 2026
b9ec0ca
chore: capture two guard gaps found while fixing the pending-document…
REPPL Sep 29, 2026
385193c
fix(guard): a substitution suspends the pending here-documents
REPPL Sep 29, 2026
d5091da
fix(agents): keep the agents readme and prompt-version log out of the…
REPPL Sep 29, 2026
1bedbe8
fix(guard): read an alternative at the first operator after a subscript
REPPL Sep 29, 2026
6fc6662
chore: defer two records to the product thinker's ruling
REPPL Sep 29, 2026
689a11a
chore: resolve iss-2609012043432648 — the status render lists the loc…
REPPL Sep 29, 2026
14d7740
chore: resolve iss-2608311039531552 — one reader strips a quoted scalar
REPPL Sep 29, 2026
a781c43
chore: resolve iss-2608311949421873 — the include table states its ca…
REPPL Sep 29, 2026
e448508
chore: resolve iss-2608271804497247 — prose citations are gated acros…
REPPL Sep 29, 2026
d527574
chore: resolve iss-2608271804499169 — the optional config overrides a…
REPPL Sep 29, 2026
e0eda4a
chore: resolve iss-2608271711539855 — the harness rules reach paths a…
REPPL Sep 29, 2026
c4ef530
chore: resolve iss-2609240646538011 — the union driver is documented …
REPPL Sep 29, 2026
4fa5eb2
chore: resolve iss-2608221254566264 — maxAgentTokens reads as the sta…
REPPL Sep 29, 2026
1cdc3e3
chore: resolve iss-110 — agents/ holds prompts only
REPPL Sep 29, 2026
f37eadb
docs(record): follow a resolved record's link from itd-198
REPPL Sep 29, 2026
71846b6
test(lint): the scribe contract case runs the shipped agent_contract …
REPPL Sep 29, 2026
4e991de
chore: capture the agent_contract default log path inside agents/
REPPL Sep 29, 2026
1418168
fix(guard): split an unquoted alternative's word, and drop what print…
REPPL Sep 29, 2026
a797dfa
fix(guard): read a root or home operand with its redundant separators…
REPPL Sep 29, 2026
ecb96b0
docs(guard): state where a pending body begins, the split alternative…
REPPL Sep 29, 2026
e7776f7
chore: restate two guard resolutions to what the shells read
REPPL Sep 29, 2026
4c7dec2
chore: resolve iss-2609290625381759 — a document a substitution never…
REPPL Sep 29, 2026
638f8a4
chore: resolve iss-2609290625482831 — root and home operands with red…
REPPL Sep 29, 2026
9eb42ff
fix(guard): carry a closed-over here-document without copying the pen…
REPPL Sep 29, 2026
a63baa1
chore: capture two guarded home reads that vet less than they read
REPPL Sep 29, 2026
9eb5ad2
fix(statusline): read the setting through the canonical home-declarat…
REPPL Sep 29, 2026
57410aa
fix(fsutil): refuse a home declaration in a directory another account…
REPPL Sep 29, 2026
a306308
test(evals): smoke the record-writing verbs against a scratch repository
REPPL Sep 29, 2026
fdc29ce
chore: resolve iss-2608231120121681 — the smoke lane runs the write-p…
REPPL Sep 29, 2026
44c41d1
chore: capture whether a group-writable ~/.abcd should be refused
REPPL Sep 29, 2026
b8bf8d2
chore: resolve iss-2609290656491358 — the status-line setting reads t…
REPPL Sep 29, 2026
10c9511
chore: resolve iss-2609290656480443 — a home declaration's directorie…
REPPL Sep 29, 2026
62e4863
docs(principles): guidance carries its evidence and its purpose
REPPL Sep 29, 2026
34bef42
chore: resolve iss-2609100506256173 — the third-party guidance rule h…
REPPL Sep 29, 2026
78ea1d5
chore(issues): re-defer 23 lapsed majors past v0.11.1, each naming wh…
REPPL Sep 29, 2026
930fde1
docs(guard): state that a call through any other tool never reaches t…
REPPL Sep 29, 2026
f586b9d
chore: resolve iss-2609091955574760 — the guard's tool reach is stated
REPPL Sep 29, 2026
1e78a62
chore(record): re-defer eight lapsed major findings against v0.11.1
REPPL Sep 29, 2026
4dda0ae
docs(itd-5): the pre-flight's scope step drops the length tiebreak it…
REPPL Sep 29, 2026
99494b0
docs(spec): two closed specs stop stating tree facts their prose cann…
REPPL Sep 29, 2026
be5c7ff
docs(agents): state the scan-before-mutating rule by blast radius
REPPL Sep 29, 2026
c222821
docs(ingest): the two author-name conventions live on the ingest page
REPPL Sep 29, 2026
6fcc816
test(evals): run the write-path smoke's git init through gittest.Env
REPPL Sep 29, 2026
fd91a69
fix: every config-named repo path refuses the git directory, not only…
REPPL Sep 29, 2026
4010944
feat(record): the next move says the spec close is what ships the intent
REPPL Sep 29, 2026
b013569
chore: resolve iss-2608261437042674 — itd-5's scope steps agree with …
REPPL Sep 29, 2026
5674a3b
chore: resolve iss-2608310912206749 — two closed specs drop tree fact…
REPPL Sep 29, 2026
d8e6501
chore: resolve iss-2608230957104179 — the scan rule is stated by blas…
REPPL Sep 29, 2026
7d130b8
chore: resolve iss-2608210923438110 — the author-name conventions are…
REPPL Sep 29, 2026
b73fe22
chore: resolve iss-2608291814578333 — config validators refuse the gi…
REPPL Sep 29, 2026
5a0b0fc
chore: resolve iss-2609100508566033 — the next move says the close sh…
REPPL Sep 29, 2026
d733597
chore(issues): defer nine drain records past v0.11.1, each naming the…
REPPL Sep 29, 2026
34a1ee4
fix(bootstrap): a network refusal names the environment the script ig…
REPPL Sep 29, 2026
7d20047
chore: capture iss-2609290743362554 — the glued sweep skips the decod…
REPPL Sep 29, 2026
aa5ea01
fix(scanner): run the glued sweep over the decoded views too
REPPL Sep 29, 2026
a3b4fd2
docs(guard): a default after a subscript prints its word when X is unset
REPPL Sep 29, 2026
2cb5fff
chore: capture iss-2609290745243990 — a parent segment after a direct…
REPPL Sep 29, 2026
0d3156d
fix(scanner): report a glued sweep that cannot be built whole as degr…
REPPL Sep 29, 2026
c811c7d
fix(guard): fold a parent segment where the target begins at the root…
REPPL Sep 29, 2026
1cff600
chore: resolve iss-2609290745243990 — a parent segment after a direct…
REPPL Sep 29, 2026
0b34f44
chore: resolve iss-2609290743362554 — the glued sweep reads the decod…
REPPL Sep 29, 2026
72f725b
test(guard): hold the parent-segment fold to linear work
REPPL Sep 29, 2026
4e8cbd3
fix(guard): read a folded segment by its marks, not a backtick scan
REPPL Sep 29, 2026
399fede
docs(brief): the dispatcher chapter names the close without quoting i…
REPPL Sep 29, 2026
489d970
merge: land fix/guarded-read-parent-vet (fsVet, 10c9511a2)
REPPL Sep 29, 2026
de6dbe2
merge: land fix/drain-observations (drainObs, 4e991de51)
REPPL Sep 29, 2026
d6e4e4b
merge: land fix/triage-major-a (triageMajorA, 1e78a62fd)
REPPL Sep 29, 2026
d1e004e
merge: land fix/triage-major-b (triageMajorB, 6fcc816cd)
REPPL Sep 29, 2026
8ff6e84
docs(intent): record the fidelity audit of itd-2609221017023290
REPPL Sep 29, 2026
efda71e
merge: bring main (#747) into the integration branch
REPPL Sep 29, 2026
0925be5
merge: land fix/drain-echo-4 (drainEcho4, 0b34f445f)
REPPL Sep 29, 2026
63e370f
merge: land chore/audit-credential-store (audits12, 8ff6e8457)
REPPL Sep 29, 2026
56f2cf2
merge: land fix/drain-rest (drainRest, 399fededd)
REPPL Sep 29, 2026
8f627c0
merge: land fix/guard-home-residuals (guardResid, 4e8cbd387)
REPPL Sep 29, 2026
8fdf0d0
docs(decisions): record the ceiling of five sub-agents from 2026-09-29
REPPL Sep 29, 2026
27ffce7
chore: recalibrate the reading windows at the integration tip
REPPL Sep 29, 2026
d2485be
chore: capture iss-2609291157309818 — the home declaration read still…
REPPL Sep 29, 2026
ecd41fd
fix(fsutil): re-judge a home declaration replaced between its vetting…
REPPL Sep 29, 2026
ce7dc04
chore: resolve iss-2609291157309818 — the home declaration read re-ju…
REPPL Sep 29, 2026
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
5 changes: 4 additions & 1 deletion .abcd/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ second home for the schemas:
|---|---|---|
| `config.json` | the ahoy surface (repo-scope config + `meta` setup block) | `development/brief/05-internals/03-configuration.md` |
| `rules.json` | the rules loader (per-repo domain overrides) | itd-3; `AGENTS.md` § abcd rule loader |
| `config/` | per-surface machine records (`identity.json`, `launch-payload.json`, `version-location.json`) | iss-62 / adr-28 / the version-location note |
| `config/` | per-surface machine records (`identity.json`, `launch-payload.json`, `version-location.json`, `artefact.json`, `reading-presets.json`) | iss-62 / adr-28 / the version-location note |
| `config/pii.json` (optional, absent here) | the redaction scanner's per-repo pattern override, read by every redacting write path and the privacy lint; absent, the bundled patterns apply | [`internal/README.md`](../internal/README.md) § `adapter/scanner/` |
| `config/scripts-closure.json` (optional, absent here) | the pinned `scripts/` runtime closure the launch payload scopes that include to; absent, `scripts/` is included like any other path | `internal/core/launch/includes.go` (`defaultClosureFn`); no chapter states its schema |
| `positioning.json` | the identity surface | `development/brief/04-surfaces/19-identity.md` |
| `site.json`, `site-baseline.json` | the site renderer and its ratchet | the site surface chapter |
| `docs-lint.json`, `record-lint.json` | the docs and record gates | the lint surface chapter |
| `citations-baseline.json` | the citation-health baseline | the docs `cite` surface |
| `prose-citations-baseline.json` | record-lint's `prose_citation_resolves` baseline (the unresolvable ids the record has ruled on) | `development/brief/05-internals/06-lint.md` |
16 changes: 8 additions & 8 deletions .abcd/config/reading-presets.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@
"test"
],
"window": {
"tokens_est": 1370000,
"measured_tokens_est": 1346832,
"measured_bytes": 5185304,
"measured_at": "a887092f79d847680e09a6f0a7a447bfb6f01749"
"tokens_est": 1380000,
"measured_tokens_est": 1358172,
"measured_bytes": 5228966,
"measured_at": "8fdf0d0330d3a15efc65ee3ad4f4c76cbc6f35df"
}
},
"entailment": {
Expand Down Expand Up @@ -216,10 +216,10 @@
"test"
],
"window": {
"tokens_est": 1380000,
"measured_tokens_est": 1358267,
"measured_bytes": 5229331,
"measured_at": "24e78506b9e7d4471d9c9110d6217e6e5f2c4b88"
"tokens_est": 1390000,
"measured_tokens_est": 1367208,
"measured_bytes": 5263754,
"measured_at": "8fdf0d0330d3a15efc65ee3ad4f4c76cbc6f35df"
}
}
}
Expand Down
1 change: 1 addition & 0 deletions .abcd/development/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ artefact type**, one canonical home per concept:
| [`brief/`](brief) | The living canvas: what abcd IS (product … delivery) + the [glossary](brief/glossary). |
| [`intents/`](intents) | Press-release intents — the WHY of each user-facing change. Lifecycle by directory: `disciplines/` `drafts/` `planned/` `shipped/` `superseded/`. |
| [`specs/`](specs) | Specs (`spc-N`) — the HOW derived from an intent. Lifecycle by directory: `open/` `closed/`. |
| [`agents/`](agents) | The agent prompts' operator statement and their prompt-version log; the prompts themselves are the repository's top-level `agents/`, which a harness loads whole (iss-110). |
| [`principles/`](principles) | Distilled cross-cutting design principles (first-class — the lifeboat packs these). |
| [`decisions/`](decisions) | ADRs (MADR) — ratified architecture decisions, one canonical home; plus `notes/`. |
| [`roadmap/`](roadmap) | Sequencing: `phases/` + `rfcs/` (an accepted RFC produces an ADR). |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Agent prompt changelog

Per [itd-5](../.abcd/development/intents/disciplines/itd-5-prompt-quality-additions.md),
Per [itd-5](../intents/disciplines/itd-5-prompt-quality-additions.md),
every `agents/*.md` prompt carries a `prompt_version` and a corresponding entry
here recording the bump rationale (and, at `1.0.0` lock, the self-improvement
pre-flight outcome and calibration-corpus delta).
Expand Down
40 changes: 25 additions & 15 deletions agents/README.md → .abcd/development/agents/README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
# Agents

Host-delegated agent prompt definitions. Each `*.md` file here is a **prompt**, not
code: abcd's core does the deterministic work and hands the prompt to the host's
Host-delegated agent prompt definitions live in the repository's top-level
[`agents/`](../../../agents/). Each `*.md` file there is a **prompt**, not code:
abcd's core does the deterministic work and hands the prompt to the host's
subagent dispatch, which owns model choice, credentials, and execution and returns
a structured result the core consumes (adr-25, host-delegated by default). The Go
side never executes these prompts.

## What lives here
This page and the prompt-version log beside it live here, in the durable record,
rather than in `agents/`: the harness registers every markdown file at the top of
that directory as an agent, with no frontmatter requirement and no name
exemption, so a readme or a changelog kept there is a spurious agent on every
installed surface (iss-110). `TestPluginAgentSurfaceRegistersOnlyAgents` holds the
directory to prompts alone.

- `*.md` — one agent prompt per file, carrying itd-5 frontmatter (below).
- `<name>/fixtures/` — per-agent fixtures. Every agent that reads untrusted input
carries at least one `injection-canary.json`.
- `CHANGELOG.md` — one entry per agent per version bump (itd-5).
## What lives where

The layout is flat. A markdown file anywhere below the top level, outside a
`fixtures/` directory, is a misfiled prompt, and record-lint's `agent_contract`
rule refuses it rather than skipping it.
- `agents/*.md` — one agent prompt per file, carrying itd-5 frontmatter (below).
- `agents/<name>/fixtures/` — per-agent fixtures. Every agent that reads untrusted
input carries at least one `injection-canary.json`.
- [`CHANGELOG.md`](CHANGELOG.md), beside this page — one entry per agent per
version bump (itd-5).

The prompt layout is flat. A markdown file anywhere below the top level of
`agents/`, outside a `fixtures/` directory, is a misfiled prompt, and
record-lint's `agent_contract` rule refuses it rather than skipping it.

The four M6 synthesis agents (itd-88) — dispatched by the `/abcd:disembark`
orchestration sections:
Expand All @@ -34,7 +43,7 @@ the delegated path.

## The itd-5 contract

Every agent prompt here conforms to [itd-5](../.abcd/development/intents/disciplines/itd-5-prompt-quality-additions.md),
Every agent prompt in `agents/` conforms to [itd-5](../intents/disciplines/itd-5-prompt-quality-additions.md),
the prompt-quality discipline, and record-lint's `agent_contract` rule enforces it
(itd-151). The frontmatter fields:

Expand All @@ -53,7 +62,7 @@ the prompt-quality discipline, and record-lint's `agent_contract` rule enforces
- **`capability_scope`** — an object `{ task_classes: [...], designed_for: "..." }`.
`task_classes` is a **YAML inline list** (a block list of `- token` items would
trip the future PQ005) of tokens drawn from the closed enum in
[`02-constraints/04-naming.md`](../.abcd/development/brief/02-constraints/04-naming.md)
[`02-constraints/04-naming.md`](../brief/02-constraints/04-naming.md)
(`oracle_review`, `intent_audit`, `spec_planning`, `code_rescue`,
`principle_distillation`, `lifeboat_packing`, `audit`, `lint`, `surface_render`,
`cross_document_audit`, `cold_reading`). `designed_for` is a free-text one-liner for human readers
Expand Down Expand Up @@ -92,9 +101,10 @@ nothing resolvable.

`agents/` is outside both the record-lint roots (`.abcd/development`) and the
docs-lint roots (`docs`, `README.md`), so the per-file record and docs rules do not
reach these files. The itd-5 contract is enforced instead by record-lint's
dedicated `agent_contract` rule, which walks this tree directly (`agents_dir` in
`.abcd/record-lint.json`) and holds each prompt to three things:
reach the prompts. The itd-5 contract is enforced instead by record-lint's
dedicated `agent_contract` rule, which walks that tree directly (`agents_dir` in
`.abcd/record-lint.json`, with `changelog` naming the log beside this page) and
holds each prompt to three things:

1. **The trust-contract frontmatter.** Every prompt declares `prompt_version` (a
semver) and `reads_untrusted_input` — the declaration is required of ALL of
Expand Down
2 changes: 1 addition & 1 deletion .abcd/development/brief/00-meta.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The brief is split across numbered folders rather than a single `README.md`. Rea

1. **Concurrent editing** — multiple agents can work on different sections without serialising on one file.
2. **Diff legibility** — `git log brief/04-surfaces/02-disembark.md` tracks the evolution of one command's design, not a whole-brief blob.
3. **Agent context budget** — agents that need only one section can pull just that file (relevant to the [`05-internals/03-configuration.md`](05-internals/03-configuration.md) `maxAgentTokens` budget).
3. **Agent context budget** — agents that need only one section can pull just that file (relevant to the `disembark.maxAgentTokens` budget, a staged key in [`05-internals/03-configuration.md`](05-internals/03-configuration.md) that no shipped code reads).
4. **Reusable shape** — the same numbered-folder layout serves as a template for future projects (the lifeboat output shape mirrors this skeleton, see [`04-surfaces/02-disembark.md § 5`](04-surfaces/02-disembark.md#5-output-shape)).

## Naming convention
Expand Down
4 changes: 3 additions & 1 deletion .abcd/development/brief/04-surfaces/08-abcd.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ itd-121). For a shipped intent the move is its fidelity-review state, read by
the intent store's one reader of the review marker (itd-2609150819445595): an
owed review names its receipt and the re-emit command; a shipped intent with no
marker owes one too, and the re-emit mints its receipt; a dead-lettered review
is reported unreviewed with its reason; an ingested one leaves nothing to do. A
is reported unreviewed with its reason; an ingested one leaves nothing to do.
For a ready planned intent, and for its open spec, the move is closing the spec,
and it says that the close ships the intent when no open spec still names it. A
positional on the namespace root is not a `show` sub-verb, so the form stays
inside the naming discipline. For an issue id it also names the checkout and
branch whose ledger it read, as every ledger verb does: a stderr line in the
Expand Down
58 changes: 54 additions & 4 deletions .abcd/development/brief/04-surfaces/17-guard.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,17 @@ than folded into either extreme. The three states — clean, repo layer dropped,
no registry at all — are decided once, in the core, and every caller formats
the same answer.

One limit is not among those states, because it is never false: the guard's
reach. The manifest's pre-tool-use matcher hands the hook the shell tool and
the question tool and nothing else, so a call through any other tool never
reaches the guard — a file the host's own tools write or edit, a command a tool
from another extension runs — and nothing warns about it, since nothing
failed. It is the guard's standing scope, not a degradation, and the `guard:`
line does not report it. Whether the guard should adjudicate more than the
shell is a separate question with a real cost: every further tool class needs
its own hazard vocabulary, and a guard that refuses a tool it cannot reason
about is worse than one that says plainly what it covers.

The two callers part company on exactly that file, deliberately. **On the hook,
the session keeps its protection:** the repo's overrides are dropped with a
notice on stderr, the bundled hazards still decide, and a hazardous command is
Expand Down Expand Up @@ -241,7 +252,12 @@ bare interpreter inside a string, because a variable is how ordinary commands
carry a program or a path between commands. A here-document body is data, but the substitutions the shell
runs in a body whose delimiter is unquoted are read as commands, and such a body
is read by the lines bash compares with its delimiter, joined across a trailing
odd run of backslashes. A backtick's text is read after bash's own pass over
odd run of backslashes. A body begins on the line after the one that opened
it, and a command or process substitution still open at that line's end holds
it back: the substitution's own lines run as commands, and the body begins on
the line after it closes. A document a substitution opens and never reads is
pending after the close in bash 5 and dropped in bash 3.2, which runs the
lines it would cover, so that line is refused as an unterminated document. A backtick's text is read after bash's own pass over
it, which drops a backslash before `$`, a backtick or a backslash (and, directly
inside double quotes, a `"`), so an escaped substitution between backticks is
read as the one bash runs. A payload that is wholly a substitution printing a
Expand Down Expand Up @@ -296,8 +312,34 @@ in or the one above it (`*`, `*/`, `.`, `..`, `./*`, `./*/`, `../*`, `.*`,
`git clean`, because that directory is usually the repository and emptying a
build directory the same way is ordinary work. Chained after a `cd` any
recursive forced delete blocks, as above. The target is compared as written,
before the shell expands it, so `$HOME` and `$PWD` are seen as those words
although no other parameter expansion is.
before the shell expands it, so `$HOME` and `$PWD` are seen as those words. It
is first read the way bash reads its text: a backslash-newline inside a name
is dropped (`$HO\⏎ME` is `$HOME`); each word a brace group makes keeps the
variables its text holds, and a name runs on into the letters a list or a
sequence places after it (`{$HOME,x}`, `$HOME/{.*,}`, `$HO{ME,}`,
`$HO{M..M}E`); an expansion whose operator can leave the value as it is reads
as the variable itself — a default, an assignment or an error message
(`${HOME:-x}`), a trim or a pattern replacement (`${HOME%/}`, `${HOME#x}`,
`${HOME/x/y}`), a substring, a case change, and a subscript read to its
matching `]` with any text after it (`${HOME[x[0]]}`, `${HOME[0]]}`, which the
bash 3.2 of macOS prints as the value); and an alternative, which prints its
word or nothing, reads as that word as written (`${X:+$HOME}`, `${X:+/}`,
`${X:+$HOME/*}`), including one the bash 3.2 of macOS reads at the first
operator after a subscript (`${X[0]]:+$HOME}`). Unquoted, the alternative's
word is split on whitespace and a substitution in it that prints nothing
drops out, as bash splits and drops them (`${X:+$HOME }`,
`${X:+$(true)$HOME}`). A trim that leaves the path above the home
(`${HOME%/*}`) blocks as the home does. Each target is also compared as a path
with its redundant separators taken out, since the kernel reads a run of
slashes as one, a `.` segment as the directory itself and the root as its own
parent (`//*`, `$HOME//`, `/./*`, `/../*`, `.//*`). A target that begins at
the root or the home has each `..` folded into the directory before it, as
the path reads lexically: `/tmp/../*` and `/tmp/x/../..` are the root, and a
`..` past the home climbs to a directory that holds the home, so `~/..`,
`~/../*` and `$HOME/../../*` read as the home and `~/../*/*` as `~/*`, while
`~/../x` stays a sibling. The kernel reads a `..` otherwise only after a
symlink, and the lexical reading is the one that blocks; a trailing `..` is
folded too, though rm refuses it.

What an allow still does not see is a hazard that never reaches command position
at all: a word that is wholly a command substitution or a variable standing
Expand All @@ -306,7 +348,15 @@ message or a branch name is spelled every day; a delete target printed whole by
substitution (`rm -rf $(echo /)`), which is read by its known text because that
is how an everyday delete names what it removes (`rm -rf $(find . -name
'*.pyc')`); a target spelled any other way than the words above (`rm -rf
"$DIR"/*` with `DIR` unset, `rm -rf /?*`); one behind a wrapper flag the per-wrapper
"$DIR"/*` with `DIR` unset, `rm -rf /?*`), a default's own word, which bash
prints only when the variable is unset (`rm -rf ${DIR:-$HOME}`, and
`${X[0]]-$HOME}`, which the bash 3.2 of macOS reads as a default after the
subscript), a `..` after a symlink, which is read past lexically (a link to
the root under a named directory), or after a segment holding a variable,
which is not folded (`/tmp/$X/../../*` is the root with `X` unset), a `..`
past the home followed by a glob other than `*` (`~/../?*`, as `/?*`), an
alternative nested more than three deep, and a substring of `$PWD` that
prints the root (`${PWD:0:1}`), which warns as `$PWD` does; one behind a wrapper flag the per-wrapper
table does not name; a REST
path an entry names by its root segment when the host serves that API under a
prefix; an IFS the shell already holds when the line starts, or gains during the line
Expand Down
4 changes: 2 additions & 2 deletions .abcd/development/brief/04-surfaces/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,8 @@ or removed without the same edit here fails the record gate.

**This documentation lives here rather than in `commands/README.md` because the
loader registers every markdown file under `commands/` as a slash command** — with
no frontmatter requirement and no name exemption, as `agents/README.md`
registering as an agent independently shows (iss-110). A readme beside the verbs
no frontmatter requirement and no name exemption, exactly as the agent loader
treats `agents/` (iss-110). A readme beside the verbs
is therefore a spurious `/abcd:README` on every installed surface (iss-160), and
the only reliable fix is a home outside the auto-discovery root.

Expand Down
7 changes: 4 additions & 3 deletions .abcd/development/brief/05-internals/05-prompt-quality.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ so the per-file rules do not reach it; this rule walks the tree directly from th
non-markdown files, and the README and changelog stems. It is configured as a
blocker, so it runs on every `make record-lint`, every `make preflight` and the CI
record gate. The operator-facing statement of the same contract is
[`agents/README.md`](../../../../agents/README.md).
[`agents/README.md`](../../agents/README.md) in the durable record.

What it enforces on every invocation:

Expand All @@ -45,7 +45,8 @@ What it enforces on every invocation:
- On the same prompt: `agents/<name>/fixtures/injection-canary.json`, present, a
regular file and non-empty. An empty file or a symlink is refused, because a
canary that asserts nothing reports the contract met without testing it.
- A `### <agent> <version>` entry in `agents/CHANGELOG.md` for every prompt's
- A `### <agent> <version>` entry in the prompt-version log,
[`agents/CHANGELOG.md`](../../agents/CHANGELOG.md) in the durable record, for every prompt's
current version. This half needs no git, so a new prompt with no entry and a
bumped version with no entry both fail.

Expand Down Expand Up @@ -97,7 +98,7 @@ gated on the research files besides, which do not exist for any shipped agent.
## The itd-5 additions

- **`prompt_version` frontmatter (ships).** Every prompt carries a semver, and
`agents/CHANGELOG.md` records each bump with a one-line rationale. A new prompt
The prompt-version log (`.abcd/development/agents/CHANGELOG.md`) records each bump with a one-line rationale. A new prompt
normally starts at `0.1.0`; the four review and research prompts enter the
changelog at `0.2.0` instead, the bump that first gave them the untrusted-input
contract. Bump rules, semver-adapted: MAJOR for a behaviour-breaking output
Expand Down
Loading
Loading