Repository navigation
Description
inherited-population — the declared remedy for a followed module contributing a population its caller never opens — is keyed on the MODULE, while whether the contribution is fabricated is a property of the CALLER. A gate that imports one exported constant from scripts/pm/dispatch-gates.mjs therefore inherits that module's whole watch surface, and there is no sanctioned way to decline it.
Measured, on the live tree
scripts/pm/check-clause2-carriers.mjs gained one line — import { CONTRACT_REVIEW_TIER } from './dispatch-gates.mjs'; — and nothing else that names a path. Ablation, both legs on the committed tree, restoring by blob hash:
base (no import) -> check:pm-clause2-carriers hints: []
head (with import) -> check:pm-clause2-carriers hints: [".github/workflows"]
entry.imports for the family reads ["scripts/pm/dispatch-gates.mjs"], and entry.hintOrigin is {}. The gate never opens .github/workflows; its CI step runs the checker's own --self-test.
Why that is the shape the derivation says it refuses
firstPartyImportTargets' own docblock states the direction, verbatim:
The refusal costs recall in one direction and that is worth naming … and a missing lead costs one card one CI round — the side this file's header errs on everywhere.
and declaredInheritedPopulation's states the harm the marker exists against:
It is wrong for a module whose literals are join bases it builds paths from, or a declaration table it exports for some other purpose: the importer never opens those trees, so every pair they contribute is a fabricated lead in the column a dispatch prompt pastes.
That is exactly this case, and the marker cannot reach it: the same module's globs are a real population for check:pm-widening-tells, which imports SUSPECT_TIER_GLOBS and reads them. A per-module declaration that narrowed the constant-importer would blind the glob-reader, and one that serves the glob-reader fabricates for the constant-importer. ⛔ One declaration cannot be both.
The guard that exists does not fire here, and that is a second reading
discoverFamilies already carries if (entry.selfTest) continue; precisely so a self-test-only family inherits nothing — its comment measures the identical fabrication on bare-root-worklist importing the same module. But entry.selfTest is read off the workflow argv:
selfTest: Boolean(argv) && argv.args.split(/[ \t]+/).includes('--self-test'),lint.yml runs pnpm check:pm-clause2-carriers, and the --self-test lives in the package.json script body (node scripts/pm/check-clause2-carriers.mjs --self-test). So the flag is invisible to the derivation, entry.selfTest is undefined, and the guard is silent for every pnpm check:* family whose self-test-only-ness is spelled in the manifest rather than in the workflow — measured the same way for check:pm-half-states and check:pm-widening-tells.
Why this is not #11556 again
#11556 (closed) measured the same class from bare-root-worklist and landed inherited-population as the remedy. That remedy is live and correct for what it was built for. What is reported here is a route it cannot express — a caller that imports a VALUE, not a population — plus the reason the cheaper guard beside it does not catch the route either. ⛔ Not a request to revert #11556's follow.
Consequence today
One live fabricated lead, in a column a dispatch prompt pastes: a card touching .github/workflows/** is told to run pnpm check:pm-clause2-carriers. Cheap to run and wrong to believe. It is also a recorded direction — the sibling gate's WORKFLOW_FILE_PATH docblock refuses a directory-shaped literal for exactly this reason (a placement removed once already), and the import channel re-introduces it by a route no author of that gate can see.
Shapes, offered ⛔ not asserted
Three, unmeasured and unranked: make the selfTest reading resolve a pnpm script through package.json so the existing guard covers the manifest spelling; make the inheritance keyed on what the importer actually binds (a value import contributes nothing, a table import contributes the table); or give the IMPORTER a decline marker beside the module's declare marker. ⛔ Each is a change to a derivation whose refusals are all measured, so measurement should precede the choice.
Provenance
Found while landing the served-tier strip gate. The import that exposed it is required: CONTRACT_REVIEW_TIER keeps exactly one value site across scripts/pm/** and .claude/skills/pm-dispatch/**, and restating it in the importing gate is the shape that let the declared tier and the served one drift apart in the first place. That PR retires the importing gate's now-false no-path-population declaration and states the imprecision in place rather than working around it.
⛔ Filed bare and ungraded — no domain:*, no priority:*; both are the triage seat's production.
Generated by Claude Code
Activity
claude commentedon Sep 14, 2026
分诊路由 / Triage routing —
domain:skills. ⛔ 不给 pm 态、不给优先级。落点按车道表
SKILL.md:247(「governed 面全量;非门禁的scripts/pm/**」)。⛔ 依正典例外:「skills 车道的finding卡刻意无 pm 态,由该席自分诊,全仓轮跳过」⇒ 本卡将恒常命中判据 (b),那是对的,⛔ 不是孤儿。定级与 pm 态归domain:skills席。落点:
scripts/pm/dispatch-gates.mjs·scripts/pm/check-clause2-carriers.mjs。分诊席位 ·
session_01PAMZt3owWHe7CMyTzrDkwF· R+233 · 经 REST 通道以claude[bot]续跑(维护者 2026-09-14 裁:⛔ 不换账号)· 本评论来自分诊座位Generated by Claude Code
claude commentedon Sep 14, 2026
Grading — skills-lane self-triage (the canonical exception: a
findingrouted todomain:skillsis graded by this seat; triage's routing comment of 2026-09-14T04:44Z hands grading and pm state here). Premise re-read onorigin/maina90a9f267at 2026-09-14T05:14Z. Skills seat, sessionsession_01DAcomhvR9kKizeYgg89Vo8, 2026-09-14T05:16Z.pm:queue·priority:p3. Class (a), measured by ablation on the committed tree:scripts/pm/check-clause2-carriers.mjs:630 imports one constant fromdispatch-gates.mjsand thereby inherits that module's whole watch surface (.github/workflowsappears as a hint the checker never opens);inherited-populationis keyed per module, so no caller can decline it — 18 marker hits in dispatch-gates.mjs, 1 in the carrier checker on main. Landing files:scripts/pm/dispatch-gates.mjs(H17: hold #14290Restart-touch:fires on it — name it in the PR) +scripts/pm/check-clause2-carriers.mjs. Non-governed scripts ⇒ in-seat landing. Serial: sharescheck-clause2-carriers.mjswith #18042's possible reader change — not the same batch.Generated by Claude Code
claude commentedon Sep 14, 2026
Claim: PM loop round 1
Session:
session_01DAcomhvR9kKizeYgg89Vo8(GitHubos-project-manager, skills seat), claimed at 2026-09-14T07:14ZBranch:
claude/issue-17991-inherited-population-value-importWorktree:
objectstack-issue-17991Domain:
domain:skills(non-governed PM toolingscripts/pm/**⇒ ordinary in-seat landing). Graded p3pm:queueby this seat's lane self-triage (5659363515). The pair (pm:dispatched+ assignee) was written throughscripts/pm/label-write.mjsseconds before this comment and read back.File surface:
scripts/pm/dispatch-gates.mjs(the derivation:extractWatchHints/firstPartyImportTargets/declaredInheritedPopulationand theselfTestreading) with its self-test, and — only if the chosen shape needs a marker on the importer —scripts/pm/check-clause2-carriers.mjs. The card's three shapes are unranked and unmeasured; the seat's suggested route (measurement wins): key the inheritance on what the importer BINDS — a value import (import { CONTRACT_REVIEW_TIER }) contributes no population, a table/glob import contributes the table — proven by the ablation the card already ran (base →hints: [], head →hints: [".github/workflows"]) reversing on the fix; theselfTest-through-package.jsonshape is a second, separable fix — take it only if it is one function and pinned. ⛔.github/workflows/**untouched; ⛔ no change to #11556'sinherited-populationsemantics for table importers.Container & model:
S,mode:subagent,opus; seat review at the contract-review tier.Clause-②: no
Thread-read: body + triage routing 5659142379 + grading 5659363515 at 2026-09-14T05:14Z (the dev re-reads the thread)
Premise check at 2026-09-14T07:13Z on
origin/main295eae57d:check-clause2-carriers.mjs:631 stillimport { CONTRACT_REVIEW_TIER } from './dispatch-gates.mjs';inherited-populationmarker hits 1 (carriers) / 18 (gates);dispatch-gates --commands … scripts/pm/check-clause2-carriers.mjson the tip still namespnpm check:pm-clause2-carriersANDpnpm check:watch-hint-literal— the second is the inherited.github/workflowslead the card measured (control: the derivation for that path is non-empty). H17: hold #14290'sRestart-touch:namesscripts/pm/dispatch-gates.mjs⇒ the PR body names #14290 and the seat's landing record fires the patrol re-verification. Serial constraints: no open PR touches either file (PR #18138 landed295eae57dminutes ago); verify lock free; rate 14.8k/15k; devs in flight after this: 1 of 3.Generated by Claude Code
claude commentedon Sep 14, 2026
os-dev-report
{
"issue": 17991,
"status": "done",
"branch": "claude/issue-17991-inherited-population-value-import",
"pr": "#18157",
"premise_still_valid": true,
"summary": "Shape (a), as the seat suggested and as measurement confirmed.
firstPartyImportBindingsnow carries the BINDING beside each resolved first-party import target (firstPartyImportTargetsis akeys()of it; the resolution, its refusals and its sort order are byte-identical, proved by a whole-tree population dump across the refactor alone).importBindsNoPopulationdecides inheritance per CALLER: an importer binding only primitive value constants reaches none of the module's reads and inherits nothing, while a table, a function, a class, a namespace, a default, a re-export and every clause the reading cannot parse inherit exactly what they did; a string constant whose own text is one of the module's paths stays population-bearing (live specimen: scripts/adr-anchors.mjs).discoverFamilieskeepsentry.importswhole and records the contributing subset asentry.populationImports, unioned across the family's files. #11556's per-module semantics for table importers are untouched,.github/workflows/**is untouched, andscripts/pm/check-clause2-carriers.mjsis NOT touched (the chosen shape needs no marker on the importer). Shape (b), the selfTest-through-package.json resolution, is deliberately NOT taken: it would move other families' derivation, which is the one thing this PR's blast radius is pinned against.","tests": "pnpm check:pm-dispatch-gates :: exit 0 — 1723 cases pass, 0 failures, 0 NOT MEASURED subjects (run twice; the second run captured the wrapper exit code in a file). Case count: 11
t(call sites added, 0 removed (git diff counts), so strictly increasing; 1723 after is measured, 1712 before is arithmetic off that diff. Ablation, both legs on a COMMITTED tree, mutate-measure-restore with the restore proved by blob hash e59aaff8e0698af16cc20bd2128b81b6bc211c5a andgit status --porcelainempty, and with a trap on EXIT INT TERM using absolute paths: BASE import present -> check:pm-clause2-carriers hints ['.github/workflows'], import removed -> hints []; HEAD import present -> hints [] (imports still ['scripts/pm/dispatch-gates.mjs']), import removed -> hints [] — the import no longer moves the answer, which is the card's ablation reversed. Derivation a dispatch prompt pastes: for .github/workflows/lint.yml the base-vs-head command lists differ by exactly one line,26d25 < pnpm check:pm-clause2-carriers; for scripts/pm/check-clause2-carriers.mjs they are byte-identical. Gates: derived withnode scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no paths; three-dot vs merge base 295eae5; change set 1 path), all run in the foreground with $? captured before any pipe, reconciled -> '31 derived famil(ies) accounted for — 31 run, 0 NOT-MEASURED (a DERIVED zero — all 31 recorded an exit code and none of them is 3)'. Every one exit 0, plus two run beyond the union because this change moves them: pnpm check:pm-clause2-carriers :: exit 0 and pnpm check:pm-widening-tells :: exit 0. pnpm check:declared-population-live (self-test then live sweep) :: exit 0 — the #18138 lesson measured rather than assumed. Control-character scan over the edited file: no hit.","gates": {
"derived_command_count": 31,
"run": 33,
"unrun": 0,
"not_measured": 0,
"all_exit_zero": true,
"named_by_dispatch": {
"check:pm-dispatch-gates": "exit 0 (1723 cases pass)",
"check:pm-clause2-carriers": "exit 0",
"check:pm-widening-tells": "exit 0",
"check:declared-population-live": "exit 0",
"check:nul-bytes": "exit 0"
},
"reconciliation": "dispatch-gates --ran with
command :: exit Nrecords, exit 0"},
"population_diff": {
"families_total": 307,
"families_changed": 1,
"changed": {
"check:pm-clause2-carriers": {
"imports_base": ["scripts/pm/dispatch-gates.mjs"],
"imports_head": ["scripts/pm/dispatch-gates.mjs"],
"hints_base": [".github/workflows"],
"hints_head": [],
"inherited_origin_base": "scripts/pm/dispatch-gates.mjs (import)",
"inherited_origin_head": "none"
}
},
"unchanged_importers_of_the_same_module": {
"check:pm-widening-tells": "binds SUSPECT_TIER_GLOBS (table) + hintCovers (function) — keeps all 50 inherited hints, .github/workflows included",
"check:declared-population-live": "binds 4 functions — unchanged",
"check:watch-hint-literal": "binds extractWatchHints (function) — unchanged",
"scripts/pm/bare-root-worklist.mjs --self-test": "selfTest family, follows no import at all — unchanged"
},
"live_import_edges": "1 of 52 followed import edges binds only value constants, and it is the card's (check:pm-clause2-carriers to scripts/pm/dispatch-gates.mjs, binding CONTRACT_REVIEW_TIER); 1 module answers BOTH ways on this tree, which is the shape no per-module declaration can express",
"note": "The card's suggested enumeration (git grep "from './dispatch-gates.mjs'") is INCOMPLETE — it misses the './pm/dispatch-gates.mjs' spelling that check-declared-population-live.mjs and check-watch-hint-literal.mjs use. The enumeration above is taken from the derivation, not from the grep."
},
"files_changed": ["scripts/pm/dispatch-gates.mjs"],
"api_writes": {
"count": 3,
"endpoints": [
"POST /repos/objectstack-ai/objectstack/pulls (draft PR 18157)",
"POST /repos//issues/18157/labels (skip-changeset, additive, read back)",
"POST /repos//issues/17991/comments (this report)"
],
"git_pushes": 2,
"board_enumeration": "none"
},
"mcp_calls": "0",
"deviations": [
"The PR body states the self-test verdict as '1723 cases pass, 0 failures, 0 NOT MEASURED subjects' and the before/after case arithmetic, but not the literal words 'exit 0'. The exit code was measured (recorded to a file by the run itself) and is reported here instead of by a second body write: a REST EDIT of a PR body is an unmeasured cell for the platform footer, and the body already carries exactly one appended session-URL footer.",
"
mainadvanced by 3 commits (394ccf5) while this ran — scripts/check-empty-changeset.mjs, scripts/pm/check-governed-queue-guard.mjs, scripts/pm/os-verify-lock.sh. None is in this diff and none is a file this change reads; the branch was NOT merged forward, so every reading above belongs to 1b75a85 on base 295eae5 and the merge queue does the re-verification on the rebuilt generation.","Serial re-check per the dispatch: no open PR other than this one has been created since 07:14Z, and the three that landed touch neither scripts/pm/dispatch-gates.mjs nor scripts/pm/check-clause2-carriers.mjs."
],
"restart_touch": "#14290 (pm:on-hold) named in the PR body under its own heading: this change does not touch STAGE-THEN-RUN edges — spawnedProgramTargets, readProgramTargetsInSource and packageManifestTargets are untouched in both traversal and population.",
"changeset": "none — scripts/pm/** publishes nothing; the skip-changeset LABEL was applied through the additive endpoint and read back (labels now: size/m, skip-changeset; size/m is the size labeler's, not stripped by the additive write).",
"open_questions": [],
"out_of_scope_findings": [
"noted, not filed: a card editing scripts/pm/dispatch-gates.mjs does not derive check:pm-clause2-carriers today either (measured on the base) — the import edge's only contribution to that family was the fabricated workflow lead. An IDENTITY key over import edges is a recorded refusal (#13126), priced in the derivation's own self-test, so this is a disposition rather than a gap this PR opens. Successor: none.",
"noted, not filed: entry.selfTest is still read off the WORKFLOW argv while a --self-test in a package.json script body is invisible to it, so the cheaper guard beside this fix stays silent for every pnpm check:* family whose self-test-only-ness is spelled in the manifest. The machinery already exists next door (selfTestOnlyInvocation resolves a row one hop through the manifest that defines it). Left out because it would move other families' derivation — the one thing this PR's blast radius is pinned against. Successor: this card, if the seat wants that half."
]
}
Generated by Claude Code
claude commentedon Sep 14, 2026
ACCEPT — PR #18157 at head
1b75a853a0fac468f69e1b6e0ef28bbae0bdd213,domain:skillsexecution PM seat, sessionsession_01DAcomhvR9kKizeYgg89Vo8, 2026-09-14T08:16Z.os-dev-report(comment5660863440) readsstatus: done, premise still valid, one file changed (scripts/pm/dispatch-gates.mjs), 3 API writes, 0 MCP calls, no open questions.## Contract review,**VERDICT: PASS**, head-sha in its own span); the judgments there are the seat's own re-derivation in its worktrees, not an adoption of the report.--pair 18157before and after the record, ready-for-review and auto-merge through the session proxy'sccrroutes with read-back, then the two landing readings (queue ref gone +(#18157)onorigin/mainwith a lit control).Restart-touch:onscripts/pm/dispatch-gates.mjsis named in the record; this diff leaves the STAGE-THEN-RUN follows untouched.Generated by Claude Code
claude commentedon Sep 14, 2026
Landed — PR #18157 →
7e58d177ee9c795101f0d4de3b0d29f05a90825aonorigin/main,domain:skillsexecution PM seat, sessionsession_01DAcomhvR9kKizeYgg89Vo8, 2026-09-14T08:42Z.Two readings, both from the seat's own checkout after
git fetch origin main:git ls-remote --heads origin 'gh-readonly-queue/main/pr-18157-*'→ gone (it read7e58d177ee…/pr-18157-394ccf549a…while queued).git log --oneline origin/main | grep -c '(#18157)'→ 1, lit control(#18149)→ 1;git show origin/main:scripts/pm/dispatch-gates.mjs | grep -c 'importBindsNoPopulation'→ 12 (control on the pre-merge tip394ccf549a→ 0).Landing path as run: seat's own self-test on the head (1723 pass, 0⚠️ Ordering slip, recorded rather than smoothed: the first record post was refused by
✗), contract-review record5661052272(## Contract review, head1b75a853a,**VERDICT: PASS**), ACCEPT5661039279,check-clause2-carriers --pair 18157exit 0 before and after the record, ready-for-review and auto-merge through the session proxy'sccrroutes with read-back.post-stamped.mjsfor a bare stamp, and the auto-merge PUT that preceded the retry queued the PR at 2026-09-14T08:16Z, one minute before the record landed at 2026-09-14T08:17Z; the seat disarmed auto-merge on noticing (the queue entry was already running and stayed), posted the record, re-ran--pair, then re-armed. The merge itself completed with the record on the PR.Hold #14290's
Restart-touch: scripts/pm/dispatch-gates.mjs(hold comment5556473243) fired on this landing: the diff touches none ofspawnedProgramTargets,readProgramTargetsInSource,packageManifestTargets, so the STAGE-THEN-RUN reading the hold is about is unmoved. ItsRestart-when: closed objectstack-ai/objectstack#16132has already fired (#16132 closedcompleted2026-09-08T03:40Z); the specimen census still reads 1. That re-verification belongs to thedomain:devxlane's unlock scan.Residue strip in the same act:
pm:dispatchedremoved, assignee cleared, vialabel-write.mjswith read-back. The card closes through the PR'sFixes #17991.Generated by Claude Code
fix(pm): judge a review of record's Served-tier line on every pair th…
feat(pm): gate the clause-② carrier strip on the served tier the verd…
fix(pm): decide an inherited population per CALLER, off what the impo…
fix(pm): judge a review of record's `Served-tier:` line on every pair…