Repository navigation
feat(core,cli,verify): bootStack composes what serve composes — item 1 stage 2 of #22301 (HELD at stop conditions) - #22381
Conversation
…es names, by serve's own reader and table Re-applies ef5396c (reverted at b3186ec pending the item-1 ruling) onto current main. The `requires` token -> provider table and its exact identity match move from the `Serve` command to `@objectstack/core`, beside the package-owned collection reader `os serve` reads `requires` with (moved there from the CLI's utils, which re-export it). `Serve.CAPABILITY_PROVIDERS` and `Serve.providesCapability` become handles over the core declarations. `@objectstack/verify`'s `bootStack` then constructs the providers the app's `requires` names, skips any provider the boot already holds, and mounts the always-on providers a mounted provider hard-depends on. Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
…'s entry rule; the instance rule Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
…helper anchors hostRoot; the dogfood run declines the marketplace Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
… read it Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 4 package(s): 9 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 6 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 47 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin f574862bb9c87ada4e2800df737e716d8e5b1131 && git checkout f574862bb9c87ada4e2800df737e716d8e5b1131
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin c512c255c5c62467a697619c0643d5a329e20f10 749197628fc07c97865c2389e3d4f6cb002ca7bf && git checkout -B drift-repro c512c255c5c62467a697619c0643d5a329e20f10 && git merge --no-ff 749197628fc07c97865c2389e3d4f6cb002ca7bf
node scripts/docs-audit/affected-docs.mjs --json c512c255c5c62467a697619c0643d5a329e20f10
|
…em1-one-composition
…rs of the instance rule boot a configuration built again Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
…op a doubled helper import Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
…onfiguration that does not declare automation Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
…em1-one-composition # Conflicts: # packages/qa/dogfood/test/permission-set-discard-overlay-eligibility.dogfood.test.ts
…s through bootShowcase Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
…ve does Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Isolated at-tier review of PR #22381 (item 1 stage 2 of #22301, ruling ① Derived judgmentsEvery accept-set and public-surface change the diff implies, each judged:
② Semver levelChangeset
③ Boundary flagsDev flags (reports
Checks on
The verdict below is on the contract at this head: the diff executes ruling A with the instance rule as ordered, the changeset says what the diff publishes at the right levels, and every flag is answered or carried. It does not vouch for the Lint families that never ran here; those are the merge head's to show green. Implemented-by: VERDICT: PASS |
…em1-one-composition
…ition, as #22301 now has them The bootStackOnce TSDoc states that a second options key on a configuration whose first boot is still live is refused by the instance rule. The platform-core activation-ledger item (revision 4) and FOLLOW-UPS restate the no-automation composition as the dogfood suite builds it: a showcase-derived configuration that does not declare automation. Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
…ℹ glyph (objectstack-ai#22409) Fixes objectstack-ai#22255 Clause-②: no ## What changes The startup banner's `Flows:` section prints one line per unbound-flow class (trigger type, reason), and every class printed as a yellow `⚠`. A class whose reason is the deployment's scheduled-work sentence (flows left unbound only because package-authored scheduled work is off, the documented default) now prints **dim, under `ℹ`**. It keeps its count, trigger type, first sentence and flow list. Every other reason keeps its yellow `⚠`: a missing trigger, a binding failure, anything else. The unknown-target-object and shadowed-flow lines are untouched. This applies the routing of record (triage `6057431712`), which executes the maintainer's direction on objectstack-ai#22160, quoted verbatim: 「预期中的降级记 info」. - `packages/cli/src/utils/format.ts`: a new `isDeploymentPolicyClass(reason)` and the class loop in `printAutomationSummary`. Only the glyph and the color depend on the class. The line's text, the class order and the records handed back to *Boot diagnostics* (`restatedAbove`) are unchanged. - ⛔ Not changed: the automation plugin's binding, the scheduled-work switch, `@objectstack/service-automation`'s own log level, `serve.ts` and `packages/spec`. ## How the class is told apart: identity, not prose `isDeploymentPolicyClass` is `reason === SCHEDULED_WORK_DISABLED_REASON` (`@objectstack/types`). Measured on `origin/main` at `11d119ab1`: - The engine records `scheduledWorkDisabledReason(policy)` from the policy reading that refused the bind (`activateFlowTrigger`). `describeUnboundReason` reads that record back for `getTriggerBindingAudit`, and `collectAutomationSummary` passes it through unchanged. - For every policy the environment resolves, that function returns the constant byte for byte: `resolveScheduledWorkPolicy` never sets `hostDisabledReason` (pinned in `env.test.ts`). - The test file's real-producer leg boots the real `AutomationServicePlugin` on a `LiteKernel` and reads the summary through `collectAutomationSummary`. Its schedule line is now asserted to start with `ℹ`, so the identity is pinned against what the producer actually records. If the producer is reworded, the line goes back to `⚠`, which is the loud direction. - The check does not call `scheduledWorkDisabledReason(resolveScheduledWorkPolicy())`. On that reading the call returns the same constant by construction, and the resolver throws on an unrecognised `OS_TENANCY_POSTURE`, which a printer must not do. - No structured kind was needed. So neither `serve.ts` (held by PR objectstack-ai#22381) nor the spec contract is touched. ## Pins (`format.boot-warning-classes.test.ts`) - **Real boot** (eight scheduled flows, switch off): the one schedule line now starts with ` ℹ 8 flows declare `. - **Policy class:** prints dim (opening SGR `ESC[2m`, no yellow) under `ℹ`, with its flows and first sentence. Controls: a missing trigger and a binding failure keep a yellow (`ESC[33m`) `⚠`. - **⛔ Identity, not words:** three reasons that only quote the policy all keep `⚠`. They are a binding failure carrying the policy's first sentence, the whole sentence inside a longer record (the schedule trigger's own refusal shape), and the first sentence alone. - **`restatedAbove` is the same under both glyphs:** a policy flow, a missing-trigger flow and a binding-failure flow, each with its producer audit record. Every flow is named once, and no *Boot diagnostics* block prints. - The existing first-sentence pin moves from `⚠` to `ℹ`. ## Evidence (head `62c86cba9`, branched from `11d119ab1`) **Public door.** `objectstack dev --seed-admin --fresh -p 38421` on `examples/app-showcase`, with the CLI built from this head. The Flows section, SGR stripped and the shared sentence cut to an ellipsis: ```text Flows: 30 flow(s) 20 bound to triggers (record_change, schedule, time_relative, api) · 7 draft ℹ 1 flow declares a 'time_relative' trigger but is NOT bound — disabled by deployment policy — … : showcase_task_due_reminder ℹ 1 flow declares a 'schedule' trigger but is NOT bound — disabled by deployment policy — … : showcase_scheduled_digest reasons cut to their first sentence — --log-level debug prints each flow's full reason Seeds: com.example.showcase 132 rows ℹ Boot diagnostics — 1 informational (2 more already listed above): ``` Both class lines open with the dim SGR (`ESC[2m`) in the raw capture, and *Boot diagnostics* still withholds the two restated records. That boot printed two other `⚠` lines, both about this worktree having no console build (`packages/console/dist` and the SDUI manifest). They come from the environment, not from this change. **Tests and gates**, all at `62c86cba9`: | Check | Result | |:---|:---| | `pnpm --filter @objectstack/cli exec vitest run --project unit --maxWorkers=2` | 270 files, 3971 tests passed, lock `VERDICT command-exit 0` | | `format.boot-warning-classes.test.ts` alone | 21 of 21 passed | | `pnpm --filter @objectstack/cli typecheck` | exit 0 (`tsc --noEmit`, then `check:test-typecheck` over `tsconfig.test.json`) | | `pnpm lint` (full: `eslint . --no-inline-config`) | exit 0, no findings | | derived gate families | `dispatch-gates --ran`: 64 derived, 64 run, 0 NOT-MEASURED, 0 UNRUN (a derived zero, every exit code recorded) | The integration layer is declared to CI: the diff reaches no integration file and no spawn entry. **Ablation.** Run on the committed fix with `scripts/ablation-replace.mjs`. In each leg the anchor went from 1 hit to 0, and the restore brought the blob back to `5804f510beed`, equal to HEAD, with `git diff HEAD` empty. - **Leg 1**, identity forced to `false`: 3 failed, 18 passed. The failures are the real-boot `ℹ` pin, the first-sentence pin and the dim/`ℹ` pin. - **Leg 2**, identity replaced by `reason.includes('disabled by deployment policy')`: 1 failed, 20 passed. The failure is the identity pin. The test imports `./format.js`, which vitest resolves to `src/utils/format.ts`, so neither leg depended on a `dist` rebuild. ## Acceptance notes - **Host-injected policy.** A per-kernel `ScheduledWorkPolicy` that carries its own `hostDisabledReason` keeps `⚠`. That sentence is the host's, not the documented default, and the printer cannot know it. For this banner the case is dormant: `git grep` finds 0 non-test producers of `hostDisabledReason:` in the tree, against a positive control of 4 hits in test files. Telling that class apart would need a structured kind on the audit row (the spec contract plus `serve.ts`), which this PR does not add. - **Contract wording.** `FlowRuntimeState.reason` in the spec contract says consumers render the reason and do not parse it. An equality check against the exported producer constant is not parsing, and no prose match was added. - **Stale prose this change makes inaccurate, left unedited** (outside the claim's file surface): - `docs/qa/platform-checklist/areas/platform-core.json` acceptance[2].verify describes the policy lines as `⚠ … disabled by deployment policy`. Its clause (fail on the misauthored `⚠` classes) still holds, and is now easier to apply. - The still-pending `.changeset/22073-boot-warning-one-line-per-class.md` quotes the class with `⚠`. This PR's changeset states the move to `ℹ`, and the two would ship in the same release. - **Line order is unchanged** (first-seen). A dim policy line can still print above a `⚠` class: the one-line-per-class order belongs to the earlier ruling and was not re-ruled. --- _Generated by [Claude Code](https://claude.ai/code/session_01BmsuLyUeuG5CNpZFMH1jzS)_ Co-authored-by: Claude <noreply@anthropic.com>
…em1-one-composition # Conflicts: # packages/qa/dogfood/test/showcase-object-extension-scalar-divergence.dogfood.test.ts
…s budget The case reboots the showcase inside the it(), under vitest's 5000 ms default. bootShowcase now composes the showcase as os serve does, and that reboot read 2809 ms quiet and timed out at 5225 ms on a loaded shard. It now carries the 300_000 budget beforeAll gives the same start(), as every other in-case boot in the swept files already does. Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
…em1-one-composition
…through bootShowcase Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Isolated at-tier review of PR #22381 at the merge-round head (item 1 stage 2 of #22301, ruling ① Derived judgmentsThe round's delta, measured. The branch-side hunks of the net diff at this head (vs
② Semver levelChangeset
③ Boundary flagsMerge-round report
Checks on
The verdict is on the contract at this head: the delta is the judged one plus the five named changes, each right; the two text fixes are true to the code and the checklist change is in its lifecycle's shape; the sweep is complete against the merged tree and against Implemented-by: VERDICT: PASS |
…em1-one-composition
…ot goes through bootShowcase bootShowcase passes the showcase's own directory as hostRoot, so the file no longer changes the process cwd to reach it. Its databaseFile option and its two reboots after stop() are unchanged. Claude-Session: https://claude.ai/code/session_01DhTqaEHqPVSVnAkjG3jywn Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: Isolated at-tier review of PR #22381 at the merge-round-2 head (item 1 stage 2 of #22301: ruling ① Derived judgmentsThe head, measured against the standing PASS. This head is
So the PR's delta is unchanged apart from the one swept file. The one commit, judged:
② Semver levelThe changeset
③ Boundary flagsRound-2 report
Checks on
The verdict is on the contract at this head: the delta is the judged one plus one swept file, the sweep is right and complete, the cwd drop is safe for what the file reads, the instance rule holds across its reboots, the changeset says what the diff publishes at the right levels, every flag is answered or carried, and every check-run on the head has a conclusion, none red. Implemented-by: VERDICT: PASS |
…nt protocol, ^18 #22381 (97610a5) added test/verify-host-root.test.ts with a current-app fixture pinned to engines.protocol '^17'. Under PROTOCOL_VERSION 18.0.0 the runtime handshake refuses that app, so `os verify` exits 1 before the pin's subject (the app-dir anchoring) is ever reached. The fixture now declares '^18', the same sweep rule this branch applies to every current-app fixture. Claude-Session: https://claude.ai/code/session_01VZqqwTj2wsihZEbfT6yyYN Co-authored-by: Claude <noreply@anthropic.com>
Part of #22301
Clause-②: yes (narrowing: a second live boot of the same configuration is refused, where it booted; widening:
bootStackmounts the app'srequiresproviders andplugins, and@objectstack/coreexports the provider table)Status: held draft. This is item 1 · stage 2 of #22301 under ruling
6070767186(A: one composition rule, with the instance rule), patched per seat order6071972897(A and A) and the seat's CI note. Contract review PASS at08929776c(6075048879). The merge round (seat note6075062726) mergedmainthree times, at3054516ef,b9222dc70and2b61f2d9d, and carries the two text fixes. Contract review PASS at8d985cf8f(6079992475). Merge round 2 (seat order6080029242) mergedmainatc512c255cand swept the one direct showcase boot it brought. Head:749197628.What this branch carries
requireshalf. The token-to-provider table, its exact identity match and the package-owned collection reader move to@objectstack/core(capability-providers.ts,stack-collections.ts).Serve's statics are handles over them.pluginsarray is mounted byserve's entry rule, which now has one home:materializeStackPluginin@objectstack/core(stack-plugins.ts). A string entry is a package specifier, a plain bundle is wrapped intoAppPlugin, and an instance is itself.serve's boot loop reads the rule from there, and each boot injects its own loader.extraPlugins,securityoranalyticsinstance with the samenamereplaces the app's plugin, and the app's instance never runs. The app's plugins count as held for therequiresresolver, and their hard dependencies are searched like a provider's.hostRootis the app's root. It is the automationpackageRoot, whether automation comes fromrequiresor fromautomation: true, and it is the root a string entry resolves from.os verifynow passesdirname(configPath)ashostRoot, the wayserveanchors to its project. CI'sDogfood Verify CLIrunsos verifyfrom the repository root, and there the showcase's./src/system/connectors/status-openapi.jsonresolved against the root (ENOENT). That one caller inpackages/cli/src/commands/verify.tsis fixed.plugins[i].bootStackof one configuration object is refused, and so is a copy that carries a mounted app-plugin instance. The refusal isRESOURCE_CONFLICT/409. The refusal names three remedies:stop()first;bootStackOnce; or, to keep two stacks live, a configuration built again (its builder called once more, or a fresh module instance). A{ ...config }spread is not one. Measured at08929776c, a boot keeps live references into a configuration's nested definitions, and writes into one:packages/objectql/src/registry.ts:2600runsapplySystemFields. That returns the authored schema itself (:651,:772,:876), or a newfieldscontainer whose values are the authored field objects (:780).:2750storesdefinition: { ...schema, name: fqn }, a shallow copy.packages/objectql/src/engine.ts:7044and:7216writeobjDef.name = nameinto a map-formobjectsentry in place.OS_CLOUD_URL=offis stated inbootStack's docs and the changeset.packages/qa/dogfooddeclares it per project in its vitestenv.bootStackOnce's TSDoc now states the instance rule for a second options key. While the first boot of aconfigis live, a secondoptskey on thatconfigis refused (RESOURCE_CONFLICT/409), and the memo drops that key. To keep two stacks live, the second one needs a configuration built again.docs/qa/platform-checklist/areas/platform-core.json, itemplatform-core.activation-ledger-registration-home, is now at revision 4. Itsfixtures.requires, step 1 and harness source entry restate the no-automation composition as the dogfood suite builds it: a showcase-derived configuration that does not declare automation (packaged-activation-ledger-reach,showcaseWithoutAutomation). Revision 1's history entry keeps its text and gains a "superseded at revision 4" note.FOLLOW-UPS.mdsays the same.declared-position-provenancecarries its boot's budget. The case reboots the showcase inside theit(), under vitest's 5000 ms default. On a loaded shard it timed out at 5225 ms; on quiet ones it read 2809, 2736 and 3752 ms. It now carries the300_000budget thatbeforeAllgives the samestart(). It was the only in-case boot in the swept files without a budget. The other 12 already carried one.The swept surface (
packages/qa/dogfood/test/**,packages/verifyconsumers)test/showcase-boot.tsexportsbootShowcase(opts, config = showcaseStack), withhostRoot=examples/app-showcase. There is no inlinehostRootand no per-file cwd change. 122 files call it, at 133 call sites (the helper's own definition is not counted). That includesshared-showcase.tsand every file that landed onmainduring the rounds:showcase-object-extension-scalar-divergence: feat(metadata-protocol)!: managed content is sealed — OS_METADATA_WRITABLE no longer opens an item a managed package ships (ADR-0131 D6, #15206 S2) #22401 rewrote itsboot()helper; the helper was re-applied after takingmain's side (2 lines).storage-unclaimed-download: new in fix(service-storage)!: downloading a file with no attachments scope and no field owner requires a signed-in caller #22439, swept after the third merge.position-environment-write-through: new in feat(plugin-security)!: under single, Setup positions are written through to the environment ledger, and row-only positions are backfilled once (ADR-0131 D3, C2 stage S7) #22388, swept in merge round 2.process.chdir(SHOWCASE_DIR)and its restore are dropped, together with the now-unusedSHOWCASE_DIRconstant, its comment and thefileURLToPathimport.bootShowcasepasses the showcase directory ashostRoot..objectstack/datalands in the per-file temp cwd, as for every other swept file. It no longer lands inexamples/app-showcase.databaseFileoption and its two reboots afterstop()are kept as they were.showcase-anonymous-deny-surfacesexpects automation mounted, so a member gets200.schedule-sweep-organization-scopepasses a stand-in undercom.objectstack.trigger.time-relativeinextraPlugins. The fixture'srequiresstays as authored.showcase-declarative-endpointsserializes a copy withoutplugins.route-ledger-live-mount-parity: the showcase requiresmarketplace, soPOST /packages/publishwith{}answers400 MISSING_REQUIRED_FIELD, and never a405.packaged-activation-ledger-reach: Packaged-action disable is unavailable without the automation service —sys_metadata_activationhas only one registrant #12359's no-automation case boots a showcase-derived config that does not declareautomation, without the connector plugins that hard-depend on it.verify/handle.test.tsuses a fresh module instance ofhandle.fixture.js.verify/harness.app-default-profile.test.tscalls an in-file builder.parent-derived-write-refusal-not-visible,write-door-unreadable-is-not-foundandpredicate-write-unreadable-not-matchedcall per-boot builders, backed bybuildAttCase…buildCmtReadonlybuilders added tofixtures/attachments-fixture.ts/comments-fixture.ts.armedboots its second showcase stack from a fresh module instance, so it never shares plugin instances.Measured at
8d985cf8fOS_TEST_SHARD=1/3 pnpm turbo run test --filter=@objectstack/dogfood,VITEST_MAX_WORKERS=3fromvitest-worker-cap.mjs)rls-multitenant, skipped by its owndescribe.skipIf. The diff adds 0 skip lines.Dogfood Verify CLIstep, run from the repo root as CI runs it✓ verify passed — no runtime failurestest/verify-host-root.test.ts@objectstack/verify@objectstack/core--project local@objectstack/cli--project unitbootStackOnceTSDoc claim, one-off probe (not committed;harness.tsis unchanged since)optskey on the sameconfigis refused withRESOURCE_CONFLICT/409. Afterstop(), the same second key boots, so the memo dropped itdispatch-gates --commands(89)--ran: 89 derived, 89 run, 0 NOT-MEASURED, 0 UNRUNcheck:pm-dispatch-gates✓ dispatch-gates self-test: 2011 cases pass., exit 0check:platform-checklist(derived for thedocs/qaedit)16 areas, 279 items. Every symbol anchor resolves, including the newpackaged-activation-ledger-reach.dogfood.test.ts#showcaseWithoutAutomation--no-inline-configover the 147 changed TS files8d985cf8fLint & Repo Gatesis success, with 196 of 198 steps success,PM dispatch-gates self-testamong them; the 2 skipped steps areUnmeasured-gate-tail reporter self-testandReport how many gates never ran. All threeDogfood Regression Gateshards,Dogfood Verify CLIand all sixTest Coreshards are successThe ablations (A1 to A7) were not re-run. Every line they cut is byte-identical between
08929776cand8d985cf8f. The cut files areverify/src/harness.ts,core/src/stack-plugins.tsandcli/src/commands/verify.ts. Over those files,git diff 08929776c 8d985cf8fshows only the 8 new TSDoc lines inharness.ts.The ablations as measured at
08929776c, throughscripts/ablation-replace.mjs, each restored with blob == HEAD andgit diff HEADempty:stop()removedos verify'shostRootremovedthe app's plugins[0] ('@fixture/verify-host-root-plugin') could not be loaded#22422 is fixed on
main(27a8b33de), and this branch contains it. The PM dispatch-gates self-test is green here and in CI.Merge round 2, measured at
749197628. Measured lightly, per the order: the swept file, the shard that holds it, the derived gates andcheck:pm-dispatch-gates. CI answers the rest.position-environment-write-throughalone (vitest run --project isolated)stop()and passes (4001 ms), so the instance rule releases on eachstop(). The run printed 0ENOENTlines, and nothing was written underexamples/app-showcaseOS_TEST_SHARD=3/3, CI's command,VITEST_MAX_WORKERS=3)rls-multitenant's owndescribe.skipIfdispatch-gates --commands(89, the same set as at8d985cf8f)--ran: 89 derived, 89 run, 0 NOT-MEASURED, 0 UNRUNcheck:pm-dispatch-gates✓ dispatch-gates self-test: 2011 cases pass., exit 0--no-inline-configon the swept filebootShowcase; the 4 remaining text matches are comments, plus the helper's own call749197628Console Pin Gate,Packed-tarball smoke (opt-in))Shards 1/3 and 2/3 and the verify, core and CLI tiers were not re-run locally; the merge changed none of this branch's files. It did bring
main's own changes topackages/core/src/security(#22441), and CI'sTest Corecovers those.Serial
mainmoved three times while the round measured, and each window was read against this branch's surface.00bee2724to3054516ef):mainchanged 4 dogfood files, and none of them boots the showcase.serve.tsauto-merged;mainadded the console not-built plugin, outside the plugin loop.3054516eftob9222dc70): feat(metadata-protocol)!: managed content is sealed — OS_METADATA_WRITABLE no longer opens an item a managed package ships (ADR-0131 D6, #15206 S2) #22401 rewroteshowcase-object-extension-scalar-divergence, and the helper was re-applied to it. It reboots withstop()between the two boots, so the instance rule holds.b9222dc70to2b61f2d9d): fix(service-storage)!: downloading a file with no attachments scope and no field owner requires a signed-in caller #22439 addedstorage-unclaimed-downloadwith a direct showcase boot, and it was swept.pnpm-lock.yamlauto-merged, andpnpm install --frozen-lockfilepasses.2b61f2d9dtoc512c255c, merged in round 2): feat(plugin-security)!: under single, Setup positions are written through to the environment ledger, and row-only positions are backfilled once (ADR-0131 D3, C2 stage S7) #22388 addedposition-environment-write-throughwith a direct showcase boot, and it was swept. The 8 other commits in the window change none of this branch's files and add no showcase boot.The other boots
mainadded in these windows each boot a configuration once and stop it, or reboot only afterstop():security-catalog-cold-boot-environment-holder,flow-runas,schedule-acting-organization,flow-door-elevated-start,managed-content-sealed;automation-trigger-elevated-door,action-flow-elevated-door.All of them are green in the runs above.
mainhas since moved tof66c440de(#22446, #22462, #22461). Those commits change two of this branch's swept files,showcase-anonymous-deny-surfaces(new API-description cases) andshowcase-public-form(a SYSTEM read-back of the created id).git merge-tree --write-tree HEAD origin/mainreports no conflict, and the would-be merged tree has 0 direct showcase boots:showcase-public-formkeepsbootShowcase. That combination has not been measured here; the merge group measures it.A dogfood file added later that boots the showcase directly will fail at boot (ENOENT), and the failure names the file. It should call
bootShowcase.Acceptance notes
hotcrm. A read-only read of
08cfa20was done; its suite was not run against this branch. Six of its test files keep one boot ofartifactlive and boot it a second time. Under the instance rule they will be refused, with the remedy, once hotcrm takes this release:case-assignment:766contact-email-tenant-scope:134flow-escalation-ownerless-case:58flow-scheduled:887hooks-runtime-service:583hooks-runtime:272None of them needs
hostRoot: hotcrm has nopluginsarray, and vitest's cwd is the app root.When
os verifyruns from the repository root, the showcase's MCP stdio connector cannot spawn./scripts/mcp-fixture.mjs, because that path resolves against the process cwd, notpackageRoot. The connector is registered degraded with an ERROR line, and the verify still passes. The underlying difference is two anchors for app-relative paths. Filed by the seat as connector-mcp: a declarative stdio transport resolves its relative command against the process cwd, while the same app's OpenAPI file ref resolves against the package root —showcase_mcp_toolsboots degraded from any other directory #22423.activity-parent-read-gate› 'list: every row returned …' runs close to vitest's 5000 ms default. On this branch's shard runs it read 2328, 3696, 3770, 3305 and 2925 ms. Twice, on a box at load average 5 to 7 on 4 vCPU, it hit 5020 ms (at91aff2e23and4a606ff8b). The file is outside this diff, and its fixture declares norequiresand noplugins, sobootStackcomposes it exactly as before. This is an observation, not filed. Carrier: none.Generated by Claude Code