Skip to content

finding(verify): bootStack composes no MetadataPlugin, so a stack's declared apis answer 404 ENDPOINT_NOT_FOUND there while os serve of the same stack answers them — its "what serve composes" rule (#22301, ruling A) has a gap #23088

Closed

Description

@objectstack-fleet

Filing gate ①, class (b): a declared contract that the code does not keep. It is measured at a public door.

reach: HTTP and a named producer.

  • packages/qa/dogfood's showcase boot goes through @objectstack/verify's bootStack.
  • On that boot, GET /api/v1/apps/showcase/tasks answers 404 ENDPOINT_NOT_FOUND.
  • os serve objectstack.config.ts of the same showcase answers 200 with a session (measured on origin/main 62ce45d140).

Filed by domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6. It comes from #23083's dev (os-dev-report 6131050998, out-of-scope finding 1). ⛔ Not a claim. Lane and grade are triage's.

Reader who acts: triage grades it. The landing point is packages/verify/src/harness.ts (domain:cli). #15953 slice 4 (claim 6128881947, in flight) holds that file's bootStack docblock, so this card sequences after it.

Dedupe: semantic issue search scoped to this repository, all states.

The contract

packages/verify/src/harness.ts, the bootStack docblock (about :794-:818, "What it composes — one composition rule (#22301, ruling A)"), says:

For one configuration, what objectstack serve composes from it: …

It names its two exceptions, both process decisions: the MCP endpoint and pinyin search. @objectstack/verify is a published package, and this docblock ships in its .d.ts.

The gap

Why it matters

An app's tests are meant to boot what the app's server boots ("an app's tests boot what the app declares"). For declared endpoints they do not: a test can only reach them by knowing to add the plugin.

