Skip to content

reader program 2/4 — @objectstack/runtime: every top-level collection read gains a packages[] path #15005

Closed

Description

@hotlong

Part of #14122 · blocks #14512 · Blocked-by: #15004 (the acceptance probe — this card does not land before that pin can go red).

Reader half of the program ruled on #14512 (comment 5528589044, maintainer 2026-09-03, batch #23): the artifact stays additive through this card. Nothing here changes what is emitted; each reader simply learns to find its collections under packages[] as well as at the top level.

The sites

From the enumeration (5523603341) and the boundary measurement (5523741937), all origin/main at the time of measurement:

Reader file:line Measured when the top level is removed
collectBundleActions packages/runtime/src/app-plugin.ts:1878-1905 4 → 0. Reads exactly bundle.actions, bundle.manifest.actions, bundle.objects[].actions, bundle.manifest.objects[].actions — no packages[] path. Every declarative action 404s at dispatch, including object-embedded ones
collectBundleHooks packages/runtime/src/app-plugin.ts:1843 1 → 0
collectBundleFunctionEntries packages/runtime/src/app-plugin.ts:1921, consumed :868, :987 —
AppPlugin jobs packages/runtime/src/app-plugin.ts:972-975 1 → 0
AppPlugin seed data packages/runtime/src/app-plugin.ts:1110-1111 1 → 0
AppPlugin translations / i18n packages/runtime/src/app-plugin.ts:1701-1705, :1749 1 → 0
AppPlugin datasources / objects packages/runtime/src/app-plugin.ts:536-541, :559, :577, :619, :646 datasources 1 → 0, datasourceMapping 1 → 0, objects 2 → 0
AppPlugin SECURITY_FIELDS packages/runtime/src/app-plugin.ts:723-800 —
createStandaloneStack surfaced keys packages/runtime/src/standalone-stack.ts:780-795 (requires, objects, permissions, positions, i18n) permissions 1 → 0, positions 1 → 0
resolve-project-database project-DB tier packages/runtime/src/resolve-project-database.ts:202, :208 —

Two things that are not obvious and cost a cycle if missed

  1. resolve-project-database opens the artifact itself. :193 is its own readFileSync + JSON.parse with a copy of loadArtifactBundle's envelope unwrap at :195, not a call to it. Inside createStandaloneStack it runs at :574, 112 lines before loadArtifactBundle at :686, and it is also reached independently from os dev (dev.ts:56), os start (start.ts:557) and os db clean (db/clean.ts:46) before any stack exists. Teaching only the bundle path leaves it blind.
  2. createStandaloneStack's ADR-0056 D7 permission surface is fed from two boundaries — from B1 here, and from the config path via appSecurityPluginOptions(config) in @objectstack/cli (card 3/4). Fixing one side leaves the other silently empty; the probe pin covers both, which is why it lands first.

⚠️ standalone-stack.ts:785 omits the objects key entirely when the array is absent (rather than setting it to []), and mergeBootConfig is a plain spread (packages/cli/src/utils/merge-boot-config.ts:42). That interacts with card 3/4's engine and driver auto-registration gates — check the two cards' behaviour together on the probe before either is called done.

Acceptance

Sibling cards: #15004 (probe, blocks this), 3/4 @objectstack/cli, 4/4 @objectstack/plugin-security. Emitter half: #14512.

Activity

  1. hotlong commented on Sep 4, 2026

    @hotlong
    ContributorAuthor

    Claiming this card.

    • session: https://claude.ai/code/session_01UHvF5hyiZjnCyExFnfQB8m
    • branch: claude/issue-15005-runtime-packages-reader

    Scope held to @objectstack/runtime readers only; the artifact stays additive. Sibling cards #15006 / #15007 own their own packages.

    Generated by Claude Code


    Generated by Claude Code

  2. hotlong commented on Sep 4, 2026

    @hotlong
    ContributorAuthor

    os-dev-report

    {
      "issue": 15005,
      "status": "done",
      "branch": "claude/issue-15005-runtime-packages-reader",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/15261",
      "premise_still_valid": true,
      "summary": "Every enumerated `@objectstack/runtime` reader now resolves its collections across both artifact shapes, through ONE new function — `resolveArtifactCollections` in `@objectstack/core`, beside `resolveArtifactPackageOrder` and built out of it. Its rule: the artifact's own top-level value first and whole, then each package body contributes, in `resolveArtifactPackageOrder`'s order, the items the top level did not already claim. On today's additive artifact that returns the caller's own object BY IDENTITY (step 2 contributes nothing), and a bundle with no `packages[]` short-circuits before any of it — so no shipped shape can have moved; on an option-B artifact the top level contributes nothing and the answer is package order. Item identity is `name` when present and a stable serialization otherwise, and both are needed: structural identity alone breaks on `objects` (the one collection `composeStacks` MERGES, so a merged top-level entry would be joined by both unmerged package halves), and name identity alone would drop a base's extension under `packages[]` where nothing merged them. Taught: AppPlugin (one lazy memoized `collections` accessor covering datasources, datasourceMapping, objects, jobs, seed data, translations, the ADR-0057 security block and the job handler context's bundle), the three exported collectors, `mergeRuntimeModule`'s declaration half, `createStandaloneStack`'s surfaced keys, and `resolve-project-database`'s project-DB tier. THREE THINGS THE REVIEWER SHOULD READ RATHER THAN SKIM. (1) SCOPE: the diff touches `@objectstack/core` and the card scopes `@objectstack/runtime` — see open_questions[0]; it is strictly additive (one new file, two new exports, one barrel line; no existing core symbol changed) but it does widen a published surface, which is a decision above this card. (2) `mergeRuntimeModule` (`load-artifact-bundle.ts`) is a site the card's table does not name; it had to be taught because the sibling ESM module re-supplies every callable regardless of shape, so `functions` was never ABSENT — a declared `effect: 'writes'` simply came back as a bare callable defaulting to `'pure'`. (3) `standalone-stack.ts`'s omit-the-key-when-absent behaviour is UNCHANGED and deliberately so: the resolver returns undefined for a key no source declares and the call sites keep their `Array.isArray` guards, so #15006's auto-registration gates see a key appear only for an artifact that actually declares `objects`. `mergeBootConfig` untouched. The card arrived unassigned; per the dispatch contract I did not write the assignee field — the claim is comment 5536000605 plus the branch. Also noted: this repo's CLAUDE.md tells a dev to assign the issue to itself, while the dispatch contract reserves that field for the PM; I followed the dispatch contract and am flagging the conflict rather than choosing silently.",
      "tests": "All at a7b7f8848 (final commit), the union re-run at that head AFTER merging origin/main (13 upstream commits, clean merge). Every exit code captured by redirect-then-capture, never through a pipe; every claim below quotes the gate's or runner's own judgement line. ACCEPTANCE PIN: `pnpm --filter @objectstack/cli exec vitest run --maxWorkers=2 test/option-b-reader-acceptance.pin.test.ts` -> `Test Files 1 passed (1) / Tests 6 passed (6)`. LEDGER 24 -> 1: the pin's set-equality assertion, its subsystem coverage and its anti-vacuity controls are untouched; the only edits are deleting the 23 rows the pin itself named and rewriting the ledger docblock. BEFORE/AFTER: with the fix in place and the ledger left at 24 the pin reported `1 failed / 5 passed` — `A ledgered subsystem now SEES its collections ... Delete these lines` naming exactly 23 rows and no others, while BASELINE, the `packages[]` anti-vacuity control and both structural tests passed in that SAME run; with those 23 deleted, 6 passed. ABLATION (two legs, both rebuilt, both proved on disk): the resolver was neutered to identity by a type-clean mutation of its derived key set, `git hash-object` moved off the HEAD blob before anything was measured (removed-text count 1 -> 0, injected marker 0 -> 1) and `scripts/ablation-dist-preflight.mjs` confirmed marker `OPTION_B_ABLATION_15005` `present in 2 built files -- the ablation is live in the artifact the suite consumes`; the pin then went RED naming EXACTLY the same 23 rows. Restore leg: hash back to the HEAD blob, whole-tree `git status --porcelain` EMPTY, preflight `--absent` -> `marker absent from all 12 built files`, pin 6 passed. A FIRST ablation attempt is reported rather than hidden: it used a comment as its marker, tsup strips comments, and the preflight correctly declared that run VOID (sourcemap-only hit); the reading above is from the redone one. SUITES, WHOLE, NOT NARROWED: `@objectstack/runtime` `Test Files 221 passed (221) / Tests 3166 passed (3166)`; `@objectstack/core` `49 passed (49) / 1170 passed (1170)`. NEW COVERAGE: packages/core/src/artifact-collections.test.ts (11 tests) and packages/runtime/src/app-plugin.option-b-packages.test.ts (6 tests, incl. the no-doubling assertion on today's additive shape — the direction the pin's non-zero-count rows could NOT have caught). TYPECHECK: exit 0 for both packages; `check:test-typecheck: OK` for both (core `4 file(s) / 4 error(s)`, runtime `27 file(s) / 191 error(s)`), byte-identical to the pre-existing ledgers so the new files add ZERO diagnostics. Both new test files are provably INSIDE those tsconfig.test.json programs — one of them failed that gate on its first run with TS2345 and was fixed, which is measurement rather than assumption. GATE FAMILY: 46/46 green, list from `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands`, re-derived IDENTICAL after `git fetch origin main` and again after the merge. `check:type-check-debt` -> `16 ledger entr(ies) re-measured in 146.0s, 207 raw tsc error(s) total, none above its recorded number / surplus: none`. `check:dual-build-cjs-loads` -> `102 published require entry point(s) across 66 package(s) load; 610 emitted CommonJS file(s) parse`. BOTH of those first returned exit code 3, `PREREQUISITE NOT MET -- nothing was measured`, and were NOT reported as passes on that reading: the first was an OOM `Killed` on its own spec build under box contention, the second wanted 12 more dist/; each was re-run once its prerequisite held and each then measured and passed. LINT: repo-wide `pnpm lint` (`eslint . --no-inline-config`) exit 0 — no narrowing claimed or needed. DOCS: no file under content/docs/ is in the diff; content/docs/releases/ was never opened. The drift bot's anchor list was not trusted as complete (it says so itself, and packages/core/src/index.ts produced no anchor at all): the whole docs tree was searched by the RULE — prose stating where a reader takes its collections from — with ZERO matches, and the nine named pages plus the ten pages importing from @objectstack/core were hand-read. The per-page readings are tabulated in the PR body. NOT MEASURED, declared: nothing. Every gate in the family has a real measurement behind it.",
      "mcp_calls": "15 — issue_read get 15005, issue_read get_comments 15005, add_issue_comment (claim), issue_read get 15004, issue_read get_comments 15004, pull_request_read get 15226 (to confirm #15007's row and its state), create_pull_request 15261, pull_request_read get 15261 (body read-back), search_issues x2 (positive control first, then the dedup query), issue_write create 15262, update_pull_request 15261, pull_request_read get 15261 (second body read-back after the PATCH), add_issue_comment (this report), issue_read get_comments 15005 (this comment's read-back). Container REST is session-gated 403 (probed at session start against a repo-scoped comment endpoint) and `gh` is absent, so no zero-quota REST channel was available; the branch-push write path was probed green before the first edit. Channel switch declared.",
      "open_questions": [
        {
          "question": "The card scopes `@objectstack/runtime`, and this diff also adds one file plus one barrel line to `@objectstack/core` — widening a published package's surface by two exports (`resolveArtifactCollections`, `packageOwnedCollectionKeys`). Is that the right home, or should it move?",
          "options": [
            "A. Keep it in `@objectstack/core`. The resolution has three callers by design — #15005 runtime, #15006 cli, #15007 plugin-security — and those three packages cannot import each other; core is a dependency of all three. It is the same argument, already written in `packages/core/src/index.ts`, that put `resolveArtifactPackageOrder` in the neighbouring file, and this resolution is built out of that function. Strictly additive: no existing core symbol changed, removed or re-typed; core's whole suite green at 1170 tests; `check:published-files` and `check:dual-build-cjs-loads` green.",
            "B. Put a private copy in each of the three packages. No published surface moves — but this program's own history is two enumerations that each missed a reader, and three private `packages[]` walks would disagree about what an artifact CONTAINS, not merely about its order. That is the drift the core module's header argues against by name.",
            "C. Keep it in runtime and have #15006 / #15007 import `@objectstack/runtime`. `@objectstack/plugin-security` does not depend on runtime — runtime depends on IT — so this inverts an existing edge."
          ],
          "recommendation": "A, on all four axes. Real business need: measured, not speculative — 23 of the pin's 24 ledgered losses are the readers this function serves, and the two sibling cards need the identical resolution. Long-term soundness: contract-first and the repo's own precedent, stated in the file it sits next to; B is the workaround the codebase already rejected once. Making AI-written metadata apps hard to get wrong: one resolution means one answer to `what does this artifact contain`, which is exactly the class of silent divergence option B's failure mode is made of. Startup scope discipline: it is not an unpulled capability — it has three named consumers today and zero speculative surface. C is refused on the dependency graph, not on taste. Flagged rather than folded in because it is a published-surface decision above the card, and the reviewer owns it."
        },
        {
          "question": "`mergeRuntimeModule` (`packages/runtime/src/load-artifact-bundle.ts`) is not in the card's enumerated table, but it had to be taught for the `functions` row to go green. Should a site the enumeration missed be landed here, or filed as 5/4?",
          "options": [
            "A. Land it here, as done. It is inside `@objectstack/runtime`, it is the same defect class, it is mechanical, and the pin's `functions` row cannot go green without it — the card's acceptance is that every runtime-side subsystem on the probe goes green.",
            "B. File it separately and leave that one row red. The ledger would then carry two rows instead of one and the program would not be one card from done.",
            "C. Teach `collectBundleFunctionEntries` alone instead. Measured not to work: `normalizeFlowFunctionEntry` deliberately drops BOTH lowered shapes, so the package body's `{ handler: '(ref)', effect: 'writes' }` normalizes to undefined and the declaration never reaches the collector."
          ],
          "recommendation": "A. The enumeration missing a reader is this program's known failure mode, not a surprise — #15004 exists because it happened twice. C is refuted by the spec's own documented behaviour rather than by preference. The site is named explicitly in the PR body rather than left to be discovered in the diff."
        }
      ],
      "out_of_scope_findings": [
        "filed as #15262: `AppPlugin` collects every seed dataset TWICE on a flat-manifest bundle — the legacy `manifest.data` fallback resolves `manifest` to the bundle itself when no `manifest` key exists, re-reading the array the top-level branch just pushed. Its `translations` sibling ~590 lines away carries the reference guard that makes the same two-location read safe; the `data` one does not. `mergeSeedDatasets` does not de-duplicate, so both copies reach the loader and every later per-org replay; for `mode: 'insert'` datasets that is a real double-apply (the end state of the closed #3434, reached by a different route). Pre-existing on origin/main, untouched by this PR. Searched with a positive control first.",
        "NOT filed, reported as context on an existing card: the OOM `Killed` inside `check:type-check-debt` truncated `packages/spec/dist` — `dist/data/index.d.ts` and `index.d.mts` gone while `index.js` / `index.mjs` remained, and the next typecheck reported TS7016 `implicitly has an 'any' type` against a real, correct dependency (the quiet direction being a suite passing green against `any`). A rebuild restored them. Same SHAPE as #15042, whose report states its cause was NOT established; here it is — a SIGKILL mid-DTS-build under box contention. Left as a note on #15042 rather than filed again."
      ]
    }

    Generated by Claude Code

  3. self-assigned this
    on Sep 4, 2026
  4. hotlong commented on Sep 4, 2026

    @hotlong
    ContributorAuthor

    os-dev-report

    {
      "issue": 15005,
      "status": "done",
      "branch": "claude/issue-15005-runtime-packages-reader",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/15261",
      "premise_still_valid": true,
      "summary": "Rework of PR #15261 after the contract review's REJECT, on the merged tree (origin/main fbecffe1d, so #15226 and #15228 are in the baseline). (1) resolveArtifactCollections and packageOwnedCollectionKeys moved from packages/core/src/artifact-collections.ts to packages/runtime/src/artifact-collections.ts, package-private; packages/core/src/index.ts restored byte-for-byte so @objectstack/core has ZERO source change (git diff fbecffe1d -- packages/core/ is empty). The changeset drops @objectstack/core entirely and keeps @objectstack/runtime at patch; review item 1 (core must be minor) is moot on this route, not ignored. (2) Review item 3a: the half-flattened support claim and its test are DELETED per #14512's ruling 'Not D (a partly flattened artifact is a new permanent shape)'; the module header now records what would actually happen on such an artifact instead of promising the opposite, and no narrowing machinery was added for a shape the ruling excludes. (3) Review item 3b: mixing the array and record spellings of one collection now raises the ADR-0112 envelope MIXED_ARTIFACT_COLLECTION_SHAPE (422) naming the key and both disagreeing sources, matching composeFunctions' refusal of the identical mix at compose time; three tests plus an anti-vacuity control, both orders driven. The code is classified in dispatcher-error-vocabulary.ts as door 'none' / boot-refusal. (4) Review item 3c: the dependency-cycle throw is documented in @throws as a BARE Error carrying no code/status. The PR body's false claim that the three packages cannot import each other is replaced by the measured edge table; the real reason is pull (one consumer). ONE DEVIATION, declared: packageOwnedCollectionKeys keeps a module-scope `export` because the test imports it by module path — the dispatch's two clauses ('drop the export' and 'the test imports it from the module path') are mutually exclusive in TypeScript. Module scope is not package surface, and that is what the three surface measurements prove.",
      "tests": "Ledger: 23 rows on origin/main after merging (measured, not recalled: `git show origin/main:packages/cli/test/option-b-reader-acceptance.pin.test.ts | grep -c` = 23), 0 after this PR — pin green, Test Files 1 passed (1) / Tests 7 passed (7) at head 38d3f248b. PUBLISHED SURFACE, three independent measurements: (a) `git diff fbecffe1d --stat -- packages/runtime/src/index.ts packages/core/src/index.ts packages/runtime/package.json packages/core/package.json` prints nothing; (b) after a full build, importing the two files runtime's `exports` map names — ESM dist/index.js 243 exports / 0 hits for either symbol, CJS dist/index.cjs 243 exports / 0 hits, with three positive controls present (AppPlugin, resolveArtifactPackageOrder, createStandaloneStack) so the zero is a measurement and not an empty probe; (c) no `declare function|const|type|class` for either symbol in dist/index.d.ts or dist/index.d.cts — the single textual hit is a JSDoc line on a private class member. `pnpm check:published-files` exit 0. ABLATION A (acceptance pin, dist-mediated, BOTH legs rebuilt): mutate — marker on disk (count 1) and `git hash-object` off the HEAD blob, `pnpm --filter @objectstack/runtime build` exit 0, `node scripts/ablation-dist-preflight.mjs @objectstack/runtime OPTION_B_ABLATION_15005_NEUTERED` = 'marker present in 2 built files'; pin then 1 failed / 6 passed naming exactly 23 rows, and `diff` against the ledger at fbecffe1d shows the two sets IDENTICAL byte for byte; restore — hash back to the HEAD blob, whole-tree `git status --porcelain` empty, residual markers 0, rebuild exit 0, preflight `--absent` = 'marker absent from all 6 built files'; pin then 7 passed. ABLATION B (the new refusal; the test imports the module by relative path so vitest compiles SOURCE and dist is not consulted — stated, no rebuild leg): with the divergence detection removed (marker on disk, hash off the HEAD blob) exactly the two refusal tests go red and the other 12 stay green including the anti-vacuity control and all three identity controls; restored, hash back to the HEAD blob and `git diff HEAD` empty. IDENTITY CONTROLS, each measured in a verbose run: (1) additive artifact returns by reference — `resolved.objects` toBe input array, `resolved.datasourceMapping` toBe input array, `resolved` toBe the artifact; (2) `packages: []` returns unchanged — this control was MISSING and was ADDED here (`[]` IS an array, so it does not short-circuit; it walks the whole resolution and must still come back as the same object), asserted with and without collections present; (3) no `packages` key short-circuits — toBe on a single-package artifact, null, undefined, a string, and a non-array `packages`. SUITES, whole, not narrowed: @objectstack/runtime 224 files / 3191 tests passed; @objectstack/cli 245 files / 2854 passed + 6 expected fail; @objectstack/core 48 files / 1159 passed (= main's 49/1170 minus exactly the moved file and its 11 tests). TYPECHECK: runtime + core + cli exit 0, check:test-typecheck OK for all three with byte-identical ledgers (core 4/4, runtime 27/191, cli 3/28); that the moved and new test files are actually CHECKED is measured — `tsc --listFiles -p tsconfig.test.json` names artifact-collections.ts, artifact-collections.test.ts and app-plugin.option-b-packages.test.ts among 304 src files. GATES: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` derived three times (before, after, at final head) — byte-identical each time, 87 unique commands over the same 10 paths; 74 ran locally, all green, every exit code captured before any pipe. Two initially reported PREREQUISITE NOT MET from unbuilt unrelated packages (check:published-readme-exports, check:dual-build-cjs-loads) and were re-run green after building — NOT counted as failures. Three cannot run outside CI and measured nothing here: check-partof-closing-keyword and check-single-claim-paths (no PR_NUMBER/PR_BODY) and spec check:react-declaration-parity (needs objectui's sdui.manifest.json); their self-tests pass. `pnpm lint` (eslint . --no-inline-config) repo-wide, NOT narrowed, exit 0.",
      "mcp_calls": "3 — one update_pull_request that was superseded, one final update_pull_request, and this comment. Everything else went through git and the public-repo zero-quota HTML payload (the REST probe returned 403 'GitHub access is not enabled for this session', so this seat has no REST channel; declared rather than assumed).",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code


    Generated by Claude Code

  5. hotlong commented on Sep 4, 2026

    @hotlong
    ContributorAuthor

    os-dev-report

    {
      "issue": 15005,
      "status": "done",
      "branch": "claude/issue-15005-runtime-packages-reader",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/15261",
      "premise_still_valid": true,
      "summary": "Follow-up round: the one line the PASS review asked to close, then CI, then ready. THE LINE: the BASELINE test's anti-vacuity guard was `expect(additive.rows.length).toBeGreaterThanOrEqual(OPTION_B_LOSSES.length)`, which this PR turned into `rows.length >= 0` — true of every array — when it emptied the ledger. RE-ANCHORED rather than deleted, because none of the three controls that survive an empty ledger covers this direction: the registryObjectsFromArtifact CONTROL asserts two object names, and the two coverage tests assert the five boundaries and #15006's four sites are represented; none of them notices rows disappearing, which is exactly the fourth direction the file's own header claims. New floor is 30, MEASURED not remembered, and it is live at its boundary. `>=` rather than `toBe` keeps the same shrink-only direction the ledger uses: a row added to the probe stays green, a row that stops being measured is red, with a failure message that says so. NOT touched, per the instruction: the set-equality assertion, the registryObjectsFromArtifact CONTROL, the five-boundary coverage test, the #15006 four-site coverage test, and the ledger itself. Then CI on head c953ac0f8 went fully green and the PR is flipped to ready (`draft: false`, `mergeable_state: clean`). ⛔ auto-merge NOT armed — that is the PM's action, and `needs:contract-review` is left on both carriers for the PM to remove.",
      "tests": "MEASUREMENT OF THE FLOOR: with the line temporarily written `expect(additive.rows.length).toBe(-1)`, the run reports `AssertionError: expected 30 to be -1` — so 30 is read off the probe, not recalled from 24 or 28. BOUNDARY REVERSE-VERIFICATION (the floor is live, not satisfied by construction): floor 30 → `Test Files 1 passed (1) / Tests 7 passed (7)`; floor 31 on the SAME fixture → `Test Files 1 failed (1) / Tests 1 failed | 6 passed (7)` with the new message firing verbatim (`... expected 30 to be greater than or equal to 31`). Both mutations proved on disk before being measured (injected-marker count 1, removed-text count 0, `git hash-object` moved off the baseline) and both restored to a byte-identical file afterwards (hash back to the baseline, residual marker count 0, `git diff HEAD --stat` empty). LOCAL RE-RUN AT HEAD c953ac0f8: acceptance pin 7 passed (7); `pnpm --filter @objectstack/cli typecheck` exit 0 with `check:test-typecheck: OK` and its ledger unchanged at 3 files / 28 errors / 6 pinned signatures; `pnpm lint` (`eslint . --no-inline-config`) repo-wide, NOT narrowed, exit 0; gate family re-derived with `--repo objectstack-ai/objectstack` and byte-identical to all three earlier derivations (87 unique commands, same 10 paths); check:nul-bytes, check:cross-package-test-inputs, check:test-source-alias, check:type-source-resolution, check:error-code-casing, check:dispatcher-error-vocabulary all exit 0. CI AT c953ac0f82df353f9efbeb55cd994f9d9ccd1e9c: 36 check runs, all `status: completed` — 33 `success`, 3 `skipped` (Build Docs, Console Pin Gate, Packed-tarball smoke — path-filtered, not hidden failures), ZERO failure/cancelled/timed-out. Named greens include Lint & Repo Gates, Type Check · workspace / source gates / consumer gates / debt ledger, Test Core 1..6/6, Dogfood Regression Gate 1..3/3, Dogfood Verify CLI, Temporal Conformance (live PG + MySQL), Build Core, Check Changeset, Check PR Size, Governed Surface Queue Guard, Part-of PR must not also close its card, and both single-claim guards. Commit status rollup `state: success`. Polling was foreground and zero-quota (the PR's checks route serves a rendered fragment carrying the head sha and a pending/success/failure favicon), so no quota was burned waiting. PR then flipped to ready and read back: `draft: false`, `mergeable_state: clean`, head c953ac0f8, labels still carry `needs:contract-review`. Worktree torn down afterwards (node_modules removed, `git worktree remove` without --force, tree clean and HEAD equal to origin beforehand).",
      "mcp_calls": "5 this round — update_pull_request (body), pull_request_read get_status, pull_request_read get_check_runs, update_pull_request (draft:false), add_issue_comment (this report). Whole-card total across both rounds: 14. CI waiting cost zero MCP calls: it ran on the public-repo zero-quota checks fragment, with the two MCP reads used only once at the end to confirm the rollup per-job rather than by favicon alone.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code


    Generated by Claude Code

  6. github-actions commented on Sep 6, 2026

    @github-actions
    Contributor

    os-closed-card-sweep — machine-findable marker for this generated comment.

    Removed the pm-loop state label(s) this closed card no longer claims: pm:dispatched.

    A state label claims work is in flight. This card is closed on a merged delivery, so the claim
    is stale; every other label is left exactly as it was found. Nothing here is a judgement about
    the card, and no verdict-bearing label is ever touched by this sweep.

    posted by half-state-patrol run 34005012908 · trigger schedule

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions