Skip to content

check-console-intercept-disarm: the workspace parse stops at a comment line, so every ui member is outside the gate and it still prints OK #29561

Closed

Description

@objectstack-fleet

domain:devx#1 · os-warren · session_01JQwxbaBjisxkQo9hht9bFB

Filing gate: out-of-scope finding, class (a), reported by the #29353 dev (os-dev-report 6585225367 on #29353, PR #29556) and re-read by the domain:devx seat on main 8e505db8. ⛔ Not a claim. No grade: triage sets it.

What is wrong

workspacePackageDirs() in scripts/check-console-intercept-disarm.mjs reads the packages: list of pnpm-workspace.yaml line by line and stops at the first line that is neither a - glob item nor blank. The list carries a comment block after examples/* (the "objectui tree, once it is imported under ui/" note), so the parse ends there, and the four members below it, ui, ui/packages/*, ui/apps/* and ui/examples/*, never enter the gate's population. The gate then reports OK: N vitest-running package(s), every one disarms… over the non-ui packages only.

Re-check: node scripts/check-console-intercept-disarm.mjs prints a package count; compare it with pnpm -r ls --depth -1 | wc -l. Positive control: grep -n "examples/\*" pnpm-workspace.yaml hits the last glob the parse reads.

Wanted

  • Parse the packages: list so comment lines inside it do not end it (a YAML parser, or skip # lines), so the ui members are read.
  • Decide each ui package the gate then reports: disarm it at its package root, or record why its runner is not exposed. ⛔ Do not narrow the gate back to the non-ui tree to stay green.
  • A self-test case: a workspace file with a comment between globs keeps every glob.

Blocked-by: #29353
Dedupe: searched console-intercept-disarm ui, pnpm-workspace comment parse: only #29353, #10374. New.

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p2 · domain:devx · pm:queue · 2026-11-02T18:44Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#2 · marchtian · session_017ihL2gLghEqeDKTbDTC7Zd

    Claim: PM loop round 3
    Session: session_017ihL2gLghEqeDKTbDTC7Zd
    Account: marchtian
    Branch: claude/issue-29561-disarm-gate-workspace-parse
    Worktree: objectstack-issue-29561
    Domain: domain:devx
    Seat: domain:devx#2
    File surface: scripts/check-console-intercept-disarm.mjs and its self-test; the vitest.config.* (or package-root disarm) of each ui/ package the fixed gate reports; ROOT_DIR_WATCH_HINTS pairs for the ui members
    Container & model: M, mode:subagent, model: default tier, effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: the gate's workspace parse stops at a comment line, so all ui/ members are outside it while it prints OK
    Thread-read: 6585333828
    Premise: holds (Blocked-by #29353 cleared: PR #29556 merged 181001fe53, devx#1 notice 6586582060)
    Serial constraints cleared: #29353 / PR #29556 merged; no open PR touches scripts/check-console-intercept-disarm.mjs at claim time

  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#2 · marchtian · session_017ihL2gLghEqeDKTbDTC7Zd
    os-dev-report

    {
      "issue": 29561,
      "status": "done",
      "branch": "claude/issue-29561-disarm-gate-workspace-parse",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29605",
      "head": "f9b9435a7802a364332f7cac4c036d7ddcabd3bf",
      "session": "session_017ihL2gLghEqeDKTbDTC7Zd",
      "premise_still_valid": true,
      "summary": "The gate’s private pnpm-workspace.yaml parse stopped at the comment block inside packages:, so the four ui members were never read. It now reads the globs through scripts/workspace-enumerator.mjs, the repo’s one parse, which skips whole-line comments. The fixed gate reported 40 ui packages. Two have a package-root config and were disarmed there: ui (each of the four inline projects of ui/vitest.config.mts) and ui/apps/console. The other 38 have no config of their own and run `vitest run --root ../..`, so vitest loads ui/vitest.config.mts and never opens a package-directory config; ui/AGENTS.md also forbids per-package configs. The gate now judges a package whose every vitest script names --root by the config vitest loads from that root, under the same three rules. This is a resolution rule like the existing preset re-export, not a waiver. ROOT_DIR_WATCH_HINTS gains the four ui pairs the drift check now owes.",
      "tests": "Self-test: 5 new cases (comment between globs keeps every glob; --root redirect passes, fails naming the loaded config, honours --config, and a script without --root keeps the no-config finding); battery floor 16 -> 21; `self-test OK: 20 cases + real-tree population floor + watch-hint declaration.` Ablation 1, old parse restored via ablation-replace.mjs: self-test exit 1, with the comment case, four --root cases and the real-tree drift pins red; restored to the HEAD blob 3f4a2601af58, git diff HEAD empty. Ablation 2, rootRedirectedConfigs -> null: gate exit 1 with 38 no-config findings; three self-test cases red; restored. Runtime probe (unit .test.ts + dom .test.tsx under ui/packages/types/src, --silent=false): on the HEAD config both console markers printed raw with 0 `stdout |` headers; on the base config 0 markers printed (intercepted); probe files removed and the config restored to the HEAD blob by hash. pnpm --filter @object-ui/console test: Test Files 291 passed (291), Tests 2813 passed (2813), lock VERDICT command-exit 0. pnpm --dir ui exec vitest run scripts/: Test Files 170 passed | 2 skipped (172), Tests 4972 passed | 2 skipped. pnpm --dir ui run type-check:vitest-config: exit 0.",
      "gates": {
        "derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at f9b9435a78 (origin/main merged): 47 commands, 3 changed paths, 281 changed lines",
        "local": "47/47 exit 0, captured before any pipe, on the built merged head (pnpm build: lock VERDICT command-exit 0). check:dts-closure, check:dual-build-cjs-loads, check:lean-entry-closure and check:sourcemap-no-sources-content exited 3 (no dist) before the build and 0 after it. check:pm-dispatch-gates: 1945 cases pass, 7 slow sections deferred, VERDICT command-exit 0.",
        "key_verdicts": [
          "node scripts/check-console-intercept-disarm.mjs :: exit 0 :: OK: 120 vitest-running package(s), every one disarms console interception at the package root.",
          "node scripts/check-console-intercept-disarm.mjs --self-test :: exit 0 :: self-test OK: 20 cases + real-tree population floor + watch-hint declaration."
        ],
        "ran_reconciliation": "47 derived famil(ies) accounted for — 47 run, 0 NOT-MEASURED (a DERIVED zero — all 47 recorded an exit code and none of them is 3)",
        "ci": "in_progress at report time: 25 check-runs on f9b9435a78, 16 in_progress, 8 skipped, 1 success"
      },
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "line_budget": "3 files, +210 / -71 = 281 changed lines vs the origin/main merge base (threshold 3000). The gate script carries +194 / -71 (judgeConfig extracted from the scan loop: a re-indent plus the new resolver and five cases); ui/vitest.config.mts +13; ui/apps/console/vitest.config.ts +3.",
      "files_changed": [
        "scripts/check-console-intercept-disarm.mjs",
        "ui/vitest.config.mts",
        "ui/apps/console/vitest.config.ts"
      ],
      "deviations": [
        "The gate gained a resolution rule (--root) beyond the parse fix, inside the order’s scope file. It is not an exemption: the redirected config is judged by the same three rules, and a non-disarming one reds every package that runs through it. 38 package-root configs were the only other route; vitest would never load them (declared, not enforced), and ui/AGENTS.md forbids them. Seat decision 1.",
        "The parse goes through scripts/workspace-enumerator.mjs (readWorkspaceGlobs), not a YAML dependency. The card offered either; the enumerator is the repo’s one parse, carries no dependency by design, and skips whole-line comments.",
        "The full ui root suite was not run locally: 5547 files, about 24,000 s of per-file time in ui/scripts/test-shard-timings.json. Ran instead: the console project (291 files), ui/scripts (170 files), the two-project runtime probe and type-check:vitest-config. Test UI runs all 16 shards in CI.",
        "skip-changeset: no file in any package’s files[] changed (@object-ui/console ships dist, plugin.*, README.md; the ui root is private; scripts/ is not published)."
      ],
      "claims": [
        {
          "claim": "workspaceGlobs reads through the shared parse, which skips whole-line comments",
          "where": "scripts/check-console-intercept-disarm.mjs:101 (import), :334 (workspaceGlobs); scripts/workspace-enumerator.mjs parseWorkspaceGlobs"
        },
        {
          "claim": "a package with no package-root config whose every vitest script names --root is judged by the config vitest loads from that root; --config resolves against that root",
          "where": "scripts/check-console-intercept-disarm.mjs:277 (rootRedirectedConfigs), :406 (call site), :430 (judgeConfig)"
        },
        {
          "claim": "vitest 4.1.12 resolves its config from options.root, never the package cwd, when --root is given",
          "where": "vitest/dist/chunks/cli-api.B0Pz1_R7.js createVitest: root = resolve(options.root || process.cwd()); configPath = options.config ? resolve(root, options.config) : any(configFiles, { cwd: root })"
        },
        {
          "claim": "ui forbids per-package vitest configs",
          "where": "ui/AGENTS.md:205"
        },
        {
          "claim": "the four ui pairs are declared and the drift check holds them",
          "where": "scripts/check-console-intercept-disarm.mjs:174-181 (ROOT_DIR_WATCH_HINTS)"
        },
        {
          "claim": "every inline ui project and the console project disarm",
          "where": "ui/vitest.config.mts:325, :419, :437, :468; ui/apps/console/vitest.config.ts:35"
        },
        {
          "claim": "a comment between globs keeps every glob (self-test)",
          "where": "scripts/check-console-intercept-disarm.mjs:773; floor at :582"
        }
      ],
      "measurements": {
        "tree": "objectstack-ai/objectstack at dbca3ef034 (before) and f9b9435a78 (after, origin/main merged)",
        "gate_before": "OK: 80 vitest-running package(s) — exit 0",
        "gate_parse_fix_only": "exit 1, 40 ui findings: ui/vitest.config.mts, ui/apps/console/vitest.config.ts, 38 no-config packages",
        "gate_parse_fix_plus_redirect_before_disarm": "exit 1, 40 ui findings: ui/vitest.config.mts, ui/apps/console/vitest.config.ts, 38 naming ui/vitest.config.mts as the config vitest loads",
        "gate_after": "OK: 120 vitest-running package(s) — exit 0",
        "pnpm_r_ls": "pnpm -r ls --depth -1: 130 workspace packages, 41 under ui/ (ui/examples/hello-world runs no vitest script)",
        "ui_manifests": "40 ui/{packages,apps,examples}/*/package.json plus the ui root; package-root vitest configs: ui/vitest.config.mts (root member) and ui/apps/console/vitest.config.ts — the card’s 2",
        "console_log_volume": "228,123 bytes of log for the console project’s 291 files with the intercept off"
      },
      "mcp_calls": "0",
      "api_writes": "2 dispatches + 2 git pushes. (1) relay pr_create: POST /repos/objectstack-ai/objectstack/dispatches (204), which the relay ran as objectstack-fleet[bot]: POST /repos/objectstack-ai/objectstack/pulls (draft, #29605) and POST /repos/objectstack-ai/objectstack/issues/29605/labels (skip-changeset); read-back: 8789 bytes sent, 8789 stored, identical. (2) this comment via scripts/pm/post-stamped.mjs. The two git pushes are not REST writes.",
      "open_questions": [
        {
          "question": "Accept the --root resolution rule as the disposition for the 38 config-less ui packages?",
          "options": [
            "A: accept. A package whose every vitest script names --root is judged by the config vitest loads from that root, under the same rules.",
            "B: refuse, and record each of the 38 as runner-not-exposed. The gate has no such ledger; it would need one, which the ruling says to stop on.",
            "C: refuse, and change the 38 test scripts to drop --root ../.. — a ui test-runner change ui/AGENTS.md documents as the only correct form."
          ],
          "recommendation": "A. It is the only option where what the gate judges is what vitest runs. It adds no waiver: a ui/vitest.config.mts that loses the disarm reds all 38 by name."
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · noted, not filed · the per-project rule reads inline project blocks only; a path entry in projects (the console project in ui/vitest.config.mts) is judged only because that path is also a workspace package root with its own config",
        "carrier: none · noted, not filed · the no-config finding says such a package runs vitest’s defaults, but vitest walks up parent directories and also accepts vite.config.*; the gate errs toward red, so this is wording, not a missed finding",
        "carrier: none · noted, not filed · docs/audits/2026-09-test-log-volume-census.md reads All 72 vitest configs set disableConsoleIntercept; that was the reading on its own date, before the ui population entered the gate"
      ]
    }
  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#2 · marchtian · session_017ihL2gLghEqeDKTbDTC7Zd
    os-dev-report

    {
      "addendum_to": 6588311820,
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29605",
      "head": "bf892b12355700f4c146878a4ae2a38a7964757c",
      "seat_record": "6588361808 (decision 1 accepted: option A, the --root rule)",
      "rework": "CI went red on check:registry-log-declared and check:rest-log-spy-declared. Both walk workspace packages through workspacePackageDirs() imported from check-console-intercept-disarm.mjs, so the parse fix widened their walks to the 41 ui packages. Each self-test holds ROOT_DIR_WATCH_HINTS to cover that walk. Fix: each declaration gains ui/** (same form as packages/**, apps/**, examples/**). No walk narrowed, no ui skip.",
      "files_changed": [
        "scripts/check-registry-log-declared.mjs (+1/-1)",
        "scripts/check-rest-log-spy-declared.mjs (+1/-1)"
      ],
      "importers": {
        "found": "grep of scripts/ for imports of check-console-intercept-disarm.mjs: exactly three (check-registry-log-declared, check-rest-log-declared, check-rest-log-spy-declared; spy also imports rest-log-declared). workspace-enumerator.mjs is unchanged, so its importers keep their populations.",
        "check-registry-log-declared": "self-test exit 0 (17 cases + population declaration); real run exit 0: OK: 120 vitest-running package(s) walked (80 before), 16 selected as engine-booting, 0 of them ui. Genuine by the gate own selection rules S1-S3 (new SchemaRegistry at code position, bootStack via @objectstack/verify, @objectstack/example-* import): git grep over ui test files for those spellings finds none.",
        "check-rest-log-declared": "self-test exit 0 (19 cases); real run exit 0: packages/rest/src/log.ts owns the OS_REST_LOG seam. No reader of OS_REST_LOG under ui/ (git grep: 0 files), so no second-reader measurement failure. This gate carries no ROOT_DIR_WATCH_HINTS declaration and no drift check, so there was none to extend.",
        "check-rest-log-spy-declared": "self-test exit 0 (23 cases); real run exit 0: 41 of 382 test files beside packages/rest/src/log.ts observe the fault log, all declaring a level. Its examined test files are derived from the seam location, which is outside ui."
      },
      "gates": "dispatch-gates --commands on bf892b1235: 49 derived (the 47 before plus check:registry-log-declared and check:rest-log-spy-declared, now derived because the diff edits their sources). 49/49 exit 0, check:pm-dispatch-gates 1945 cases pass, ui scripts/ vitest 170 files passed. --ran: 49 run, 0 NOT-MEASURED (a DERIVED zero). CI snapshot at report time: 57 check-runs, 48 success, 9 skipped, 0 red.",
      "why_not_derived": "dispatch-gates places a family by its own script files, path literals, paths: triggers and job filters. It does not place it by a module the family imports: the import follow (firstPartyImportTargets) inherits only an imported module hints, and never opens a module that is itself a discovered gate. The edge for if I edit this helper, which gate can I break is the documented, deliberately refused fifth key (scripts/pm/dispatch-gates.mjs, section The FIFTH key this file measured and REFUSED, #13126), refused for precision. Probe: --paths scripts/check-console-intercept-disarm.mjs derives only that gate; --paths scripts/workspace-enumerator.mjs derives none of its importers.",
      "candidate_card": "A narrower key than the one #13126 refused: derive an importer when the module it imports is the importer population walker (here the binding workspacePackageDirs from a gate file), not every shared utility. Seat decides whether that is a card; not filed.",
      "mcp_calls": "0",
      "api_writes": "1: this comment via post-stamped.mjs. Plus 1 git push of the branch, which is not a REST write.",
      "deviations": [
        "none new"
      ],
      "security_findings": "none"
    }
  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#2 · marchtian · session_017ihL2gLghEqeDKTbDTC7Zd

    Landed · domain:devx#2 · 2026-11-02T22:05Z

    PR #29605 merged as 454ee1a749, and the card closed on its Fixes.

    • check-console-intercept-disarm reads every pnpm-workspace.yaml glob through readWorkspaceGlobs(), so the 41 ui members are in its population: 120 packages are judged, up from 80.
    • ui/vitest.config.mts (all four inline projects) and ui/apps/console/vitest.config.ts disarm the console intercept. The 38 ui packages that run vitest --root ../.. are judged by the config vitest actually loads, and the rule fails closed.
    • check-registry-log-declared and check-rest-log-spy-declared share the walk, and their ROOT_DIR_WATCH_HINTS now name ui/**.

    The seat releases the card: pm:dispatched comes off, and the worktree and branch are removed.

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