Skip to content

CI: a pull request that edits only the MCP server's SKILL.md renderer skips the Console test that pins its download mirror #31017

Closed

Description

@objectstack-fleet

domain:ui#2 · os-tesla · session_01L9qibw7DekEe3wx5f3zphf

Filing gate: ① a named location. This is an out-of-scope finding from PR #31015 (card #30865), raised by the card thread (os-dev-report 6691357143, carrier: seat). ⛔ Not a claim. Triage sets the grade and the lane.
class: b · reach: every future edit to packages/mcp/src/skill-md.ts that lands without the Console mirror; NOT MEASURED in CI (read from .github/workflows/ci.yml on the PR branch 828224c8).

Business reason

#30865 happened because the Console's "Download skill" SKILL.md drifted from the one the MCP server serves. After #30861 the download taught a delete_record call the server refuses, so an agent following it failed every delete. PR #31015 makes the mirror byte-identical and adds a drift pin: ui/apps/console/src/pages/developer/objectstack-skill.test.ts compares the download with renderSkillMarkdown from packages/mcp/src/skill-md.ts. That pin only runs when Test UI runs. A pull request that edits only skill-md.ts matches neither the ui nor the ui_consumers filter, so Test UI skips. The ui filter is ui/** plus root build files; ui_consumers is spec, client, core, formula, lint, sdui-parser and types, and not packages/mcp. Per the filter's own comments, the queue reads the same diff, so its entry skips too. The drift lands, and the same broken download can ship again until some later run of the full ui suite reds on main.

Where

Wanted

A change to packages/mcp/src/skill-md.ts runs the Console test that pins its mirror, on the PR and in the queue. One possible fix is a ui-filter row for that one file, with a comment naming the pin. Another is an equivalent pin on the packages/mcp side that Test Core runs. Whichever is chosen, check:ci-filter-parity and check:cross-package-test-inputs must stay green.

Activity

  1. added
    enhancementNew feature or request
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    domain:devxDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Nov 6, 2026
  2. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: audit · p2 · domain:devx · 2026-11-06T17:55Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 7, 2026
  4. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#2 · marchtian · session_017ihL2ebbZkr2QAEG1x7UC8

    Claim: PM loop round 1
    Session: session_017ihL2ebbZkr2QAEG1x7UC8
    Account: marchtian
    Branch: claude/issue-31017-skill-md-runs-console-pin
    Worktree: objectstack-issue-31017
    Domain: domain:devx
    Seat: domain:devx#2
    File surface:

    • .github/workflows/ci.yml, job filter: route packages/mcp/src/skill-md.ts onto the path that runs the Console mirror pin (ui/apps/console/src/pages/developer/objectstack-skill.test.ts), with a comment naming the pin. Or the card's alternative, an equivalent pin on the packages/mcp side, whichever keeps the change smallest and the parity checks green.
    • Plus whatever pin or self-test a gate derives from it (check:ci-filter-parity, check:cross-package-test-inputs).
      Container & model: S, mode:subagent
      Clause-②: no
      Metadata-protocol: none
      Responsibility: n/a — CI routing; independent contract review before ACCEPT
      Thread-read: none
      Premise: holds. At origin/main 5f00374492:
    • the ui (ci.yml:547) and ui_consumers (:590) path lists name nothing under packages/mcp;
    • the pin landed with PR fix(console): the skill download teaches delete_record confirm: true and mirrors the served SKILL.md #31015 (merged 2026-11-06T18:24Z).
      Serial constraints cleared: fix(console): the skill download teaches delete_record confirm: true and mirrors the served SKILL.md #31015 has landed, and no open PR touches ci.yml or packages/mcp/src/skill-md.ts.
  5. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

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

    {
      "issue": 31017,
      "status": "done",
      "branch": "claude/issue-31017-skill-md-runs-console-pin",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/31138",
      "head": "8e90ef14f50d45643baa26327a27e7c47c6b3fb7",
      "session": "session_017ihL2ebbZkr2QAEG1x7UC8",
      "premise_still_valid": true,
      "change": "packages/mcp/src/skill-md.test.ts gains a top-level describe that imports the Console mirror (ui/apps/console/src/pages/developer/objectstack-skill.ts) from source and pins the identity constants and five renders byte-identical to renderSkillMarkdown, the same table the Console pin uses. The new cross-package edge is declared in all four places: CROSS_PACKAGE_TEST_INPUTS (@objectstack/mcp), turbo.json @objectstack/mcp#test inputs, one ci.yml crosspkg row whose comment names the Console pin and #30865, and the check-ci-filter-parity rollback battery, where the new member is recorded by name (21 to 22). packages/mcp/tsconfig.test.json widens rootDir to ../.. (the cli/client shape) because the import was 1 x TS6059, and the paragraph saying rootDir needs no widening is rewritten. Strictness is untouched, and the ledger still holds 53 errors in 6 files. No job, if: or timeout changes.",
      "chosen_fix": "(b), the mcp-side pin. (a) is the smaller diff, but it covers exactly one file. The default render also reads DELETE_RECORDS_MAX_PER_CALL from packages/mcp/src/mcp-http-tools.ts, which is the same drift one import away. That file had 30 commits on main from 2026-09-07 to 5f00374492, against 13 for skill-md.ts, so covering it under (a) would start the ui lane on most MCP PRs. The ui output also starts Lint UI, Type Check UI, Build UI Deps, Build & E2E UI and 16 Test UI shards, not only Test UI. In that window, 4 of the 13 skill-md.ts commits touched no ui or ui_consumers path, so they would have started the whole lane only for this. (b) starts no new job on a packages/mcp diff, because core already starts Test Core and turbo ls --affected already selects @objectstack/mcp. It guards the whole render closure. Its price is one declared cross-package read: a mirror-only diff now also starts Test Core with @objectstack/mcp unioned in, and the mirror has 3 commits on main since the ui/ import.",
      "proof": "(1) Filter evaluation with picomatch 4.0.7, dot:true, over the filter job's own lists. At HEAD, packages/mcp/src/skill-md.ts gives core=true ui=false ui_consumers=false crosspkg=false, so Test Core starts. The mirror gives crosspkg=true ui=true; on origin/main it gave crosspkg=false. (2) turbo ls --affected on a throwaway local commit that changes only skill-md.ts (base 5f00374492): 14 packages, @objectstack/mcp included. The probe was never pushed and its worktree is removed. --union-into for a mirror-only diff printed '+ @objectstack/mcp (declared glob matched ui/apps/console/src/pages/developer/objectstack-skill.ts)'. (3) A test that fails on a deliberate drift, through scripts/ablation-replace.mjs: blob mutated, then restored, with the hash equal to HEAD and git diff HEAD empty. Leg 1 adds ' (DRIFT)' to a line of the skill-md.ts render: src/skill-md.test.ts 5 failed | 11 passed, all five 'renders the served text for ...' cases. Leg 2 changes DELETE_RECORDS_MAX_PER_CALL from 200 to 250 in mcp-http-tools.ts: 5 failed | 11 passed. Restored: 16 passed. (4) Before this fix, the Test UI selector run on the same skill-md.ts-only probe already lists the Console pin as always-on ('reaches the repository root outside apps/console', 691 of 6641 files, mode=affected). So the only gap was that Test UI never started.",
      "parity": "pnpm check:cross-package-test-inputs :: exit 0. 'All 261 self-test cases passed.' 'OK: 32 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob (6 of them on a split \"test:repo\" task); 19 walked root(s) judged, 3 on ACCEPTED_WALK_RADII; 4523 test file(s) import a workspace sibling by bare specifier over 471 package pair(s), every one declared.' | pnpm check:ci-filter-parity :: exit 0. '--self-test: 141 assertions' 'OK: all 219 declared cross-package glob(s) (161 unique) are covered by core or crosspkg, every crosspkg entry still covers one, and the test job's if: still names both filters.' Before the battery row was added, the self-test was red (1 of 140: 'rolling crosspkg back ... got 22'). That is the registry row the order anticipated.",
      "gates": {
        "local_head": "8e90ef14f5",
        "package": [
          "pnpm --filter @objectstack/mcp exec vitest run --maxWorkers=2 :: exit 0 (Test Files 60 passed (60), Tests 768 passed (768); lock VERDICT command-exit 0)",
          "pnpm --filter @objectstack/mcp run typecheck :: exit 0 (check:test-typecheck OK, 6 file(s) / 53 error(s) / 8 pinned signature(s))"
        ],
        "derived": [
          "node scripts/check-closing-keyword-parity.mjs :: exit 0",
          "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
          "node scripts/check-comment-mask-adoption.mjs :: exit 0",
          "node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
          "node scripts/check-comment-mask-corpus.mjs :: exit 0",
          "node scripts/check-declaration-mirrors.mjs :: exit 0",
          "node scripts/check-declaration-mirrors.mjs --self-test :: exit 0",
          "node scripts/check-dts-emitted.mjs --self-test :: exit 0",
          "node scripts/check-issue-citations.mjs :: exit 0",
          "node scripts/check-plugin-teardown-shape.mjs :: exit 0",
          "node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
          "node scripts/check-self-test-wired.mjs :: exit 0",
          "node scripts/check-self-test-wired.mjs --self-test :: exit 0",
          "node scripts/check-self-test-workflow-commands.mjs :: exit 0",
          "node scripts/check-self-test-workflow-commands.mjs --self-test :: exit 0",
          "node scripts/check-step-collectors.mjs :: exit 0",
          "node scripts/check-step-collectors.mjs --self-test :: exit 0",
          "node scripts/check-whole-set-label-write.mjs :: exit 0",
          "node scripts/check-whole-set-label-write.mjs --self-test :: exit 0",
          "node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0",
          "node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0",
          "node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0",
          "node scripts/ci/scheduled-full-run.mjs --self-test :: exit 0",
          "node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
          "node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
          "node scripts/pm/bare-root-worklist.mjs --self-test :: exit 0",
          "node scripts/pm/ci-failure.mjs --self-test :: exit 0",
          "pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
          "pnpm check:agent-test-spelling :: exit 0",
          "pnpm check:aggregator-roster :: exit 0",
          "pnpm check:bash32-floor :: exit 0",
          "pnpm check:ci-filter-parity :: exit 0",
          "pnpm check:cli-command-ids :: exit 0",
          "pnpm check:closed-ceremony-text :: exit 0",
          "pnpm check:cross-package-test-inputs :: exit 0",
          "pnpm check:declared-population-live :: exit 0",
          "pnpm check:doc-authoring :: exit 0",
          "pnpm check:driver-memory-census :: exit 0",
          "pnpm check:dts-closure :: exit 0",
          "pnpm check:dual-build-cjs-loads :: exit 0",
          "pnpm check:engine-double-contract :: exit 0",
          "pnpm check:entry-guard :: exit 0",
          "pnpm check:gitlink-declared :: exit 0",
          "pnpm check:issue-citations :: exit 0",
          "pnpm check:keyed-text-bounds :: exit 0",
          "pnpm check:lean-entry-closure :: exit 0",
          "pnpm check:logger-receiver-detach :: exit 0",
          "pnpm check:node-version :: exit 0",
          "pnpm check:nul-bytes :: exit 0",
          "pnpm check:objectql-double-limit :: exit 0",
          "pnpm check:org-identifier :: exit 0",
          "pnpm check:page-declaration-shape :: exit 0",
          "pnpm check:parse-guard :: exit 0",
          "pnpm check:platform-object-tenancy-census :: exit 0",
          "pnpm check:pm-close-cards :: exit 0",
          "pnpm check:pm-dispatch-gates :: exit 0",
          "pnpm check:pm-expected-skips :: exit 0",
          "pnpm check:pm-fleet-write-dispatch :: exit 0",
          "pnpm check:pm-fleet-write-execute :: exit 0",
          "pnpm check:pm-fleet-write-validate :: exit 0",
          "pnpm check:pm-governed-merges :: exit 0",
          "pnpm check:pm-issue-transfer :: exit 0",
          "pnpm check:pm-post-stamped :: exit 0",
          "pnpm check:pm-record-recognisers :: exit 0",
          "pnpm check:pnpm-acquisition :: exit 0",
          "pnpm check:pnpm-filter-targets :: exit 0",
          "pnpm check:pnpm-flag-spellings :: exit 0",
          "pnpm check:published-files :: exit 0",
          "pnpm check:query-options-erasure :: exit 0",
          "pnpm check:ratchet-remedy-authority :: exit 0",
          "pnpm check:refd-timer-probe :: exit 0",
          "pnpm check:registry-log-declared :: exit 0",
          "pnpm check:required-contexts :: exit 0",
          "pnpm check:rest-log-spy-declared :: exit 0",
          "pnpm check:scripts-symbol-anchors :: exit 0",
          "pnpm check:shard-attestation :: exit 0",
          "pnpm check:slot-lookup :: exit 0",
          "pnpm check:sourcemap-no-sources-content :: exit 0",
          "pnpm check:stall-guard-budget :: exit 0",
          "pnpm check:stall-guard-headroom :: exit 0",
          "pnpm check:system-context-census :: exit 0",
          "pnpm check:test-source-alias :: exit 0",
          "pnpm check:tier-file-adoption :: exit 0",
          "pnpm check:turbo-task-graph :: exit 0",
          "pnpm check:type-check-coverage :: exit 0",
          "pnpm check:type-check-debt :: exit 0",
          "pnpm check:undeclared-dep-imports :: exit 0",
          "pnpm check:vouch-for-reference-callers :: exit 0",
          "pnpm check:watch-hint-literal :: exit 0",
          "pnpm check:where-matcher :: exit 0",
          "pnpm check:workflow-status-functions :: exit 0",
          "pnpm check:workflow-step-name-quoting :: exit 0"
        ],
        "note": "check:dual-build-cjs-loads and check:lean-entry-closure first exited 3 (PREREQUISITE NOT MET, no dist). After a full turbo build (--concurrency=2, docs excluded, lock VERDICT command-exit 0), both reran exit 0. The record above carries the rerun codes.",
        "ran_reconciliation": "Run reconciliation — 92 derived, 92 run, 0 NOT-MEASURED, 0 UNRUN. dispatch-gates --ran: 92 accounted, a DERIVED zero (all 92 recorded an exit code, none is 3).",
        "ci": "At report time, PR #31138 head 8e90ef14f5 shows Check Changeset success; filter, Lint, Type Check, Governed Surface Queue Guard and the PR-body guards are in_progress. The CI verdict is not measured here, and convergence is the seat's."
      },
      "files_changed": [
        ".github/workflows/ci.yml",
        "packages/mcp/src/skill-md.test.ts",
        "packages/mcp/tsconfig.test.json",
        "scripts/check-ci-filter-parity.mjs",
        "scripts/cross-package-test-inputs.mjs",
        "turbo.json"
      ],
      "changeset": "skip-changeset, carried on pr_create. The house rule is that a published file is one that ships in files[]. @objectstack/mcp ships dist, README.md and CHANGELOG.md. After pnpm --filter @objectstack/mcp build, the new describe title and the mirror path have 0 hits in dist, against the positive control renderSkillMarkdown (4 files). The other five files are CI and root config, which are fast-lane non-published.",
      "deviations": [
        "The merge of origin/main before the PR was a no-op: 'Already up to date', and ls-remote main is 5f00374492, the branch point.",
        "The branch keeps a first commit titled 'wip(mcp): ...' (fdf24e7b11), pushed before the build per AGENTS.md. It was not rewritten.",
        "A throwaway detached worktree in the scratchpad held one local probe commit (skill-md.ts plus one newline, committed with --no-verify) to measure the ui selector and turbo affected. It was never pushed and the worktree is removed.",
        "The Console pin (ui side) was not rerun locally because its file is unchanged. Test UI runs on this PR because turbo.json is in the ui filter.",
        "test:repo was not run locally. It belongs to CI.",
        "The PR body ends with the order's line '🤖 Generated with [Claude Code](https://claude.com/claude-code)' in place of the AGENTS.md session-URL footer form. The order's two attribution lines head the body, as ordered."
      ],
      "open_questions": [
        {
          "question": "Accept fix (b), the mcp-side pin plus the declared edge, over (a), the ui filter row?",
          "options": [
            "A: keep (b). Every packages/mcp change, the DELETE_RECORDS_MAX_PER_CALL closure included, runs the pin with no new job start. A mirror-only diff also starts Test Core.",
            "B: switch to (a). One ci.yml row covers skill-md.ts only, starts the ui lane on about 4 of 13 such PRs, and leaves the mcp-http-tools.ts constant unguarded."
          ],
          "recommendation": "A, because it closes the defect class at no new job start, and B would need a second, high-traffic ui row to match it."
        }
      ],
      "out_of_scope_findings": [],
      "security_findings": "none",
      "mcp_calls": "0",
      "api_writes": "2 relay strokes. (1) pr_create, as POST /repos/objectstack-ai/objectstack/dispatches (relay run 42379953141). It created PR #31138 (draft) and wrote the label leg skip-changeset. Read back: 12148 bytes sent and stored, identical; assignees none; labels [skip-changeset]. (2) This os-dev-report comment, through post-stamped.mjs --comment=31017. git push x2 is not a REST write.",
      "filed_issues": [],
      "dogfood_battery": "n/a — no '!' in the PR title and no (narrowing) arm"
    }
  6. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

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

    {
      "round": 2,
      "delta_of": "os-dev-report 6707959593",
      "head": "2760301b1e257f3ca63a32a6a2b6a13613e867ee",
      "change": "Round 2, comment only (contract review should-fix 2). The header of ui/apps/console/src/pages/developer/objectstack-skill.ts now names both readers. objectstack-skill.test.ts beside it imports the canonical renderer and runs when Test UI does. packages/mcp/src/skill-md.test.ts imports this file and runs in Test Core on every packages/mcp change. The header also states the rule: the file stays import-free, or every import must resolve from packages/mcp's test program (tsconfig.test.json), because that program compiles it without the Console's aliases, dependencies or DOM types (#31017). No code change. Fix (b) kept.",
      "files_changed": [
        ".github/workflows/ci.yml",
        "packages/mcp/src/skill-md.test.ts",
        "packages/mcp/tsconfig.test.json",
        "scripts/check-ci-filter-parity.mjs",
        "scripts/cross-package-test-inputs.mjs",
        "turbo.json",
        "ui/apps/console/src/pages/developer/objectstack-skill.ts"
      ],
      "gates": {
        "local_head": "2760301b1e",
        "package": [
          "pnpm --filter @objectstack/mcp exec vitest run --maxWorkers=2 src/skill-md.test.ts :: exit 0 (16 passed)",
          "pnpm --filter @objectstack/mcp run typecheck :: exit 0 (6 file(s) / 53 error(s) held)"
        ],
        "derived_new_vs_round_1": [
          "node scripts/check-sdui-manifest.mjs :: exit 0",
          "node scripts/check-sdui-manifest.mjs --self-test :: exit 0",
          "pnpm --dir ui exec vitest run scripts/ :: exit 0",
          "pnpm check:dispatcher-error-vocabulary :: exit 0"
        ],
        "derived_all": "96 commands, all exit 0, recorded in the run log. The 92 from round 1 were rerun on the new head, and check:cross-package-test-inputs and check:ci-filter-parity each exit 0 there.",
        "note": "In the sweep, check:type-check-debt exited 3 because of a verify-lock queue-timeout (exit 99, another holder's full build), so nothing was measured. Rerun under the lock with a slot name, it exits 0: 'OK — 128/131 workspace packages type-checked ... 0 raw tsc error(s)'. The record carries the rerun code.",
        "ran_reconciliation": "Run reconciliation — 96 derived, 96 run, 0 NOT-MEASURED, 0 UNRUN; a DERIVED zero (all 96 recorded an exit code, none is 3)."
      },
      "deviations": [
        "None new. The PR body footer is left as is, per the order."
      ],
      "api_writes": "1 more relay stroke: this delta comment through post-stamped.mjs --comment=31017. 1 more git push. The PR body is not touched.",
      "mcp_calls": "0"
    }
  7. objectstack-fleet commented on Nov 7, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:devx#2 · marchtian · session_017ihL2ebbZkr2QAEG1x7UC8

    Landed · #31017 · PR #31138

    • Merged through the queue at 2026-11-07T16:34Z as 962ea9d0be. Tier H: os-zhuang approved and enqueued it. The contract review PASSed (6708693885), and the seat ACCEPTed (6708747421).
    • A diff confined to packages/mcp now runs the Console SKILL.md mirror pin, inside Test Core's skill-md.test.ts. A diff confined to the mirror starts Test Core too, through the crosspkg row.
    • The mirror ui/apps/console/src/pages/developer/objectstack-skill.ts must stay import-free: its header says why.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:devxDomain lane — seat card indexed by label:pm:seatenhancementNew feature or requestpriority:p2Medium: important, M3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions