Commit 0da7cd2
refactor(spec)!: strip internal tracker ids from the three customer-facing text populations, and widen check-doc-authoring Rule 3 to hold them (#13019)
* chore(gates): widen check-doc-authoring Rule 3 to the three adjacent spec text populations
Rule 3 held the zod `message:` population alone and named three neighbouring
ones as deliberately out of scope pending a ruling. That ruling arrived as
ruling-inheritance rather than a new decision: the founding rationale is "the
ban follows the audience, not the file type", and it transfers unchanged to
- strictObject unknown-key error-map options (surface/history/aliases/
guidance/guidanceSets/retiredForms) — printed verbatim at the refusing
author, same audience and same moment as a refusal message;
- retiredKey() tombstone prescriptions — the prescription IS the parse error;
- .describe() prose — projects into content/docs/references/** and the
generated skill artifacts.
ADR ids and migration commands are KEPT: AGENTS.md positively requires a
tombstone to carry a durable reference, and an ADR id is customer-resolvable
where #NNNN is not. No exemption mechanism is added; the rule stays
exemption-free by design, exactly as its own header prescribed.
Positions alone were not enough. The guidance maps — and a share of the refusal
messages — are hoisted into named consts and referenced from the sink, so a
matcher reading only a literal's own position stops at the VariableDeclaration.
collectTextSinkConsts() closes that with a per-file sink-alias fixed point. It
is not a hypothetical about the new buckets: the hoisted spelling was hiding
five ids from the `message:` rule itself, which had reported that population
clean since the day it landed.
The `seen` floor is now PER BUCKET rather than on the total, for the same
reason #4932's floor is per-ROOT: .describe() alone would hold a total positive
forever while the guidance matcher rotted unseen.
Measured on this base: green before the widening (535 message strings, 0
violations), red after it with 584 violations — strictObject 262, describe 187,
tombstone 130, message 5.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
* refactor(spec)!: strip internal tracker ids from customer-facing spec text — mechanical pass
479 of the 584 literals the widened Rule 3 reports, across 84 files. Driven by
the gate's own violation list, so the edited ranges are exactly the ruled
population; every edit is inside a string literal, none touches code.
The rules, in the order they fire:
197 a parenthetical whose whole content is ids — it goes with them
166 a parenthetical carrying ids beside customer-resolvable content — the
ids go, an ADR id / protocol version / phrase stays, and a fragment
left holding an open connective ("widened by") is dropped whole rather
than stranded
110 the `history:` idiom — "Until #N [批 NN] closed this shape" states the
closure as a fact instead of citing the work that performed it
15 bare-prose idioms, each deleting the governing preposition with the id;
a stranded `since` is a worse sentence than the citation was
ADR ids, protocol versions, error codes and migration commands are kept
throughout — they are the durable references AGENTS.md requires, and they are
customer-resolvable where #NNNN is not. 485 insertions / 485 deletions: the
line count is unchanged because nothing but literal text moved.
The remaining 105 need sentence repair rather than excision and are hand-edited
in the following commit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
* refactor(spec)!: strip the remaining tracker ids — hand-repaired sentences
The 105 sites the mechanical rules could not take without rewriting the
sentence around them, across 37 files. Two further mechanical clusters were
folded into the rule set first (a parenthetical whose ids sit at the end of one
concatenated operand while its content continues in the next; a `.describe()`
opening with a bracketed `[#N]` tag), leaving 50 read and repaired one by one.
Each repair states in words what the id used to point at — "the gap this key
exists to close", "the console release that restores this flag", "the same
silent-drop bug one level down" — rather than deleting the clause and leaving a
sentence that no longer says anything. ADR ids, protocol versions, error codes
and `os migrate` commands are untouched throughout.
Verified beyond the gate, because an excision from mid-parenthetical can take
the closing bracket with it and still parse: every concatenated string
expression in all 88 touched files was compared against the branch base for
bracket balance — 11,065 expressions, balance unchanged on every one. That
check caught one real defect (a dropped `)` in `protocol.zod.ts`) that reads
almost right and compiles fine.
`check:doc-authoring` is now GREEN on the widened rule: 13,306 customer-facing
strings across 670 spec sources, 0 violations, with every bucket populated
(message 778 · strictObject 3282 · tombstone 751 · describe 8495) so the
per-bucket blindness floor is satisfied rather than merely unbreached.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
* test(spec): move the sentence pins with the strings they pin, and add negative pins
12 spec test files asserted on wording this PR reworded. Each pin now asserts
the NEW sentence rather than being deleted — `toContain('#3810')` becomes
`toContain('match-everything write')`, `toContain('#5058')` becomes
`toContain('open gap')` — so the pin still holds the fact it was written to
hold. Nine were moved mechanically and verified against the post-strip message
text (the old fragment must be gone from the corpus and the proposed new one
must actually occur in it); the remaining pins asserted only "the message
carries id #N", which has no replacement substring, and were re-pointed by hand
at the surviving clause.
Where a pin existed to hold a tracker id, it is replaced by the NEGATIVE pin
the gate's own failure text prescribes: the message must not match `#\d{3,5}`.
That keeps the assertion load-bearing instead of trivially true — a pin merely
deleted would let the id return.
Also adds the changeset: `@objectstack/spec` patch, FROM -> TO at bucket level.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
* chore(spec): regenerate content/docs/references after the .describe() strip
The `.describe()` bucket projects into the generated reference docs, so the
strip lands there too: 64 files, 772 insertions / 772 deletions, line for line.
Regenerated with `check:generated --fix` on the committed merge (never in MERGE
state, where `gen:schema` would roll the authorable-surface anchor back to the
old fork point) and narrowed to the one artifact the check proved stale.
Verified: every regenerated path is under `content/docs/references/`,
`content/docs/releases/` is untouched, and no `+` line in the diff carries a
tracker id.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
* test(spec): repoint the remaining assertion pins off the stripped ids
The first pin pass moved the pins whose expected text still existed in the
post-strip sources. This one covers the rest, found by running the suite rather
than by pattern-matching: 92 tests across 40 files were asserting on wording
this PR reworded.
Scope was held narrow in two directions, deliberately:
- only ids this branch actually REMOVED from non-test spec sources, read out
of the diff rather than guessed — a pin on an id that still exists must
keep working, and silently weakening it would be worse than leaving it;
- only literals in an ASSERTION ARGUMENT. Test TITLES and COMMENTS keep their
ids on purpose: the gate excludes test bodies because that reader HAS the
tracker, and the ban follows the audience. An earlier line-based attempt
would have stripped 482 literals across 134 files, most of them titles.
Three shapes of repair:
- an id used as a DISCRIMINATOR between sibling refusals — `driver-credential-
refusal.test.ts` filtered issues with `message.includes('#9041')` vs
`('#9147')` — now discriminates on the remedy clause that actually differs
("the URL's own userinfo" vs "add `username` to `config`"). That helper is
why ten tests there read as "the refusal did not fire": it fired, and the
filter could not see it.
- an id that was one term of a larger expected string or regex — the id term
is dropped, the rest of the pin stands.
- an id that was the WHOLE expected value — repointed at a distinctive
surviving phrase of the same message, or, where a sibling assertion already
covers that, replaced by the negative pin the gate's own failure text
prescribes (`.not.toMatch(/#\d{3,5}/)`), so the pin stays load-bearing.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
* test(spec): finish moving the pins, and undo the ones that were never stale
Iterated against the suite rather than against a pattern: 92 -> 46 -> 13 -> 4 -> 0.
Two corrections worth recording, because both produced confidently wrong states
that still read as progress.
**Reverted the pins that were never stale.** A bulk phrase swap repointed pins
whose ids are still in the sources — in populations OUTSIDE the four ruled
buckets: conversion-registry summaries, migration entries, TSDoc, and refusal
prose built inside `error: () =>` callbacks (filed as a separate finding). Those
tests were passing; the swap broke them. Ten sites are restored to the id they
legitimately still assert. The rule the reverts encode: a pin may only lose an
id this branch actually removed FROM THAT MESSAGE, which is narrower than "an id
this branch removed somewhere".
**Restored a regex the repair had eaten.** The regex cleaner stripped `\(\)`
to tidy emptied groups and took the literal `` `find\(\)` `` in
`driver.test.ts` with it. That failure was briefly, and wrongly, diagnosed as
pre-existing on main — the phrase really was absent from every revision,
because the mangled regex was what was being compared. The evidence that settled
it was `git diff` against the branch base, not a grep for the phrase.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
* test(spec): pin the area-gate refusal on its enforcement clause
The last stale pin. `#4722` on the `areas[].requiredPermissions` tombstone was
first repointed at a phrase from the SIBLING `visible` guidance, which is a
different message on the same surface — it matched neither. It now pins
"re-checked in the shell", the clause that states how the gate is actually
enforced, which is what the citation stood in for.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
* chore(spec): regenerate references after merging main (discharges the merge deferral)
`origin/main` moved 21 commits during the run. One conflict, in
`packages/spec/src/ui/view.zod.ts` — the cross-wave file declared at claim time:
main rewrote the `visibleWhen` describe to document `current_user` resolution,
this branch had stripped two ids from the older sentence. Resolved by taking
main's newer prose whole and applying this branch's strip to it, so neither the
new content nor the convention is lost. Asserted mechanically before staging:
no tracker id survives in the resolved line.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
* fix(spec): repo-wide consumer-pin sweep + repair the strip's cross-operand scars
CI was red on Test Core with 8 failures in @objectstack/metadata. Cause: the
pin iteration ran against the spec suite only, and packages OUTSIDE spec pin
spec messages too. This round sweeps every tracked test file in every package
and repairs two defect classes the spec-only pass could not see.
**Stale consumer pins (4 sites, 4 packages).** Same narrow rule as before — a
pin may only lose an id this branch removed FROM THAT MESSAGE:
- metadata/plugin-artifact-forward-conversion: `…17 (#12497, ADR-0049)` ->
`…17 (ADR-0049)`; the surviving ADR id carries the pin.
- metadata/stored-envelope: `toContain('#5309')` had no replacement fragment,
so it becomes the negative pin the gate prescribes, beside the existing
`storage bookkeeping` assertion which stays the positive half.
- objectql/engine-unknown-option: two pins — a regex term `#8057, ADR-0049`
trimmed to `ADR-0049`, and `/#4286, ADR-0049/` likewise.
- service-automation/screen-nodes: `/#4343/` repointed at
`` /`script.config.actionType` was removed/ `` plus a negative id pin.
**Cross-operand scars in the prose itself (13 sites, 10 spec sources).** An
excision that spans two concatenated operands leaves a scar neither a
per-literal tidy nor `git diff` review can see, because each literal is
individually well-formed — it appears only once the `+` chain is joined, which
is exactly what the customer reads:
'… sees a body ' + '(#5309), so …' -> '… sees a body ' + ', so …'
reads as "a body , so"
12 were space-before-punctuation / double-space at an operand boundary, found
by a joined-chain scan and repaired by trimming the left operand. The 13th was
a stranded possessive: `RECORD_NOT_FOUND (#7867's not-found gate)` had become
`( 's not-found gate)`, now `(the by-id not-found gate)`.
Verified by running suites, since substring probes proved unreliable in BOTH
directions here — they missed objectql/#8057 and service-automation/#4343
(the id survives elsewhere in spec) and wrongly cleared metadata/#5309 (it
survives elsewhere in that package). Ten packages, 27,704 tests, all green:
spec 11675 · objectql 4268 · runtime 2898 · metadata-protocol 2010 · lint 2300 ·
plugin-auth 1695 · service-automation 1091 · core 1015 · metadata 674 ·
plugin-dev 58. All 14 spec artifacts regenerated and current.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LpRNHxWZgSUgVnFT9mQQo4
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 96c796c commit 0da7cd2
208 files changed
Lines changed: 2103 additions & 1605 deletions
File tree
- .changeset
- content/docs/references
- ai
- api
- automation
- data
- integration
- kernel
- security
- system
- ui
- packages
- metadata/src
- objectql/src
- services/service-automation/src/builtin
- spec/src
- ai
- api
- automation
- conversions
- data
- driver
- identity
- integration
- kernel
- migrations
- security
- studio
- system
- ui
- scripts
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
50 | 50 | | |
51 | 51 | | |
52 | 52 | | |
53 | | - | |
| 53 | + | |
54 | 54 | | |
55 | 55 | | |
56 | | - | |
57 | | - | |
| 56 | + | |
| 57 | + | |
58 | 58 | | |
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
62 | | - | |
63 | | - | |
64 | | - | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
65 | 65 | | |
66 | 66 | | |
67 | 67 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
36 | 36 | | |
37 | 37 | | |
38 | 38 | | |
39 | | - | |
| 39 | + | |
40 | 40 | | |
41 | | - | |
| 41 | + | |
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
26 | | - | |
| 26 | + | |
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| |||
33 | 33 | | |
34 | 34 | | |
35 | 35 | | |
36 | | - | |
| 36 | + | |
37 | 37 | | |
38 | 38 | | |
39 | 39 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
56 | | - | |
| 56 | + | |
57 | 57 | | |
58 | | - | |
| 58 | + | |
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
| |||
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
91 | | - | |
92 | | - | |
| 91 | + | |
| 92 | + | |
93 | 93 | | |
94 | 94 | | |
95 | 95 | | |
| |||
110 | 110 | | |
111 | 111 | | |
112 | 112 | | |
113 | | - | |
| 113 | + | |
114 | 114 | | |
115 | | - | |
| 115 | + | |
116 | 116 | | |
117 | 117 | | |
118 | 118 | | |
| |||
145 | 145 | | |
146 | 146 | | |
147 | 147 | | |
148 | | - | |
| 148 | + | |
149 | 149 | | |
150 | | - | |
| 150 | + | |
151 | 151 | | |
152 | 152 | | |
153 | 153 | | |
| |||
0 commit comments