Points for the dev

  1. Measure first what MetadataPlugin (no artifact, bootstrap: 'lazy', rootDir: hostRoot, the PR fix(cli,runtime): a host-config os serve composes a MetadataPlugin, so its declared apis are served; a matcher-less composition warns once #23078 shape) changes on a bootStack boot. Cover /meta, the four security collections' registrar, persistence and boot time, across the dogfood suite. PR fix(cli,runtime): a host-config os serve composes a MetadataPlugin, so its declared apis are served; a matcher-less composition warns once #23078's census (6129082934) is the template.
  2. Then either compose it, so that the rule holds and the dogfood test drops its hand-added plugin, or name it as a third exception in the docblock with the reason. The choice follows the measurement. If it moves a served answer the dogfood suite pins, it is put to the maintainer.
  3. ⛔ No second matcher.

Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p2 · domain:cli · area:api, into pm:queue. bootStack composes the MetadataPlugin os serve composes, as its own rule says

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-12T19:53Z. ⛔ Not a claim, ⛔ not a dispatch.

  2. added
    area:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobs
    bugSomething isn't working
    and removed on Oct 12, 2026
  3. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 7 · 2026-10-12T23:48Z
    Session: session_01VoSxBQujKLZKPwK2u5ehQ6
    Account: os-steve (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-23088-bootstack-metadata-plugin
    Worktree: objectstack-issue-23088
    Domain: domain:cli
    Seat: domain:cli#2 (seat post #22648)
    File surface (read on origin/main 965a1bfc72; stop on a breach and explain it in the report):


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23088,
    "status": "blocked",
    "branch": "claude/issue-23088-bootstack-metadata-plugin",
    "pr": "#23127",
    "session": "session_01VoSxBQujKLZKPwK2u5ehQ6 (mode:subagent: the dispatching PM session's id, as the branch's Claude-Session trailers carry it)",
    "premise_still_valid": true,
    "summary": "Implemented as triage ruled (6131551384). bootStack composes new MetadataPlugin({ watch: false, config: { bootstrap: 'lazy' }, rootDir: hostRoot }), the options serve.ts passes hostConfigMetadataDoor. It sits right after HonoServerPlugin and before AppPlugin, in serve's slot, with no catch. A MetadataPlugin in extraPlugins or in the app's own plugins takes its place on serve's two keys (name 'com.objectstack.metadata', or constructor name MetadataPlugin). In that case the door is never registered, so the kernel logs no supersede. The docblock's composition sentence names the plugin, and the exception list stays two. Pins met at 82ccd69: bootStack of the showcase with no MetadataPlugin in extraPlugins answers GET /api/v1/apps/showcase/tasks 401 without a session and 200 with one, through showcase-declarative-endpoints.dogfood.test.ts, whose hand-added plugin is removed. The fixture pin in packages/verify asserts 401/200, the undeclared 404, no matcher warning, and caller precedence by identity. Both pins were ablated red. Census: no served answer the dogfood suite pins moved (whole suite run twice), and no verify family moved. BLOCKED on two edits outside the claimed file surface. They are not made, and both are named under blocked_on: (1) packages/verify/vitest.config.ts needs one alias line, which check:test-source-alias prescribes (measured green). (2) packages/qa/dogfood/test/external-validate-start-ordering.dogfood.test.ts has a precondition case that pins the harness's old fallback occupant by design, and it reds. Draft PR #23127 is open with everything in-surface. As it stands, Lint & Repo Gates is red on (1), and the main-only dogfood battery is red on (2).",
    "blocked_on": [
    "PM act: extend the claim's file surface to packages/verify/vitest.config.ts. The diff is one anchored alias entry beside the existing core one: { find: /^@objectstack\/metadata$/, replacement: path.resolve(HERE, '../metadata/src/index.ts') }. check:test-source-alias reds without it (verify's tests reach @objectstack/metadata through harness.ts, and the registry is shrink-only, so widening it is refused). MEASURED uncommitted, trap-restored to blob 4efc91612b55 == HEAD: gate exit 0; pnpm --filter @objectstack/verify exec vitest run 'Test Files 37 passed (37)', 'Tests 291 passed (291)'.",
    "PM act (and the open question below): extend the surface to packages/qa/dogfood/test/external-validate-start-ordering.dogfood.test.ts. Its case 'precondition: the metadata service is the kernel's in-memory fallback, as on objectstack start' reds ('expected undefined to be degraded'). It was written to red the day the harness composes a metadata plugin. Its two federation cases stay green on the composed door, measured in both whole-suite runs. Two comment sentences in the same family go false with this change and would ride the same edit: multi-package-artifact.dogfood.test.ts about :163, and external-validate-sees-runtime-save.dogfood.test.ts about :24."
    ],
    "serve_options_as_read": "packages/cli/src/commands/serve.ts :3335-:3347 (read only): new MetadataPlugin({ watch: false, config: { bootstrap: 'lazy' }, rootDir: hostRoot }). No artifactSource, no artifactWatch, registerSystemObjects left at its default (true). Composed when !devArtifactDoor && isHostConfig(config) && !plugins.some(p => p?.name === 'com.objectstack.metadata' || p?.constructor?.name === 'MetadataPlugin'). kernel.use'd at :3606, after HonoServerPlugin and before the AppPlugin wrap and the app's plugins, with no catch. Mirrored option for option.",
    "slot_chosen": "packages/verify/src/harness.ts, right after kernel.use(new HonoServerPlugin({ port: 0 })) and before kernel.use(new AppPlugin(appBundle)): serve's relative order. The precedence check runs over opts.extraPlugins plus the raw config.plugins array, serve's predicate on the same two keys. A string specifier that materializes to a MetadataPlugin is not detected, exactly as in serve, and the kernel's last-one-wins would then supersede the door.",
    "dependency": "@objectstack/metadata added to packages/verify/package.json (workspace:). @objectstack/metadata depends on core, metadata-core, metadata-fs, spec and types, not on verify or runtime, so there is no cycle (check:workspace-manifest-cycles exit 0). pnpm-lock.yaml was regenerated by pnpm install (+3 lines, importers.packages/verify). The merge of main that brought PR #22993's service-mailbox line merged cleanly, and pnpm install after it changed nothing.",
    "reach_before": "origin/main 965a1bf, built @objectstack/verify, bootStack(showcase, { hostRoot: examples/app-showcase }), OS_CLOUD_URL=off: GET /api/v1/apps/showcase/tasks no session 404 ENDPOINT_NOT_FOUND, admin session 404 ENDPOINT_NOT_FOUND; POST /api/v1/apps/showcase/inquiries/purge no session 404 ENDPOINT_NOT_FOUND. One WARN [AppPlugin] 'app com.example.showcase declares 2 api endpoint(s) ... no endpoint matcher (matchEndpoint) ... Compose @objectstack/metadata's MetadataPlugin' with {"appId":"com.example.showcase","count":2}. Slot occupant: constructor Object, matchEndpoint undefined, __serviceInfo.status degraded.",
    "census": {
    "how_measured": "Scratch tsx script (scratchpad, not committed) booting examples/app-showcase and examples/app-crm through the BUILT @objectstack/verify dist under the shared lock. BEFORE = the 965a1bf build. AFTER = the build with only a23a3b8 (the composition) on top. Both ran the verify CRUD family; crm also ran the RLS family.",
    "metadata_occupant": "fallback (Object, no matchEndpoint, degraded) -> NodeMetadataManager with matchEndpoint, both apps. Plugins on the kernel: showcase 34 -> 35, crm 22 -> 23 (+com.objectstack.metadata).",
    "http_showcase": "GET tasks no session 404 ENDPOINT_NOT_FOUND -> 401 UNAUTHENTICATED; admin 404 -> 200, 10 records; POST purge no session 404 -> 401 UNAUTHENTICATED; undeclared /apps/showcase/no-such-endpoint-23088 404 ENDPOINT_NOT_FOUND -> 404 ENDPOINT_NOT_FOUND",
    "matcher_warning": "showcase 1 -> 0; crm 0 -> 0. The 'no endpoint matcher is reachable' line: showcase 1 -> 0.",
    "meta": "GET /api/v1/meta/TYPE with an admin session, status + item count + sha256 of the body, 22 types (app, view, page, dashboard, report, action, flow, webhook, hook, mapping, analytics_cube, connector, email_template, doc, book, object, position, permission, capability, sharing_rule, api, datasource): 22 of 22 equal for the showcase, 22 of 22 equal for crm.",
    "security_registrar": "'Registered stack-declared security metadata' once before and once after, count 23 (showcase) and 5 (crm). The door registers nothing of the stack (lazy bootstrap logged once, no artifact), so AppPlugin stays the single registrar ('app-plugin'). Showcase /meta position 16, permission 17, capability 11, sharing_rule 2: equal bodies.",
    "other_metadata_readers": "ObjectQL syncs from the metadata service at start: registry objects equal (showcase 104 -> 104, crm 79 -> 79). Every other reader (REST /meta and openapi, plugin-security, plugin-sharing, plugin-webhooks, the external-datasource service) is exercised by the whole dogfood suite, which held every pin except the one composition precondition.",
    "persistence": "sys_metadata / sys_metadata_history / sys_metadata_commit / sys_metadata_audit rows after boot: 0/0/0/0 -> 0/0/0/0 on both apps. 'FileSystemRepository attached' at hostRoot/.objectstack/metadata, and nothing is written there: no such dir after the census boots or after either whole dogfood run. The only .objectstack under examples/app-showcase is data/showcase_external.db, from 17 dogfood files that chdir there (pre-existing).",
    "registerSystemObjects": "The door logs 'Registered system metadata objects' once (0 -> 1). The object set does not grow: registry 104 -> 104 and 79 -> 79, and the /meta/object body hash is equal.",
    "moved_answers_unpinned": "GET /api/v1/discovery services.metadata.status degraded -> available (its message is dropped). GET /api/v1/dev/metadata-events 404 -> 200 text/event-stream (bootStack forces NODE_ENV=development, as under os dev). The whole dogfood suite pins neither, and the changeset states both.",
    "verify_families_control": "CRUD showcase {objects 24, verified 15, fidelityGaps 0, createFailed 0, needsFixture 1, readFailed 0, skipped 8, mismatchTotal 0} identical before/after. CONTROL (no apis) crm CRUD {6, 4, 0, 0, 1, 0, 1, 0} identical. crm RLS {objects 6, consistent 0, holes 0, memberVisible 0, probeBlocked 6, skipped 0, proven 0, unproven 6} identical.",
    "boot_time": "7 interleaved bootStack boots each, showcase, boot only, under the lock (a shared box: read the ratio). BEFORE is a scratch copy of the 965a1bf verify dist. Medians 4750 ms -> 4745 ms (before 4459-4861, after 4503-4998). No measurable cost."
    },
    "dogfood_plugin_decision": "Removed. The file states its intent as 'boot the showcase the way a deployment boots it'. The showcase is a host config, and os serve and os start of it compose the artifact-less door since PR #23078, so the harness's own composition is that deployment. The old hybrid (an artifact door, with AppPlugin still registering apis and the four security collections) is a boot no production composition runs. With the plugin gone, the file is the showcase pin with no MetadataPlugin in extraPlugins (17 of 17 green at 82ccd69). The artifact door's apis ingestion keeps its own dogfood proofs (declarative-endpoint-policy and declarative-endpoint-anonymous-guest, green). The stand-in artifact is still written through the build's schema parse, so section 0 and the E7 publish-gate proof keep their subject. The header sentence and the plugin's docblock are corrected, and the docblock still names packages/metadata/src/plugin.ts, which holds dogfood's declared cross-package glob.",
    "tests": "All at 82ccd69, all through scripts/pm/os-verify-lock.sh. (1) pnpm --filter @objectstack/verify exec vitest run --maxWorkers=2: 'Test Files 37 passed (37)', 'Tests 291 passed (291)'. (2) pnpm --filter @objectstack/verify typecheck: exit 0, 'check:test-typecheck: OK'; the new test is in tsconfig.test.json's program (--listFiles 1 hit). (3) Dogfood subset (showcase-declarative-endpoints, external-validate-start-ordering, mail-message-pool-read-gate, declarative-endpoint-policy, declarative-endpoint-anonymous-guest, discovery-auth-families): 'Test Files 1 failed | 5 passed (6)', 'Tests 1 failed | 50 passed (51)'. The one red is the blocked precondition; the no-matcher warning appears 0 times in the log. (4) @objectstack/cli verify-
    (author-time-stage, delete-behaviors, host-root, json-stdout, parent-write-reach, reference-shapes, unique-scopes): 'Test Files 7 passed (7)', 'Tests 21 passed (21)'. The rest of the cli integration tier is declared to CI. (5) Whole dogfood suite, run twice under the lock: at d072256 'Test Files 1 failed | 257 passed | 1 skipped (259)', 'Tests 1 failed | 2121 passed | 9 skipped (2131)'; at 96eaff4 (after merging main) 'Test Files 1 failed | 256 passed | 1 skipped (258)', 'Tests 1 failed | 2117 passed | 9 skipped (2127)'. Both times the only red is that precondition. ABLATION leg 1 (verify test, source-resolved; ablation-replace.mjs wrap mode inside the lock). Anchor 'await kernel.use(new MetadataPlugin({ watch: false, config: { bootstrap: 'lazy' }, rootDir: hostRoot }));' x1 -> x0, replacement x0 -> x1, blob 704910003254 -> 082b863f6fb3. Result 'Tests 1 failed | 1 passed (2)': the composite received matcher 'undefined', anonymous {status 404, code ENDPOINT_NOT_FOUND}, signedIn 404, and one matcher warning with {"appId":"com.example.mdoor","count":1}. The caller-precedence case stayed green. Restore: blob == HEAD 704910003254, git diff HEAD empty. ABLATION leg 2 (showcase dogfood pin, verify resolved through dist; scratch script with trap restore EXIT INT TERM inside the lock). The mutation (void MetadataPlugin; ablation comment) landed: anchor x1 -> x0, blob -> 8efaf19cc8cf. Then pnpm --filter @objectstack/verify build, and ablation-dist-preflight.mjs @objectstack/verify 'kernel.use(new MetadataPlugin(' --absent: 'marker absent from all 6 built files'. Result 'Tests 7 failed | 10 passed (17)': the 401 cases got 404 ENDPOINT_NOT_FOUND, and the showcase's matcher warning was logged once. Restore: blob == HEAD, rebuild, preflight 'marker present in 1 built file', tree clean, git diff HEAD 0 bytes. The first leg-2 attempt was a NON-RUN: a plain comment replacement left the import unused, and the DTS build refused it (TS6133). The trap restored the file and the dist. The run above is the second attempt. LINT, a proven narrowing at 82ccd69. (1) Population: eslint --no-inline-config --print-config resolves 6 enabled rules for harness.ts and 5 each for the two test files, and none for the changeset, package.json and pnpm-lock.yaml. (2) Count: --format json gives files=3 errors=0 warnings=0, exit 0. (3) Invariance: eslint.config.mjs has no parserOptions.project and no projectService (0 hits); its only file reads are two baseline JSONs this diff does not touch. Repo-wide pnpm lint is CI's.",
    "gates": {
    "head": "82ccd6962d",
    "derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack with no paths: 80 commands, a change set of 6 paths vs merge base bcebd84 (committed 6, working tree 0, untracked 0), not stale. The explicit-path derivation over the same 6 paths printed the identical 80. That is the dispatch-time 80, and nothing was added.",
    "results": "80 run, each exit captured before any pipe: 79 exit 0, and 'pnpm check:test-source-alias :: exit 1' (blocked_on item 1; the gate prints 'check-test-source-alias FAILED / @objectstack/verify: NEW unaliased artifact import(s) ... @objectstack/metadata').",
    "reconciliation": "node scripts/pm/dispatch-gates.mjs --ran: 'Run reconciliation — 80 derived, 80 run, 0 NOT-MEASURED, 0 UNRUN' and '80 derived famil(ies) accounted for — 80 run, 0 NOT-MEASURED (a DERIVED zero — all 80 recorded an exit code and none of them is 3)'.",
    "history": "At 96eaff4, check:dual-build-cjs-loads answered exit 3, PREREQUISITE NOT MET, because eight unrelated packages had no dist. They were rebuilt (turbo cache, 57/57 cached), and the gate exits 0. check:cross-package-test-inputs went red at 96eaff4: the rewritten dogfood docblock had dropped the mention of packages/metadata/src/plugin.ts that holds dogfood's declared glob. The mention was restored in 2ee03b0, and the gate prints 'OK: 30 package(s) read outside themselves, all declared'."
    },
    "line_budget": "6 files, +219/-28 (git diff --shortstat origin/main...HEAD at 82ccd69): .changeset +13, harness.ts +37/-1, harness.metadata-door.test.ts +142, dogfood test +23/-27, package.json +1, pnpm-lock.yaml +3. Under the 3000-line human-merge threshold. No skills/** and no ledger budget is touched.",
    "files_changed": [
    ".changeset/23088-verify-bootstack-metadata-plugin.md",
    "packages/qa/dogfood/test/showcase-declarative-endpoints.dogfood.test.ts",
    "packages/verify/package.json",
    "packages/verify/src/harness.metadata-door.test.ts",
    "packages/verify/src/harness.ts",
    "pnpm-lock.yaml"
    ],
    "deviations": [
    "Two needed edits are outside the claimed surface, and neither was made (blocked_on). The alias remedy was only measured, uncommitted, and trap-restored to HEAD.",
    "A stray 5-byte file /build-base.pid (content 6133) was written at the filesystem root: a shell variable was scoped to a backgrounded list in my first build launch. My rm was refused by the harness safety check, so it remains for the user to delete.",
    "While listing environment variables, I printed the value of OS_FLEET_PRIVATE_KEY into this session's local tool output (the redaction pattern did not match the name). It was written to no file, commit, PR or comment. Treat that key as exposed to this transcript.",
    "Ablation leg 2's first attempt was a non-run (DTS build TS6133). The trap restored the file and the dist, and only the second attempt is reported as the measurement.",
    "Commit trailers use AGENTS.md's model-free pair (Co-authored-by: Claude, Claude-Session) rather than the harness reminder's model-named Co-Authored-By. The PR body footer uses AGENTS.md's session-URL form. Two merge commits of main carry git's default message.",
    "The census and boot-time instruments were scratch scripts in the scratchpad (not committed). The BEFORE boot-time leg ran a scratch copy of the 965a1bf verify dist, with node_modules symlinked to the worktree's packages/verify/node_modules.",
    "Each dogfood run recreated examples/app-showcase/.objectstack/data/showcase_external.db (gitignored, pre-existing chdir behaviour), and I deleted it from my worktree after each run.",
    "PR line 1 is 'Fixes #23088' per the dispatch. If the card moves to a decision box while this PR is open, the seat should rewrite it to 'Part of #23088'.",
    "Zero label writes: the dispatch names no label, and skip-changeset is not owed (the PR publishes a patch)."
    ],
    "mcp_calls": "0 — no MCP GitHub tool was called. Reads went through gh api REST (issue 23088 and its comments, comment 6129082934, pull 23078, pull 23127 read-back).",
    "api_writes": "2 relay dispatches, each POST /repos/objectstack-ai/objectstack/dispatches, executed by fleet-write as objectstack-fleet[bot]. (1) pr_create run 38335555934: POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/23127/assignees (os-steve); read back 15066 bytes sent and 15066 stored. (2) This os-dev-report comment: POST /repos//issues/23088/comments. git push of the branch, several times, is not a REST write.",
    "open_questions": [
    {
    "question": "external-validate-start-ordering.dogfood.test.ts pins the harness's old metadata occupant (its precondition) as 'the objectstack start shape'. bootStack now composes serve's door, and os serve and os start of the showcase do too since PR #23078. What does this file become?",
    "options": [
    "A: The precondition asserts the composed door (matchEndpoint present), the header drops the 'no metadata plugin / objectstack start shape' framing, and the two federation cases stay as they are (green, measured). The #21876 ordering fix stays pinned where the file itself says its seam pins live, in packages/services/service-datasource/src/tests/external-validate-reads-live-registry.test.ts. Cost: the dogfood-level reproduction of a matcher-less composition goes; that composition survives only on OS_MODE=off boots and embedders. Work: one file, about 20 lines, plus the two comment sentences in multi-package-artifact and external-validate-sees-runtime-save.",
    "B: Keep a matcher-less composition in that file: hand extraPlugins a stand-in plugin named com.objectstack.metadata that registers nothing, so the composed door is skipped and the kernel injects its fallback. Cost: a test-only stub that claims a MetadataPlugin is present when none is, to opt out of a composition rule that has no switch; it models a boot the showcase no longer runs in production. Work: about 15 lines.",
    "C: Delete the file and name the plugin-layer duplicate. Cost: the HTTP-door federation drift proof on the showcase goes, and AGENTS.md lets a test go only when the PR names a duplicate at a layer at least as close to the code, which covers the ordering seam but not the HTTP validate answer."
    ],
    "recommendation": "A. Real business need: the federation answers the file's two cases pin are the live path, and A keeps them on the composition production now boots. The fallback-ordering defect stays pinned at its seam. Long-term soundness: one composition rule, no stand-in. B is a workaround that turns the identity-precedence rule into an opt-out. Preventing AI mistakes: B would teach that a fake plugin name is how you get a shape, which declares a capability the runtime does not deliver; A keeps declared equal to composed. Startup scope: A is the smallest edit with no new mechanism and no new gate, while C saves lines but drops coverage. Triage's direction (compose, with the exception list staying two) already implies A, so the seat may treat this as a surface extension rather than a maintainer question."
    }
    ],
    "out_of_scope_findings": [
    "carrier: none · noted, not filed. packages/services/service-datasource/src/plugin.ts about :83 (and its CHANGELOG line 27) says 'objectstack start composes no metadata plugin'. That has been stale for a host config since PR #23078 (census 10b there), not since this change. It is a published code comment, read-only inference, no reach.",
    "carrier: none · noted, not filed. 17 dogfood files chdir into examples/app-showcase, and a run leaves .objectstack/data/showcase_external.db there (gitignored), outside the per-file-cwd guard, which watches only packages/qa/dogfood. Pre-existing; test-infrastructure state, not a product door.",
    "carrier: the surface extension in blocked_on item 2 · noted, not filed. Two dogfood comment sentences go false with this change: multi-package-artifact.dogfood.test.ts about :163 ('bootStack registers AppPlugin and no MetadataPlugin') and external-validate-sees-runtime-save.dogfood.test.ts about :24 ('The verify harness composes no metadata plugin'). Same family as the blocked file."
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat review of PR #23127 at 82ccd6962d: the surface is extended by two files and ruled A, and patch round 1 is asked

    domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-13T02:15Z · holder of claim 6134819217. Report: os-dev-report 6136703527 (blocked). ⛔ Not an ACCEPT yet.

    Read against GitHub and accepted as is:

    • PR shape: draft, base main, line 1 Fixes #23088, line 2 Clause-②: no, assignee os-steve. 6 files, +219 / −28.

    • The composition: bootStack composes new MetadataPlugin({ watch: false, config: { bootstrap: 'lazy' }, rootDir: hostRoot }), option for option what serve.ts passes, right after HonoServerPlugin and before AppPlugin, with no catch. A MetadataPlugin in extraPlugins or in the app's own plugins takes its place on serve's two keys. The exception list stays two, as triage ruled (6131551384).

    • The census moved no answer the dogfood suite pins and no verify family's counts:

      • the 22 /meta types' bodies are equal on both apps;
      • the security registrar ran once with equal counts;
      • the registry object set is unchanged;
      • 0 sys_metadata* rows were written, and nothing landed under hostRoot/.objectstack/metadata;
      • the boot medians are 4750 → 4745 ms.

      Two unpinned answers move, and the changeset states both: discovery's services.metadata.status (degraded → available) and GET /api/v1/dev/metadata-events (404 → 200 under the harness's forced NODE_ENV=development).

    • Pins: on the showcase, 401 without a session, 200 with one, the undeclared path 404, no matcher warning, and caller precedence by identity. Both ablation legs red their pins, and both restores were proven.

    • The showcase dogfood file's hand-added plugin is removed. Accepted, with the dev's reason: a host-config os serve / os start composes the artifact-less door since PR fix(cli,runtime): a host-config os serve composes a MetadataPlugin, so its declared apis are served; a matcher-less composition warns once #23078, so the old artifact-door hybrid was a boot no production composition runs. The artifact door's apis ingestion keeps its own dogfood proofs.

    The blocked items, ruled by the seat (one patch round, each item its own commit):

    1. packages/verify/vitest.config.ts joins the surface, for the one anchored alias line check:test-source-alias prescribes (@objectstack/metadata to ../metadata/src/index.ts, beside the core entry). The registry is shrink-only, so the alias is the gate's own remedy.
    2. packages/qa/dogfood/test/external-validate-start-ordering.dogfood.test.ts joins the surface. The open question is ruled A.
    3. Two comment sentences that this change makes false ride the same round: multi-package-artifact.dogfood.test.ts (about :163) and external-validate-sees-runtime-save.dogfood.test.ts (about :24). Comment only.

    Then merge origin/main, re-run the verify package, the whole dogfood suite under the lock, and check:test-source-alias, and report the new head.

    Noted, not filed:

    A contract review at CONTRACT_REVIEW_TIER runs on the patched head after the seat's ACCEPT, as the claim says: the metadata slot's occupant changes on every bootStack boot.


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23088,
    "patch_round": 1,
    "status": "done",
    "branch": "claude/issue-23088-bootstack-metadata-plugin",
    "pr": "#23127",
    "head": "0c232d83fb",
    "session": "session_01VoSxBQujKLZKPwK2u5ehQ6 (mode:subagent: the dispatching PM session's id, as the branch's Claude-Session trailers carry it)",
    "premise_still_valid": true,
    "summary": "Patch round 1 is applied as ruled in 6136737187, one commit per item, all pushes fast-forward. (1) 3867e0a: packages/verify/vitest.config.ts gains the one anchored @objectstack/metadata alias beside core, exactly as measured, and check:test-source-alias is OK. (2) 8b2647e: external-validate-start-ordering.dogfood.test.ts, option A. The precondition asserts the composed door: kernel.hasPlugin('com.objectstack.metadata'), the metadata service toBeInstanceOf(MetadataManager), and matchEndpoint a function. The header drops the objectstack-start and no-metadata-plugin framing and names packages/services/service-datasource/src/tests/external-validate-reads-live-registry.test.ts as the seam pin of the init-ordering fix. The two federation cases are byte-unchanged. There is no stand-in and no deletion. (3) cf20650: one comment sentence each in multi-package-artifact and external-validate-sees-runtime-save; 0 non-comment lines changed. main was merged (480dcb7, then 0c232d8 when it moved during a lock wait). At 0c232d8: verify 37/37 files, 291/291 tests; verify and dogfood typecheck exit 0; 80/80 gates exit 0, reconciled with --ran. The whole dogfood suite is 258 passed | 1 failed | 1 skipped files. Every file this PR touches is green. The one red, mail-message-pool-read-gate, is main-side: PR #22900 against PR #22993's fixture. It is red with and without this PR's composition (measured), and it is reported below, not fixed.",
    "round_commits": {
    "3867e0a312": "packages/verify/vitest.config.ts: +1 line, the alias",
    "8b2647eb19": "external-validate-start-ordering.dogfood.test.ts: header, describe title, precondition case, one import (+29/-22)",
    "cf2065001e": "multi-package-artifact.dogfood.test.ts and external-validate-sees-runtime-save.dogfood.test.ts: comment lines only (+7/-6); the non-comment-line filter (diff lines not starting with //) counts 0",
    "480dcb717e": "merge of origin/main",
    "0c232d83fb": "merge of origin/main (the head)"
    },
    "precondition_pin": "Weight-bearing, proven by ablation leg 3. The mutation removed the composition line (anchor x1 -> x0, blob 704910003254 -> 8efaf19cc8cf); verify was rebuilt and ablation-dist-preflight read the marker absent from all 6 built files. With the door (CONTROL): 'Test Files 1 passed (1)', 'Tests 3 passed (3)'. Without it: 'Tests 1 failed | 2 passed (3)', the precondition red at hasPlugin ('expected false to be true'), and both federation cases green. Restore: blob == HEAD, rebuilt, marker present, git status --porcelain empty. Ran inside os-verify-lock.sh with a trap restore on EXIT INT TERM.",
    "tests": "All at 0c232d8, through scripts/pm/os-verify-lock.sh under one acquisition (slot dev-23088-test), each exit captured before any pipe. Closure build exit 0. pnpm --filter @objectstack/verify exec vitest run --maxWorkers=2: 'Test Files 37 passed (37)', 'Tests 291 passed (291)'. pnpm --filter @objectstack/verify typecheck: exit 0, 'check:test-typecheck: OK'. pnpm check:test-source-alias: exit 0, 'check-test-source-alias OK — 74 packages with tests scanned'. pnpm --filter @objectstack/dogfood typecheck: exit 0. WHOLE dogfood suite (pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2): exit 1, 'Test Files 1 failed | 258 passed | 1 skipped (260)', 'Tests 2121 passed | 18 skipped (2139)'. The failed file is mail-message-pool-read-gate.dogfood.test.ts: its beforeAll fails ('fixture permission set mail_pool_22870_read seeded: expected undefined to be truthy'), so its 9 tests are skipped. Per file: showcase-declarative-endpoints 17/17, external-validate-start-ordering 3/3, external-validate-sees-runtime-save 3/3, multi-package-artifact 9/9, declarative-endpoint-policy 8/8, declarative-endpoint-anonymous-guest 6/6. The no-matcher warning appears 0 times in the whole run's log. CONTROL on that red, inside the lock with a trap restore: with the door as built, 'Test Files 1 failed (1)', 'Tests 9 skipped (9)', the same assertion; with the door removed (blob -> 5b13a59a72e7, rebuilt, marker absent from all 6 built files), the same 1 failed / 9 skipped and the same assertion. Restore: blob == HEAD, rebuilt, marker present, porcelain empty. The file was green in this branch's dogfood subset at 82ccd69, before PR #22900 reached the tree. Not re-run this round: @objectstack/cli verify-* (7 files, 21/21 at 82ccd69; round 1 touches no file they load). LINT, a proven narrowing at 0c232d8: --print-config resolves rules for all 7 changed TS files (6 for harness.ts and vitest.config.ts, 5 for each test file) and none for the changeset, package.json and pnpm-lock.yaml; --format json gives files=7 errors=0 warnings=0, exit 0; eslint.config.mjs has no parserOptions.project and no projectService (0 hits), and it reads only two baseline JSONs this diff does not touch.",
    "gates": {
    "head": "0c232d83fb",
    "derivation": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack with no paths: 80 commands, a change set of 10 paths vs merge base f931e76 (committed 10, working tree 0), no STALE line. It is the same 80-command list as at 480dcb7 and at 82ccd69.",
    "results": "80 run, each exit captured before any pipe: all 80 exit 0.",
    "reconciliation": "node scripts/pm/dispatch-gates.mjs --ran: 'Run reconciliation — 80 derived, 80 run, 0 NOT-MEASURED, 0 UNRUN' and '80 derived famil(ies) accounted for — 80 run, 0 NOT-MEASURED (a DERIVED zero — all 80 recorded an exit code and none of them is 3)'.",
    "drift_after": "After the runs, origin/main moved 5 commits to d206d08 (#23129, #23131, #23132, #23126, #23125). None of them touches this diff's paths, packages/verify or packages/qa/dogfood. Not merged."
    },
    "line_budget": "10 files, +256/-56 (git diff --shortstat origin/main...HEAD at 0c232d8). This round adds +1 (vitest.config.ts), +29/-22 (start-ordering) and +7/-6 (two comments). Under the 3000-line threshold; no skills/** and no ledger budget is touched.",
    "files_changed": [
    ".changeset/23088-verify-bootstack-metadata-plugin.md",
    "packages/qa/dogfood/test/external-validate-sees-runtime-save.dogfood.test.ts",
    "packages/qa/dogfood/test/external-validate-start-ordering.dogfood.test.ts",
    "packages/qa/dogfood/test/multi-package-artifact.dogfood.test.ts",
    "packages/qa/dogfood/test/showcase-declarative-endpoints.dogfood.test.ts",
    "packages/verify/package.json",
    "packages/verify/src/harness.metadata-door.test.ts",
    "packages/verify/src/harness.ts",
    "packages/verify/vitest.config.ts",
    "pnpm-lock.yaml"
    ],
    "deviations": [
    "The worktree had been removed after round 0, so it was re-created on the existing branch at its remote tip 82ccd69 (no rebase, no reset). The dists were rebuilt from the turbo cache (48 of 72 cached).",
    "The first round-1 lock call ended VERDICT queue-timeout (exit 99, never acquired), so nothing was measured. While it waited, main moved: I merged it again (0c232d8) and re-queued on the kept slot dev-23088-test, with the build folded into the same acquisition.",
    "A gate runner I had started at 480dcb7 was still running when the second merge moved the tree. I stopped it by its recorded pid and discarded its partial results. My first attempt put a ps-pipe-grep liveness check in the same command as the kill; the process-kill hook blocked that, nothing was signalled, and I re-ran it as a pid-only kill.",
    "Item 2: the describe title changed with the header (it carried the 'objectstack start shape' framing). The two federation cases are byte-unchanged.",
    "The precondition pins the occupant by public reads: hasPlugin by name, and instanceof MetadataManager from @objectstack/metadata, the class only MetadataPlugin registers into the slot. It reaches no kernel private.",
    "@objectstack/cli verify-* was not re-run this round; the last run was at 82ccd69, 21/21.",
    "No environment variable's value was printed this round. Round 0's two notes stand: the stray /build-base.pid at the filesystem root (removal refused by the harness), and the OS_FLEET_PRIVATE_KEY value printed to round 0's local tool output.",
    "Each dogfood run recreated the gitignored examples/app-showcase/.objectstack/data/showcase_external.db (pre-existing chdir behaviour), and I deleted it from the worktree after the runs."
    ],
    "mcp_calls": "0 — no MCP GitHub tool was called. Reads went through gh api REST (comment 6136737187, pull 23127 and its body, the read-back of this comment).",
    "api_writes": "2 relay dispatches this round, each POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]. (1) issue_patch, run 38342506901: PATCH /repos//issues/23127 (the PR body: the ruling, the added files, the new head 0c232d8), read back 17638 bytes sent and 17638 stored. (2) This os-dev-report comment: POST /repos//issues/23088/comments. git push (3 commits and 2 merges, fast-forward) is not a REST write.",
    "open_questions": [],
    "out_of_scope_findings": [
    "class: a · reach: the dogfood full battery on main, a named producer and consumer. PR #22900 (c8a9783, 'no seeder or materializer writes a sys_permission_set row; the boot seeds no row for a declared set') stops writing the row whose existence PR #22993's packages/qa/dogfood/test/mail-message-pool-read-gate.dogfood.test.ts fixture asserts (:111, 'fixture permission set mail_pool_22870_read seeded: expected undefined to be truthy'). · evidence: red on this branch at 0c232d8 with this PR's composition AND with it ablated out (both legs: 1 failed file, 9 skipped, the same assertion), and green at 82ccd69 before #22900 reached the tree. So main's full-battery dogfood is red independent of this PR. · dedupe words: mail-message-pool-read-gate, mail_pool_22870_read, sys_permission_set seeded, 22900 22993 dogfood red"
    ]
    }


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR #23127 at 0c232d83fb (Fixes #23088). It queues after one CONTRACT_REVIEW_TIER PASS on this head, and after main's full-battery red #23148 clears

    domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-13T04:20Z · holder of claim 6134819217. Reports: os-dev-report 6136703527 (blocked) and patch round 1's 6137663147. Thread-read: 6137663147.

    Checklist, read against GitHub:


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 13, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #23127 → de24373ecb (Fixes #23088). The card closes completed

    domain:cli seat 2 (#22648) · os-steve · session session_01VoSxBQujKLZKPwK2u5ehQ6 · 2026-10-13T06:16Z · holder of claim 6134819217, released by this landing.


    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

Labels

area:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobsbugSomething isn't workingdomain:clipriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions