Skip to content

fix(dogfood): the wall /packages case's operator package declares the CRM dependency its view binds - #24724

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-24700-wall-packages-fixture-closure
Oct 20, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/issue-24700-wall-packages-fixture-closure

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #24700

Clause-②: no

The hourly full run on main (run 39345244575, 5018fc303d) is red in Dogfood Regression Gate (2/3) on one case of packages/qa/dogfood/test/wall-environment-metadata-refusal.dogfood.test.ts. The case is "/packages: each of the thirteen write doors refuses A 403 PERMISSION_DENIED, and B reads the operator's package unchanged", and it fails in both walled postures (isolated and group) at expect(commits.length).toBeGreaterThan(0).

Cause (measured, see Evidence)

  • The case's operator creates com.em.iso.op / com.em.gro.op with no dependencies.
  • It saves a draft list view bound to crm_lead into that package, then calls POST /packages/:id/publish-drafts.
  • Since PR fix(lint)!: the save door refuses a list view written into a package and bound outside its closure #24630 (9f12d06770, the ruled narrowing), a package draft publish judges a list view against the package's closure. crm_lead belongs to com.example.crm, which is outside that closure.
  • The publish therefore answers 200 with data.success: false, outcome: refused, publishedCount: 0.
  • The case's ok() reads only the status, so the refusal surfaced three lines later as zero commits.

The narrowing is ruled and stays. This PR changes one test file and nothing else.

What changes (one case, one file)

  • The operator's package declares the dependency. At POST /packages the package now declares dependencies: { 'com.example.crm': '*' }, in the bare-manifest body the case already sent.
    • dependencies is a declared ManifestSchema row, and PackageInstallManifestSchema extends ManifestSchema.
    • The view stays on crm_lead, so every later line of the case keeps the names it read before: the re-save as draft, the orphan view, the thirteen doors and B's reads. Zero downstream lines change.
    • The other shape, binding the view to an object inside the closure, would have needed a new object in the package and a rename of every crm_lead.em_PREFIX_pv reference in the case.
  • The publish line asserts the receipt, in data: { success: true, outcome: 'published', publishedCount: 1 }, with failed[] as the assertion message.
    • A refused publish now fails at the publish line and names its cause.
    • The top-level success of the 200 envelope is constant, so the assertion reads data, as view-container-cross-package-default.dogfood.test.ts does.
  • CRM_PKG names com.example.crm, which examples/app-crm/objectstack.config.ts declares as manifest.id. This follows the same literal convention as that sibling file's SHOWCASE.

Evidence

Every run used the same command, pnpm exec vitest run --maxWorkers=2 test/wall-environment-metadata-refusal.dogfood.test.ts, run in packages/qa/dogfood under the shared verify lock.

  • The closure was built by pnpm turbo run build --filter=@objectstack/dogfood, the dogfood gate's own build step.
  • The file runs the case in both walled postures, so one run covers both variants the gate runs, plus the single control.
Run Tree Result
R1 (red) base 1c1144fcd, the file as on main 2 failed, 21 passed. In both postures: AssertionError: expected 0 to be greater than 0 at :242:30, the hourly run's line
R2 (cause isolated) same tree and the same main file. Only #24630's rule-context line is removed from packages/lint/src/runtime-gate.ts (the packageScopeInForce(args.packageScope) spread). Lint rebuilt, ablation-dist-preflight --absent green 23 passed
R3 (green) 70fe76cd6, this change 23 passed
R4 (reverse leg) 70fe76cd6 with the dependency emptied (dependencies: {}) 2 failed at the new publish line, :253:10. The message is the refusal: view/crm_lead.em_iso_pv failed author-time validation: 1 issue, views[0].object [list-view-object-outside-closure]. Its hint: "Declare a dependency on the package that defines crm_lead in the dependencies of com.em.iso.op's manifest" (the group posture is the same with em_gro)
R6 (final) a11658eb2, after merging origin/main 78b1a63bc closure rebuilt (66/66), 23 passed
  • Why R2 instead of a run at 9f12d06770^. R2 stands in for that run and is a single-variable control on the current tree. With only the narrowing's line gone, the unchanged case is green. So the narrowing is the case's only cause of red, and no other line of the case is stale against it.
  • Mutation discipline. Each mutation ran through scripts/ablation-replace.mjs (WRAP), was restored and proven hash-equal to HEAD, and left a clean tree.
    • After R2, lint was rebuilt and ablation-dist-preflight found the line back in all four lint dist files.
    • The first R4 attempt was refused by the tool before any run, because its replacement text overlapped the anchor. It ran nothing.
    • No permanent test file was added.
  • Typecheck and gates.
    • tsc --noEmit in packages/qa/dogfood exits 0 on a11658eb2, and --listFiles includes this file.
    • The derived gate families (dispatch-gates.mjs --commands, 55) ran on a11658eb2: 54 exit 0. check:dual-build-cjs-loads exits 3 with PREREQUISITE NOT MET, because it reads every package's dist and eight packages outside the dogfood closure are unbuilt locally. That is NOT MEASURED locally, and CI's Lint & Repo Gates reads it.
    • pnpm lint on a11658eb2: LINT_EXIT=0 (the eslint . --no-inline-config run printed no finding).

Dogfood is not in the PR or queue fast set; it runs on main's hourly full battery. The runs above are the pre-merge reading, and the next hourly run refreshes #24700.

Changeset

None. skip-changeset: the diff is one file under packages/qa/dogfood/test/, @objectstack/dogfood is "private": true, and it ships nothing.

Acceptance notes

  • The other two cases' publish lines still read a refused publish as a write. These are the walled CONTROL: the platform operator writes at every one of these doors and the single (CONTROL) case in this same file. Both were held off by this dispatch, so they are not changed here.
    • An instrumented run of the committed file logged every publish-drafts receipt (R5, restored and proven hash-equal to HEAD). This case's two publishes answer published, publishedCount 1.
    • Three CONTROL publishes answer 200 with success: false, outcome: refused, publishedCount: 0, each with list-view-object-outside-closure: crm_lead.em_iso_pkgv into com.em.iso.opctl, crm_lead.em_gro_pkgv into com.em.gro.opctl, and crm_lead.em_sin_pv into com.em.sin.a.
    • Their status-only ok() reads each as "the operator writes" (walled) or "writes as before" (single), so these controls measure nothing at the publish-drafts door.
    • The same two-line shape applies there: declare com.example.crm at create and assert the receipt. Raised with the seat.
  • ok() stays status-only for every other line. Only this case's publish line reads the receipt.

Generated by Claude Code

… CRM dependency its view binds

The case "/packages: each of the thirteen write doors refuses A ..." saved a
draft list view bound to crm_lead into a package created with no
dependencies. Since the save door judges a package's list view against the
package's closure, publish-drafts refuses that view (200, success: false,
publishedCount: 0) and the case read 0 commits three lines later.

The operator's package now declares com.example.crm, the package that ships
crm_lead, and the publish line asserts the receipt (success, outcome
published, publishedCount 1), so a refused publish fails where it breaks,
naming its cause.

Claude-Session: https://claude.ai/code/session_01LmjU2x1faLZ39DVTFyVca6
Co-authored-by: Claude <noreply@anthropic.com>
…ll-packages-fixture-closure

Claude-Session: https://claude.ai/code/session_01LmjU2x1faLZ39DVTFyVca6
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Oct 20, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

Nothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs.

What this run could not see

Coarse fallback — 0 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 54159fd742e5a79fc10ac41854dba3395e1a1ffe → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

席位核对 · ACCEPT (direct acceptance)

domain:cli seat 2 (#22648) · os-justin · session session_01LmjU2x1faLZ39DVTFyVca6 · 2026-10-20T02:12Z · head a11658eb2c8657ad44c70fb084dc8fef33a89ac6 · claim 6280921751. No contract face (one private test file), so no review of record is owed.

Why direct. The dev (a mode:subagent of this session) was stopped when the host restarted the container, after this PR opened and before its os-dev-report posted. The host said so explicitly. Its worktree survived clean at this head, equal to the remote branch. Per dispatch-runbook.md 〈直接验收兜底〉 the PR body is the report, and the review criteria are unchanged. Landing waits on the CI condition below.

Check Reading
Shape Draft, base main. First line Fixes #24700; Clause-②: no. Assignee os-justin = the card's. skip-changeset is correct: @objectstack/dogfood is private: true. check-governed-merges.mjs --pr 24724: NOT governed, 18 changed lines.
Surface 1 file, the one case the claim names (:236–:253). The narrowing (PR #24630) is untouched. The other cases are held off, as the claim says.
Fix Triage's first shape (6280767644). The operator package declares com.example.crm at create, which examples/app-crm's manifest.id reads. The publish line asserts the receipt (success, outcome, publishedCount) with failed[] as the message, which is triage's "assert the publish answer's success". No downstream line changes.
Evidence The body's runs: R1 is red on base 1c1144fcd at :242:30 in both postures, the hourly run's line. R2 removes only #24630's rule-context line and turns green, so the narrowing is the case's only cause. R3 and R6 are green on the fix, R6 after merging main. R4 empties the dependency and reds at the new publish line with the closure refusal's own hint. Mutations went through ablation-replace.mjs and were restored hash-equal.
Dogfood in CI Dogfood Regression Gate (${{ matrix.shard }}/3) is skipped on PRs; the full dogfood runs on main's hourly battery. So the local runs above are the pre-merge reading, and the next hourly run after this lands is the proof that the card's red has cleared.
Gates Check-runs on this head (38, latest per name), read at this act: 7 success, 8 skipped, 23 in_progress. Landing waits on all of them.

Accepted deviations:

  • check:dual-build-cjs-loads was NOT MEASURED locally. CI's Lint jobs carry it.
  • The report comment is missing because the dev was stopped by the host. The PR body stands in for it.

Out-of-scope dispositions:

Landing: this is the main-red fix, the first PR this lane arms. It goes to the queue by this seat once every check on this head reads success (or an expected skip).


Generated by Claude Code

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

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

hourly full run: red on main (CI)

2 participants