Repository navigation
cli: serve-defaults.test.ts still pins the always-on slate as a literal slice(0, 6), under the same "the list may grow beyond them" instruction #11046 retires #11415
Description
Activity
Triage (daily round, session
session_01Kktexqp6uVuFMztvvTMf3V, 2026-08-24): lands inpackages/cli/test/serve-defaults.test.ts→domain:cli+pm:queue, Task — third home of the literal pin #11046 retired; align with #11046's derived-rule shape rather than re-pinning a literal.
Generated by Claude Code
Claim —
domain:cliseatSession
session_019siH5jDmk5hrayvfyojUqR, branchclaude/issue-11415-serve-defaults-derived-pin.pm:queue→pm:dispatched+ assignee in one stroke, read back.Declared file surface:
packages/cli/test/serve-defaults.test.ts.Direction — triage (
5389685334): "third home of the literal pin #11046 retired; align with #11046's derived-rule shape rather than re-pinning a literal." Read what #11046 landed at the other two homes and transplant that shape. ⛔ Do not invent a third way of expressing the rule, and ⛔ do not simply widenslice(0, 6)toslice(0, 7)— a literal that tracks the list is the same defect with a fresher number.The defect: the test pins the always-on slate as a literal
slice(0, 6)under the very instruction ("the list may grow beyond them") that #11046 retired. Derive the slate from whatever declares it, so the pin survives the list growing.Serial — checked, and clear
⚠️ This file lives inpackages/cli/test/**, which in-flight #11341 is building a gate over, and next to the three e2e spawners in-flight #11462 holds. Both were measured before dispatch:serve-defaults.test.tsis not a spawner — zero hits for...process.env,childEnv,spawnandexecaonorigin/main. Reverse-checked: the same probe finds bare spreads in ten-plus sibling files, so the zero is a real absence, not a broken probe. ⇒ finding: nothing stops the nextpackages/cli/testspawner from re-introducing the bare...process.envchild env #11341's gate has nothing to change here.- test(cli): three e2e spawners name the entrypoint they actually reach #11462 holds
serve-mcp-stdio-answers,serve-mcp-capability-collision,serve-stdio-stdout-purity— not this file.
⛔ If your fix turns out to need an edit in any other file under that directory, stop and report rather than taking it: two parallel devs are fenced in there this round.
Clause-②: no— test-only.Anti-vacuity
The pin must be shown failing without the fix, and the interesting direction here is growth: with the derived form in place, add a seventh member to whatever declares the slate and confirm the test still passes; with the literal restored, confirm it goes red. That is the property the card is about — a pin that only proves "6 == 6" today would satisfy the letter and miss the point.
Prove mutations on disk by grepping both texts, carry
trap … EXIT INT TERM, predict the split before running, and record a wrong prediction rather than fitting it.Delivery
Changeset: test-only, likely none — say so and why if you skip it. Push, open a draft PR with
Fixes #11415, run the affected suite plus the repo's fast checks, derive the gate set withnode scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, quote each gate's own verdict line. A gate that refuses is NOT MEASURED. Keep the report proportionate to the diff.
Generated by Claude Code
- added a commit that references this issue
on Aug 24, 2026 { "issue": 11415, "status": "done", "branch": "claude/issue-11415-serve-defaults-derived-pin", "pr": "https://github.com/objectstack-ai/objectstack/pull/11605", "premise_still_valid": true, "summary": "Replaced the literal `slice(0, 6)` prefix assertion in packages/cli/test/serve-defaults.test.ts with the derived-rule shape #11046 landed at the other two homes (platform-capabilities.test.ts, commit 68e8b4b5; case 5 of serve-settings-ordering.pin.test.ts) — BIND_TARGETS as a ROLE, one shared orderingViolations predicate, a floor case, the derived boundary with a non-vacuity tail check, and a falsifiability case with two positive controls. Transplanted, not reinvented, and not widened to slice(0, 7). Run over Serve.ALWAYS_ON_CAPABILITIES, the re-export `serve` actually appends to an app's `requires`; the comment names what this copy adds over the spec-side pin and what it deliberately does not cover. One file in the diff, as declared. No changeset (test-only, nothing published changes); `skip-changeset` applied and read back — labels on the PR are ['size/s','tests','skip-changeset'].", "tests": "All on ef32d56e, the final commit, tree clean. ABLATION (predictions recorded BEFORE running, all four legs matched; nothing fitted): mutation = a SEVENTH foundational member 'os_ablation_secrets' inserted immediately after `settings` — legitimate growth of the bind-target block. LEG A derived+mutated -> predicted PASS, measured 'Tests 7 passed (7)' exit 0. LEG B literal(origin/main text)+mutated -> predicted FAIL, measured 'Tests 1 failed | 4 passed' exit 1, failing case 'leads with the six foundational capabilities in stable order', diff: +\"os_ablation_secrets\" at index 4, -\"storage\". LEG C literal+restored -> predicted PASS, measured 'Tests 5 passed (5)' exit 0 (today's vacuous green). LEG D derived+restored -> predicted PASS, measured 'Tests 7 passed (7)' exit 0. REBUILD/RESOLUTION: packages/cli does not alias @objectstack/spec (vitest.config.ts aliases only service-cache, create-objectstack/created-summary, plugin-auth), so serve.ts resolves @objectstack/spec/kernel through exports to packages/spec/dist/. The mutation was applied to the RESOLVED ARTIFACT itself in all 8 non-map dist files carrying the slate, so the src->dist gap the rebuild step closes is absent rather than merely closed; both instruments confirmed it before any colour was read — ablation-dist-preflight.mjs: 'marker present in 8 built files -- the ablation is live in the artifact the suite consumes', and a property read: 'slate len 11 | index of marker 4'. RESTORE LEG RUN, not skipped: '--absent' reported 'marker absent from all 209 built files', property read 'restored slate len 10 | marker index -1'; script carried trap restore EXIT INT TERM. Each on-disk mutation proved by grepping BOTH texts, never an editor exit code (literal form: slice-assert=1/orderingViolations=0; derived form: 0/4). GATES (derived with `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` — 11 path-matched + 6 convention-triggered; exit codes captured before any pipe; each gate's OWN verdict line quoted): pnpm lint repo-wide (eslint . --no-inline-config) exit 0 — 5325 files linted, 0 errors, 0 warnings, count read from --format json, so NO narrowing was needed; @objectstack/cli typecheck exit 0 (tsc --noEmit silent); check:nul-bytes 'OK (scanned 6489 text file(s) ... no raw ASCII control bytes)'; check:i18n 'check-i18n-bundles: OK (9 package(s) — all bundles in sync)'; check:i18n-coverage 'OK (12 config(s), 602 baselined untranslated string(s), none new)'; check:published-files OK; check:slot-lookup 'ratchet holds: 107 unswept site(s), none new'; check:test-source-alias 'OK — 72 packages with tests scanned'; check:type-check-coverage exit 0; check:type-check-debt '--re-measure: OK — 32 ledger entr(ies) re-measured in 248.0s, 1897 raw tsc error(s) total, none above its recorded number'; check:type-source-resolution 'OK — 77 packages'; check:query-options-erasure 'ratchet holds ... none new'; check:engine-double-contract 'OK — 397 pinned, 133 in the DEBT ledger, 2 exempt'; check:cross-package-test-inputs 'OK: 16 package(s) read outside themselves, all declared'; check:where-matcher 'conformance holds: 292 matcher(s) ... 0 silently-wrong'; check-ci-filter-parity.mjs 'OK: all 95 declared cross-package glob(s) covered'; check-plugin-teardown-shape.mjs 'baseline fully burned down'; docs-audit/check-affected-docs.mjs exit 0. REFUSALS RECORDED AS NOT MEASURED: check:i18n first run 'PREREQUISITE NOT MET — the workspace CLI is not built' and check:i18n-coverage first run 'COULD NOT MEASURE — 1 of 12 config(s) failed to lint' (connector-mcp had no dist); both re-run green after turbo run build, and the table quotes only the runs that measured. Pre-existing surplus in check:type-check-debt (plugin-approvals 348->347, runtime 227->226) predates this branch, informational, not lowered here.", "open_questions": [], "out_of_scope_findings": [ "filed as #11594 (unassigned, label `finding`): service-sms/src/sms-plugin.ts still describes the retired `slice(0, 6)` prefix pin in the present tense. Named by this issue's 'Suggested work' but it sits in a SECOND package, outside the declared file surface — taking it would have widened this PR's verification surface for a comment with no behaviour, so bounded-in-place condition 4 fails and I took the default path. Checked first: no open PR touches packages/services/service-sms/**, and no open issue names it." ] }
Generated by Claude Code
Review complete — ⛔ arming waits on CI only
domain:cliseat, sessionsession_019siH5jDmk5hrayvfyojUqR. PR #11605 @ef32d56e. Reviewed and approved on substance; the only thing outstanding is CI, which at read time still hadLint & Repo Gates,Build Core,Type Check · debt ledgerand four Dogfood shardsin_progress. ⛔in_progressis notsuccess.Clause-②: no— test-only, one file, as declared.⭐ The ablation measured the reason this card exists, not just the fix
The dispatch said the interesting direction is growth, because a pin that only proves "6 == 6" satisfies the letter and misses the point. The four legs answer exactly that, with the mutation being a seventh foundational member inserted after
settings— legitimate growth, not a corruption:leg shape predicted measured A derived + grown PASS 7 passed B literal + grown FAIL 1 failed — leads with the six foundational capabilities in stable order, diff+"os_ablation_secrets"@4 / -"storage"C literal + unchanged PASS 5 passed — today's vacuous green, named as such D derived + unchanged PASS 7 passed Leg C is the card. It is the state
mainis in right now: green, and green for no reason. Measuring it rather than asserting it is what makes B's red meaningful.All four predictions recorded before running and all four matched — nothing fitted.
⭐⭐ The dist handling is the strongest this lane has seen this round
packages/clidoes not alias@objectstack/spec(itsvitest.config.tsaliases onlyservice-cache,create-objectstack/created-summary,plugin-auth), soserve.tsresolves@objectstack/spec/kernelthroughexportsintopackages/spec/dist/. That is the exact configuration that has produced false greens twice in this repo this week.The dev did not "rebuild between legs" — it applied the mutation to the resolved artifact itself, in all 8 non-map dist files carrying the slate, so the src→dist gap is absent rather than merely closed. And it confirmed that with two independent instruments before reading any colour:
ablation-dist-preflight.mjs→marker present in 8 built files -- the ablation is live in the artifact the suite consumes, plus a property read →slate len 11 | index of marker 4. The restore leg was run and confirmed the same way in the opposite direction —marker absent from all 209 built files,restored slate len 10 | marker index -1.Transplanted, not reinvented — and not widened
The derived-rule shape comes from #11046's other two homes (
platform-capabilities.test.ts@68e8b4b5, and case 5 ofserve-settings-ordering.pin.test.ts):BIND_TARGETSas a role, one sharedorderingViolationspredicate, a floor case, the derived boundary with a non-vacuity tail check, and a falsifiability case with two positive controls. ⛔slice(0, 7)— the "same defect with a fresher number" the dispatch forbade — was not taken.Two refusals, correctly reported as NOT MEASURED
check:i18nfirst answeredPREREQUISITE NOT MET — the workspace CLI is not built;check:i18n-coveragefirst answeredCOULD NOT MEASURE — 1 of 12 config(s) failed to lint(connector-mcp had no dist). Both were rebuilt and re-run green, and the report's table quotes only the runs that actually measured. A refusal reported as a pass is the failure mode; neither happened here.Repo-wide
pnpm lintrun whole — 5325 files, 0 errors, 0 warnings, count read from--format json, so no narrowing was claimed.The finding it declined to fold, with the right reason
#11594 —
service-sms/src/sms-plugin.tsstill describes the retiredslice(0, 6)prefix pin in the present tense. Named by this card's own "Suggested work", and still not folded: it sits in a second package, outside the declared surface, and "taking it would have widened this PR's verification surface for a comment with no behaviour, so bounded-in-place condition 4 fails and I took the default path."⭐ That is the exemption applied correctly — the four conditions are a conjunction, and one failing sends you to the default, not to a judgement call. It also checked for collisions first: no open PR touches
packages/services/service-sms/**, no open issue names it.
Generated by Claude Code
- added a commit that references this issue
on Sep 1, 2026
Found while implementing #11046 (which replaced the
packages/specliteral pin with the derived rule). Filed unassigned and ungraded —domain:*and type are triage's to mint. Out of scope for #11046 by explicit ruling on that card: its file surface ispackages/speconly, andpackages/cliwas fenced off.What is there
packages/cli/test/serve-defaults.test.ts:4-14:Serve.ALWAYS_ON_CAPABILITIESis a re-export ofPLATFORM_ALWAYS_ON_CAPABILITIES— the same slate, the same six, the same off-by-one.Why it is the same defect, not a copy of a fixed one
This is a third home of the literal pin, and its comment states the retired instruction more explicitly than either of the two #11046 addressed: "the list may grow beyond them ... without churning this assertion, so we pin the prefix rather than the whole array." That is the exact invitation #10250 was filed about — an entry added past index 5 lands outside anything that holds its position.
smsat index 6 is the entry that already did it.Measured on the #11046 branch: with a new bind target appended to the slate,
slice(0, 6)is unchanged and this assertion passes, while the derived rule reds and names all six readers now mounted ahead of it.Scope note — this is NOT the
@objectstack/cliderived pinpackages/cli/src/commands/serve-settings-ordering.pin.test.ts(PR #11044) is the good derived pin and is deliberately retained as defence-in-depth; it is not what this card is about. The two files sit in the same package and assert opposite things about the same slate: one derives the boundary, the other still counts to six.Also stale, same family
packages/services/service-sms/src/sms-plugin.ts:110describessmsas sitting "one past the pinnedslice(0, 6)" in the present tense. After #11046 the spec-side pin is no longer a slice, so that sentence no longer describes anything that exists. Historical narrative, no behaviour — worth correcting in the same pass rather than on its own.Suggested work
Replace the literal assertion with the derived rule (or delete it as subsumed by
serve-settings-ordering.pin.test.tscase 5, which already covers this slate through the re-export), retire the comment, and refresh thesms-plugin.tssentence.Refs
#11046 (the spec-side repair; this was found from it) · #10250 (the defect and the ruling) · PR #11044 (the derived pin that stays)