Skip to content

test(spec): pin the solution-blueprint pointer row to its subject - #16994

Merged
zhuangjianguo merged 2 commits into
mainfrom
claude/issue-15263-pointer-row-pin
Sep 9, 2026
Merged

test(spec): pin the solution-blueprint pointer row to its subject#16994
zhuangjianguo merged 2 commits into
mainfrom
claude/issue-15263-pointer-row-pin

Conversation

@claude

@claude claude Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Refs #15263

Blocked-by: #16992 — must land AFTER it. Measured, not assumed: see "Landing order" below.

Clause-②: no
A test-only change. It adds no schema, no export, no accept set and no runtime path;
it asserts an existing published artifact's content. Nothing an author can write moves.

Split from #16992. The fix and its regeneration stay there. This pin was separated
because a change under packages/spec/scripts/ is a change to the generator that the
#11705 generated-artifact exception has to trust: carried alongside the regenerated
skills/** index, the recompute that certifies that index would be running the same
PR's own generator and could not certify it, so the whole PR would have needed a human
merge. Split, #16992 measures NOT governed and this PR measures NOT governed.

What this pins, and why a generator-only check cannot

The published skill-index row for ai/solution-blueprint.zod.ts is generated from the
module's own doc block, with Exports: … as the fallback when no block qualifies.
check:skill-refs and check:docs each compare an artifact against the generator that
wrote it, and the generator reproduces the header selector faithfully — so both stayed
green for the entire life of the defect #16992 fixes. Triage said it plainly:

⛔ 验收必须断言发布出来的那一行内容,而不是「生成器跑通了」。…生成器自己看不见这一类 —— 它们忠实地复现了选择器。

So this asserts the fact the artifact must state. Modelled on
packages/spec/scripts/query-pointer-row.test.ts, which #14441's fix used for the same
reason one file over.

Two legs that fail differently

leg what makes it red
SOURCE the separator between the module header and SNAKE_CASE goes away — reds immediately, no regeneration needed
CORPUS an index is regenerated from a file whose header no longer qualifies — reads checked-in bytes, so it is blind to a source-only regression and catches the published state instead

Ablation from the committed fix, deleting the one-line doc:

stage source legs corpus leg
source mutated, index not regenerated RED (2) green — reads checked-in bytes
index regenerated from the mutated source RED RED, row reverts byte-for-byte to the Exports: fallback

The mutation was proven on disk by blob hash before each run and the restore proven by an
empty git diff HEAD. A fourth leg ("finds the rows at all") is an anti-vacuity guard and
stayed green throughout — without it, "no bad row" would read as green when nothing parsed.

Landing order — this PR is red until #16992 lands

Measured on this branch, which is based on main where the fix has NOT landed:

× opens on the plan-first authoring sentence, not on `SNAKE_CASE`
× still documents `SNAKE_CASE` — the fix ADDS a symbol doc, it does not delete the header
✓ finds the rows at all
× reads the blueprint sentence on every one of them, never the `Exports:` fallback
  Tests  3 failed | 1 passed (4)

That is the pin correctly detecting the defect that is still on main — it is evidence the
pin is not vacuous, not a fault in this PR. It goes green the moment #16992 lands and this
branch takes that commit. ⛔ Do not land this first.

Cross-package declaration

The pin reads skills/*/references/_index.md, outside its own package, so it is declared in
packages/spec/vitest.repo-tests.json and runs under the repo project, whose hash moves
with what it actually reads. Left undeclared it would run under @objectstack/spec#test,
invisible to both the affected-subset filter and the turbo cache — green on every PR while
red on main, which is the one failure a pin like this exists to refuse.
pnpm check:cross-package-test-inputs caught exactly that and is now green.

Governed-surface verdict

node scripts/pm/check-governed-merges.mjs --test \
  packages/spec/scripts/solution-blueprint-header-row.test.ts \
  packages/spec/vitest.repo-tests.json

governed-surface predicate: 0 of 2 path(s) hit the register (5 surfaces, repo-agnostic).
  ✅  NOT governed — ordinary queue landing applies to a PR with exactly this file list.

exit 0.

Changeset — both halves, measured

Half 1: packages/spec's files[] is dist, json-schema, liveness, prompts,
llms.txt, README.md, src/**/*.zod.ts, CHANGELOG.md, api-surface,
spec-changes.json. Neither packages/spec/scripts/** nor a root vitest.repo-tests.json
is on it, so half 1 says no.

Half 2, measured on the deciding tree — npm pack --dry-run --json on the
@objectstack/spec tarball:

path shipped entries
scripts/solution-blueprint-header-row.test.ts 0
vitest.repo-tests.json 0
any scripts/ entry at all 0
positive control — src/**/*.zod.ts 206
discriminating control — root *.json that DO ship package.json, spec-changes.json

The last row is what makes this a measurement rather than an absence: a sibling root-level
.json is shipped by the same files[] mechanism, and this one is not. ⇒ nothing
published moves ⇒ skip-changeset, applied as a label rather than an empty changeset
(an empty-frontmatter changeset is a real input to changesets/action and an all-empty set
stalls the release silently and greenly).

Verification

  • pnpm check:cross-package-test-inputs ✓ · pnpm check:test-source-alias ✓ · pnpm check:nul-bytes ✓ · pnpm --filter @objectstack/spec check:scripts-typecheck ✓ · pnpm check:agent-test-spelling ✓ · pnpm check:type-check-coverage
  • The pin ran green on the branch that carries the fix: test:repo 28 files / 407 passed.
  • On this main-based branch it is 3 red / 1 green, exactly as the landing-order section shows.

Generated by Claude Code

The published skill-index row for `ai/solution-blueprint.zod.ts` is generated
from the module's own doc block, with an export list as the fallback when no
block qualifies. Neither generator can see the difference: `check:skill-refs`
and `check:docs` each compare an artifact against the generator that wrote it,
and the generator reproduces the header selector faithfully — so a
generator-only check passes on exactly the state where the row says nothing
about the file's subject. This pins the fact the artifact must state instead.

Two legs that fail differently. The SOURCE leg reds the moment the separator
between the module header and `SNAKE_CASE` goes away — no regeneration needed.
The CORPUS leg stays green through that, because it reads checked-in bytes, and
reds once an index is regenerated from a file whose header no longer qualifies.
Both directions measured by ablation.

The pin reads `skills/*/references/_index.md`, outside its own package, so it is
declared in `vitest.repo-tests.json` and runs under the `repo` project, whose
hash moves with what it actually reads.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016N6xmWt5hYm94ffVEwGH8x
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 9, 2026
@github-actions github-actions Bot added the size/m label Sep 9, 2026
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 1 changed file(s) yielded no anchor (packages/spec/vitest.repo-tests.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/spec/vitest.repo-tests.json) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 131 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json db769829f856f1947de53ac6eff0927ded75364fpackageMentionDocs.

@claude

claude Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

The red is the declared landing order, not a defect — and it is this pin working

domain:spec execution seat (PM), 2026-09-09T00:44Z. Recorded once so a reader of a red draft does not have to re-derive it; ⛔ no re-run spent, ⛔ nothing pushed.

Test Core (1/6) failed on 101955c017 with exactly three assertions:

FAIL scripts/solution-blueprint-header-row.test.ts
  > opens on the plan-first authoring sentence, not on `SNAKE_CASE`
  > still documents `SNAKE_CASE` — the fix ADDS a symbol doc, it does not delete the header
  > reads the blueprint sentence on every one of them, never the `Exports:` fallback

⭐ Those are the pin's own three legs, and they are the same three the ablation reddened when the fix was removed. This PR carries the pin without the fix — the fix is in #16992 — so on this base the published row is still the Exports: fallback and the pin correctly says so. ⇒ A green result here would have meant the pin does not work.

This is the Blocked-by: #16992 the PR body already declares, now observed rather than predicted.

What unblocks it

#16992 lands first. It is currently GOVERNEDskills/objectstack-ai/references/_index.md hits the register, and the #11705 generated-surface exception does not lift it while a packages/spec/scripts/** co-edit sits in the same PR, which is exactly why the work was split into these two. ⛔ No seat flips a governed PR ready, enqueues it, or arms auto-merge.

⇒ Once #16992 is on main, this PR is rebased/re-run and its three legs should go green against the corrected row. ⛔ Until then this red is expected and ⛔ must not be "fixed" by weakening the pin.


Generated by Claude Code

@claude

claude Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

Correction to my 00:44Z comment — #16992 is no longer governed

domain:spec execution seat (PM), 2026-09-09T00:52Z. One line of that comment has gone false and it changes what a reader should expect, so it is corrected rather than left standing.

I wrote:

#16992 lands first. It is currently GOVERNED … ⛔ No seat flips a governed PR ready, enqueues it, or arms auto-merge.

That was true when written and is not true now. The split it described has since completed: the packages/spec/scripts/** co-edit moved onto this PR, which is what was blocking the #11705 exception. Re-run by this seat on GitHub's final file list for #16992, with node_modules present:

governed-surface predicate: 0 of 4 path(s) hit the register after 1 generated-artifact lift(s)
✅ NOT governed — ordinary queue landing applies
ℹ️ #11705: skills/objectstack-ai/references/_index.md is a PURE REGENERATION —
   byte-equal to `pnpm --filter @objectstack/spec gen:skill-refs` recomputed on THIS tree

#16992 needs no maintainer merge. It lands through the ordinary queue as soon as its checks close green, and this PR follows it. ⛔ Nobody should be waiting on a human for it.

Everything else in that comment stands unchanged: this PR's three red legs are the pin correctly reading a main that still carries the Exports: fallback, Blocked-by: #16992 is real, and ⛔ the red must not be cleared by weakening the pin.


Generated by Claude Code

Copy link
Copy Markdown
Collaborator

Blocked-by: #16992 is cleared — the branch has been updated to take the fix

domain:spec execution seat, 2026-09-09T01:19Z.

#16992 merged at 2026-09-09T01:17:37Z, merge commit db769829f, now main's tip.

The corrected row is on main — verified by content, not by "the generator ran"

That distinction is this PR's whole reason for existing, so the unblock is measured the same way:

git show origin/main:skills/objectstack-ai/references/_index.md
  "Solution Blueprint Schema (ADR-0033"                              →  1
  "BlueprintConditionSchema, BlueprintSummaryOperationsSchema"       →  0   (the Exports: fallback is gone)
  firing control — total `node_modules/...` rows in the index        →  17

The control fires, so the 0 is a reading rather than an unread file.

What was done, and what was deliberately not

update_pull_request_branch — a merge of main into this head. ⛔ No rebase, ⛔ no amend, ⛔ no force-push: anyone holding a checkout of claude/issue-15263-pointer-row-pin keeps it valid.

The pin was not touched. Its three red legs were the correct reading of a main that still carried the Exports: fallback — that redness was the evidence the pin is not vacuous, and weakening it to reach green would have destroyed the only thing this PR contributes. It goes green because the world changed, not because the assertion did.

Standing state

The prior instruction in the PR body — "⛔ Do not land this first" — is now spent, not overridden: #16992 is on main and this PR builds on it.

⛔ Still draft. Landing waits on all three limbs, checked in this order and none skipped:

  1. in-seat review of the diff at the new head;
  2. check-clause2-carriers --pair 16994 exit 0;
  3. every check completed and success/skipped, aggregated by name — ⛔ not the required subset, ⛔ not the rollup.

⚠️ Limb 3 is the one to watch here, because it is the limb that changes meaning: the four legs must now read 4 passed, and specifically the three that were red must be red for no reason at all rather than red for a new one. A green that arrives with the anti-vacuity leg (finds the rows at all) having gone green-by-emptiness is not a pass — that leg exists so "no bad row" cannot read as green when nothing parsed.


Generated by Claude Code

@zhuangjianguo
zhuangjianguo marked this pull request as ready for review September 9, 2026 01:41

Copy link
Copy Markdown
Collaborator

✅ Landing — all three limbs verified at head 23fbde9df

domain:spec seat (收班后留守), 2026-09-09T01:41Z. Undrafted and auto-merge armed 01:41:35Z.

⭐ The decisive reading — the pin's legs, from the job log rather than the check conclusion

This is the reading the previous comment said would decide it, so it is quoted whole rather than summarised. From Test Core (1/6), job 102300727427, ANSI stripped:

@objectstack/spec:test:repo:  ✓  repo  scripts/solution-blueprint-header-row.test.ts (4 tests) 28ms
@objectstack/spec:test:repo:  Test Files  28 passed (28)
@objectstack/spec:test:repo:       Tests  407 passed (407)

4 tests, all passing — matching the four legs one-for-one, so none was skipped or silently dropped. Zero failure lines anywhere in the repo project (control: 88 log lines carry the spec:test:repo: prefix, so that zero is a reading). ⭐ 28 files / 407 tests reproduces exactly the figure this PR's body recorded when the pin was run on the branch that already carried the fix.

⚠️ Stated precisely, because it is not what I said I would read. I said I would read the four leg names. Vitest's reporter prints per-test names only on failure, so the log gives the count and the pass mark, not the names. What rules out the green-by-emptiness case is not the names but the construction: the anti-vacuity leg fails when nothing parses — that is its entire job — so its passing is the evidence that rows were found, and the remaining legs then say every found row reads the blueprint sentence. ⇒ the conclusion holds, by a slightly different route than advertised, and the difference is on the record rather than glossed.

Limb ① — in-seat review at the new head

The true diff, taken three-dot (see #17003, filed today, on exactly the trap of taking it two-dot on a branch that has merged main in):

git diff --stat origin/main...23fbde9df
  packages/spec/scripts/solution-blueprint-header-row.test.ts | 116 +++++++++
  packages/spec/vitest.repo-tests.json                        |   1 +
  2 files changed, 117 insertions(+)

⚠️ The two-dot form would have listed the whole of main's progress since bb7d91f19 as this PR's file list. It is 2 files.

node scripts/pm/check-governed-merges.mjs --test \
  packages/spec/scripts/solution-blueprint-header-row.test.ts \
  packages/spec/vitest.repo-tests.json
  → 0 of 2 path(s) hit the register · ✅ NOT governed · exit 0

db769829f (the #16992 fix) confirmed an ancestor of the head, and the row now on main is byte-for-byte what the pin asserts:

solution-blueprint.zod.ts` — Solution Blueprint Schema (ADR-0033 §4 — plan-first authoring)

Limb ② — --pair

✓ check-clause2-carriers: PR #16994 / card #15263 — the clause-② declaration is readable in the
  fixed spelling and both carriers agree, and its diff carries no widening tell.
exit=0

Limb ③ — checks by name

34 check runs, aggregated by name (⛔ not the required subset, ⛔ not the rollup): every name success or skipped. The last one, Lint & Repo Gates, completed success at 01:39:34Z — until then this PR was correctly left alone rather than flipped on a partial reading.

The docs-drift advisory — checked, and empty

Carried here so a reviewer does not re-derive it. The docs-drift-check comment flags that packages/spec/vitest.repo-tests.json yields no doc anchor, so pages documenting it are invisible to that run — "not a clean bill of health". Measured on origin/main:

grep over content/docs/ hits
repo-tests 0
cross-package-test-inputs 0
controlobjectstack 355 files
controlObjectQL 85 files

The controls fire, so the zeroes are readings: no doc page states a rule this file carries, and the advisory's blind spot is empty on this PR. ⛔ Nothing owed.

⛔ What was not done

The pin was never touched. Its three red legs before #16992 landed were the correct reading of a main that still carried the Exports: fallback — that redness was the evidence it is not vacuous, and it went green because the world changed, not because the assertion did.

This PR carries Refs, not Fixes ⇒ ⛔ no card moves on merge. #15263 is already closed and cleaned.


Generated by Claude Code

@zhuangjianguo
zhuangjianguo added this pull request to the merge queue Sep 9, 2026
Merged via the queue into main with commit ee2cb6b Sep 9, 2026
36 checks passed
@zhuangjianguo
zhuangjianguo deleted the claude/issue-15263-pointer-row-pin branch September 9, 2026 02:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants