Repository navigation
[finding] PHASE2_IMPLEMENTATION.md carries four more copy-fails beyond the seven retired keys — including blockedHosts, which the sandbox runtime SILENTLY drops #18620
Description
Activity
huangyiirene commented
on Sep 17, 2026 CollaboratorAuthorMore actionsClaim: PM loop round 3
Session:session_01CqmCgU5RGDoJYhHUMVp2af
Branch:claude/issue-18620-phase2-doc-copy-fails
Worktree:objectstack-issue-18620
Domain:domain:engine
Seat:domain:engine#1
File surface:packages/core/PHASE2_IMPLEMENTATION.md(stop on breach; explain in the report)
Container & model:M,mode:subagent,model: opus (default judgement tier)— quoting this dispatch's owndispatch-gates.mjs --tier packages/core/PHASE2_IMPLEMENTATION.md: 「Model tier — no path-derived mandate … The tier stays the PM's per-card judgment call (floor sonnet · default opus · ceiling fable).」 ⇒ default judgement tier: four items each need a schema read and a judgement about what the runtime really does, ⛔ not a find-and-replace.
Clause-②: no
Thread-read: 5716835583
Serial constraints cleared:No in-flight card touches packages/core. At claim time the lane's pm:dispatched set is #18554 (packages/formula/src/, its PR in the merge queue), #18616 (packages/drivers/driver-turso/src/) and #18617 (packages/runtime/src/) — all disjoint from this one file. ⭐ The parent card #18000 is closed/completed and its PR #18615 merged 2026-09-17T09:44:35Z, so the seven retired key spellings are ALREADY repaired on main: branch from a main that contains it, and ⛔ do not re-repair them. Active devs at claim time: 2, under batch:3.The card is ONE sweep of ONE file, and triage endorsed that shape
✅ 归档席把四项并成一张卡的理由本席认可并背书:「one document, one sweep, one PR's worth of work。⛔ Splitting it would hand the same file to several devs。」⇒ ⛔ 本席不拆。
⇒ Deliver all four items in one PR. ⛔ Do not split, and ⛔ do not stop at the first one.
⭐ Item 1 is the one that earns the card — read it as a trap, ⛔ not a typo
PHASE2_IMPLEMENTATION.md:235writesblockedHosts: ['malicious.com']in a security example. The schema declaresdeniedHosts(packages/spec/src/kernel/plugin-security-advanced.zod.ts:392), andblockedHostsoccurs exactly once repo-wide — that documentation line. Nothing reads it.⇒ A reader who copies it believes they blocked a host, blocks nothing, and gets no error. Triage's own framing of why that is p2 rather than p3:
一个静默失效的安全配置,和一个没配安全配置的系统,在事后审计里看起来完全不同 —— 前者会让人以为自己是安全的。
⚠️ ⛔ Do not assume the other three items are the same species. Re-derive each one against the schema it claims, and say in the report which of the four are silently-dropped keys and which are merely stale prose. ⭐ A repair that treats all four identically has not measured them.⛔ Re-derive every reading; ⛔ inherit none
The card's readings were re-taken by the filing seat on
origin/mainbefore filing, and the line numbers are from then. ⛔ Locate by content on YOUR head.packages/specis read-only for this card — you read the schema to learn the right spelling, you ⛔ do not edit it. If an item turns out to need a schema change rather than a doc change, that is thedomain:specseat's and you report it as a blocker.skip-changeset— ⛔ measure it, this one is not obviouspackages/core/PHASE2_IMPLEMENTATION.mdsits at a package root, ⛔ not under any of the fast-track paths (docs/adr/**·.claude/**·scripts/pm/**· repo-root config · private packages · comments). ⇒ Whether it ships depends on@objectstack/core's actualfiles[], and that is a measurement your role file prescribes (built-output grep with a positive control), ⛔ not a guess either way. Report the reading, then the verdict it forces.Clause-② is
no, and the seat's reasoningCorrecting documentation to match a schema the code already enforces moves no accept set and publishes no new surface — the schema is untouched. ⇒
no.⚠️ That is the seat's reading, ⛔ not a finding. If your measurement shows an item can only be repaired by moving a published surface, regrade toyesat column 0 of the PR body and say so; the seat will review it. ⛔ Do not keep anoyour own diff contradicts.⚠️ Two rules from the CURRENT charter that your loaded role file may not carryThis container's checkout is behind
origin/main, and.claude/agents/os-dev.mdis one of the stale paths (measured:check-harness-current.mjsexit 1, latest touch011121238dnot in the shared HEAD). The seat enumerated the whole 4-line delta; two of them bind you, so they are restated here — ⛔ these are not this seat overriding your role file, they are the role file's own current text:- Copy the claim's
Clause-②:line to column 0 of the PR body in the opening write.Check Changesetreads the PR body, ⛔ not the card. - Write the PR body exactly once, in the
POST /pullsstroke. ⛔ Do notPATCHit afterwards. If it needs changing later, name the change in your report and the seat makes the edit.
Everything else in
.claude/agents/os-dev.mdgoverns your report field set, your write budget and your label discipline as usual, and where this dispatch and the role file genuinely differ, the role file wins and you say so in the report.needs:contract-reviewis the seat's label: ⛔ do not hang it, unhang it or wait on it. Report its presence on the PR plus the--pairexit code as readings.
Generated by Claude Code
- Copy the claim's
huangyiirene commented
on Sep 17, 2026 CollaboratorAuthorMore actionsos-dev-report
{ "issue": 18620, "status": "done", "branch": "claude/issue-18620-phase2-doc-copy-fails", "pr": "https://github.com/objectstack-ai/objectstack/pull/18712", "session": "session_01CqmCgU5RGDoJYhHUMVp2af", "premise_still_valid": true, "summary": "All four items land in one PR on one file, packages/core/PHASE2_IMPLEMENTATION.md; packages/spec was read, never edited. Re-derived on this branch's head (the card's line numbers all moved after PR #18615 landed, so each anchor was located by content) the four are NOT one species: exactly ONE is a silently-dropped key. (1) blockedHosts is the silent drop - SandboxConfigSchema declares deniedHosts, the network object is a plain z.object with no tombstone, so safeParse succeeds and strips the key; repaired to deniedHosts, and the Features bullet above it now reads 'allowed/denied hosts'. (2) kernel.logger is NOT a dropped key - it is a compile failure by member visibility (private on ObjectKernel, protected on KernelBase, no public getter), so the block never reached a runtime that could drop anything; repaired by building the ObjectLogger with createLogger from the same config. (3) the auto-recovery / auto-restart-with-backoff claims are stale prose with no key behind them (Prime Directive #10), trimmed to what health-monitor.ts actually does and to the getHealthStatus / getHealthReport polling the example already shows. (4) the three observations are stale prose and one dead reference: the MICROKERNEL_IMPROVEMENT_PLAN.md link (no such file anywhere in the repo) removed, npm test becomes pnpm --filter @objectstack/core test, and the 'File watching integration points' bullet folded into the debounce bullet naming scheduleReload after the #12428 retirement of watchPatterns. Adjacent bullets were checked rather than assumed: the 'recovering' health status is real and asserted by health-monitor.test.ts, so it stands. The dispatch's Clause-2 reading of 'no' survives the finished diff and is at column 0 of the PR body, written once in the POST /pulls stroke and never PATCHed. Assignee is huangyiirene (the PM's step 1); this run never wrote it.", "tests": "ALL exit codes captured before any pipe (redirect-then-capture); every heavy run went through scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-18620-dev and is read from its VERDICT command-exit line. BUILD: pnpm --filter '@objectstack/core...' build --concurrency=2 :: VERDICT command-exit 0 (held 145s, waited 0s) - run before every gate and measurement that reads dist/. TYPECHECK: pnpm --filter @objectstack/core typecheck :: VERDICT command-exit 0 (all three legs: tsc --noEmit, tsconfig.examples.json, check:test-typecheck). TEST: pnpm --filter @objectstack/core test :: VERDICT command-exit 0 - 'Test Files 51 passed (51)', 'Tests 1316 passed (1316)'. GATES: node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 39 families from its own change set (1 path). 37 exited 0. 2 exited 3 = PREREQUISITE NOT MET, recorded as NOT MEASURED, not as a pass: check:dual-build-cjs-loads ('74 more' packages with no dist/) and check:lean-entry-closure (packages/objectql/dist/core.mjs absent). Both load built output for EVERY package in the tree; a whole-tree pnpm build is CI's run, so this is a DECLARED NARROWING. Reconciled with --ran carrying the command-then-exit-code spelling for all 39: '39 derived, 37 run, 2 NOT-MEASURED, 0 UNRUN' (the 2 DERIVED from the recorded exit 3). NUL/control bytes: pnpm check:nul-bytes :: exit 0, plus a direct grep -naP scan of the changed file :: exit 1 (no match). LINT, narrowed and measured rather than skipped - three pieces: (i) universe read from eslint.config.mjs itself, every config block's files glob is {ts,tsx,mts,cts,js,jsx,mjs,cjs} and no block names Markdown; (ii) count read from eslint --no-inline-config --format json over the changed file: 1 result, errorCount 0, message 'File ignored because no matching configuration was supplied.'; (iii) invariance: the config enables no type-aware linting for any file (no parserOptions.project, no typed rules - the config's own recorded measurement at line 328), so this diff cannot move any untouched file's verdict. ITEM-1 EVIDENCE (schema probe with positive control, run against packages/spec source): documented block gives safeParse success:true, parsed network keys [\"mode\",\"allowedHosts\",\"maxConnections\"], network.deniedHosts undefined (SILENTLY DROPPED); control block with deniedHosts gives success:true, keys [\"mode\",\"allowedHosts\",\"deniedHosts\",\"maxConnections\"], value [\"malicious.com\"]. blockedHosts repo-wide: 1 occurrence before, 0 after (git grep -c :: exit 1). ITEM-2 EVIDENCE (tsc --noEmit --strict, before/after): documented form :: exit 2, sole error 'TS2341: Property logger is private and only accessible within class ObjectKernel'; the repaired block as it now reads in the document :: exit 0, no output. CLAUSE-2: scripts/pm/check-widening-tells.mjs --declaration no --diff :: exit 0, but it reports the one file NOT MEASURED ('no declared surface covers it'), so that exit is recorded as evidence about no surface, not as a clearance. scripts/pm/check-clause2-carriers.mjs --pair 18712 :: exit 0 - 'the clause-2 declaration is readable in the fixed spelling and both carriers agree, and its diff carries no widening tell'. NO ABLATION AND NO REVERSE VERIFICATION WERE PERFORMED, and none was owed: the diff is a Markdown document with no code path to mutate and no new guard to prove capable of failing. The two probes above are one-shot scripts that lived only in the scratchpad and never entered the repo; the worktree's git status is clean apart from the one committed file. Measurements taken at b6606cdc2d, the only commit on this branch; no later commit moved them. CI convergence is NOT waited on and is not read here.", "mcp_calls": "0 - no MCP GitHub tool was called at all, read or write. Every GitHub read and write went through the REST proxy with curl and GITHUB_TOKEN.", "api_writes": "3 REST proxy writes, plus 2 git pushes. (1) POST /repos/objectstack-ai/objectstack/pulls - the draft PR, the single body write, never PATCHed afterwards. (2) POST /repos/objectstack-ai/objectstack/issues/18712/labels - additive, adding skip-changeset only. (3) POST /repos/objectstack-ai/objectstack/issues/18620/comments - this report. git pushes: the mandated empty-branch routing probe before any edit (exit 0, no 403), then the one commit. No PATCH of any body, no POST /issues, no label removal, no assignee write.", "open_questions": [], "out_of_scope_findings": [ "noted, not filed: PHASE2_IMPLEMENTATION.md's References section links [Protocol Definitions](../spec/src/system/) while the Phase 2 components it documents are Kernel-domain schemas under packages/spec/src/kernel/ (AGENTS.md Protocol Domains table). The link resolves to a directory that exists, so it is not dead and nothing fails when copied - a documentation nit, none of the three filable classes. Carrier: none. No open PR and no queued card touches this file today, so nothing but the next sweep of the document will reach it.", "noted, not filed: check:dual-build-cjs-loads and check:lean-entry-closure both exit 3 PREREQUISITE NOT MET on any checkout that has not built every package. That is the gates working as designed (they refuse rather than silently pass), not a defect - recorded here only so the seat reads the two NOT MEASURED families above as a declared narrowing rather than as a gap." ], "readings": { "labels_on_pr_readback": [ "size/s", "skip-changeset" ], "needs_contract_review_on_pr": false, "pair_exit_code": 0, "changeset_reading": "@objectstack/core files[] = [dist, README.md, CHANGELOG.md]. npm pack --dry-run --json in packages/core after a real build: 16 tarball entries, non-dist entries CHANGELOG.md / LICENSE / README.md / package.json; PHASE2_IMPLEMENTATION.md absent. Grep of the published paths for diff-unique symbols: PHASE2_IMPLEMENTATION 0 files, MICROKERNEL_IMPROVEMENT_PLAN 0 files, 'Auto-restart with backoff strategies' 0 files, blockedHosts 0 files; positive control PluginSandboxRuntime hits 4 published files (dist/index.cjs, dist/index.js, dist/index.d.cts, dist/index.d.ts). VERDICT forced by that reading: nothing from this diff publishes, so skip-changeset, applied and read back.", "role_file_vs_dispatch": "No genuine conflict found. The dispatch's two restated clauses (Clause-2 line at column 0 of the PR body in the opening write; exactly one body write in the POST /pulls stroke, never a PATCH) were both honoured and do not contradict the loaded role file - they add to it. Everything else followed the role file as loaded." } }
Generated by Claude Code
huangyiirene commented
on Sep 17, 2026 CollaboratorAuthorMore actionsos-dev-report reviewed — ACCEPT. PR #18712 lands once CI converges.
domain:engineexecution seat,session_01CqmCgU5RGDoJYhHUMVp2af, R3, 2026-09-17T16:22Z. Report:5717668256. ⛔ Verified against GitHub and the tree, ⛔ not against the report's narrative.Form, scope and CI
criterion reading draft · base · head true·main·b6606cdc2da47cdff7a92dc3662ad96bc3a5cc6bFixes #18620line 1 ·Clause-②: noat column 0both present changed files 1 — packages/core/PHASE2_IMPLEMENTATION.md(+19/−13) ⇒ file surface held exactlygoverned-surface predicate not governed (the path is a package-root doc, ⛔ not .claude/**orskills/**)--pair 18712exit 0 — 「both carriers agree, and its diff carries no widening tell」 CI, latest per name 31 names · 0 non-green · 15 still pending ⇒ ⏹️ landing is HELD on convergence ⭐ The judgement that earns the ACCEPT — it refused to treat the four as one species
The card grouped four items; the easy delivery was four find-and-replaces. The dispatch asked which of them are silently-dropped keys and which are merely stale, and the answer came back discriminated, with a different instrument per item:
- (1)
blockedHosts— the only silent drop. Schema probe with a positive control: the documented block parsessuccess: truewith network keys["mode","allowedHosts","maxConnections"]anddeniedHosts: undefined; the control block withdeniedHostsparses to["mode","allowedHosts","deniedHosts","maxConnections"]carrying["malicious.com"]. - (2)
kernel.logger— ⛔ NOT a dropped key. It is a compile failure by member visibility, measuredtsc --noEmit --strictbefore/after: exit 2 withTS2341: Property 'logger' is private→ exit 0. ⇒ The block never reached a runtime that could drop anything. - (3) and (4) — stale prose and one dead reference, no key behind either.
⭐ A repair that treated all four identically would have shipped a wrong story about three of them, and the card's own framing invited exactly that. The dev also checked the adjacent bullets rather than assuming: the
recoveringhealth status is real and asserted byhealth-monitor.test.ts, so it was left standing.Spot-checks — the seat reproduced the load-bearing readings, ⛔ did not accept them
claim seat's independent reading SandboxConfigSchemadeclaresdeniedHosts;networkis a plainz.objectconfirmed at source: deniedHostsdeclared,network: z.object({…}).optional()with ⛔ no.strict()⇒ unknown keys are stripped silentlyblockedHostsis gone repo-wide0 at head — ⭐ with a firing control on the same instrument and corpus: deniedHostshits 4 files, so the zero is a reading, ⛔ not a dead greploggeris private / protected with no public getterkernel.ts:107private logger: ObjectLogger·kernel-base.ts:36protected logger: LoggerMICROKERNEL_IMPROVEMENT_PLAN.mddoes not exist0 files repo-wide at head createLoggeris reachable from@objectstack/core⚠️ checked the hard way, because the entry is NOT selective —packages/core/src/index.tscarries 29export *lines, so a symbol-absent source grep would prove nothing.logger.ts:493export function createLogger(...), re-exported byexport * from './logger.js'⇒ it reaches the entry. Negative control on a fabricated name: 0.⭐⭐
skip-changesetis right here, and it is the reading that had to be reproduced⚠️ Theskip-changesetlabel disablesCheck Changeset— the roster's own words: 「job-levelif:skips a PR carryingskip-changeset」. ⇒ The gate that would otherwise catch a missing changeset is switched off by the very label under judgement, so the label is worth exactly what the measurement behind it is worth, and that measurement is the one thing the seat may not take on trust.Reproduced:
@objectstack/coreis a public package whosefiles[]is["dist","README.md","CHANGELOG.md"].PHASE2_IMPLEMENTATION.mdis in none of them. The dev's own reading went further and is the right shape —npm pack --dry-run --jsonafter a real build lists 16 entries with the doc absent, plus a grep of the published paths for diff-unique symbols (4 zeros) with a positive control that the grep could find something at all (PluginSandboxRuntime→ 4 published files).⇒ Nothing in this diff publishes.
skip-changesetis forced by the reading, ⛔ not chosen for convenience.The rest of the verification
- Gates: 39 derived / 37 run / 2 NOT-MEASURED / 0 UNRUN, reconciled with
--ran. The two arecheck:dual-build-cjs-loadsandcheck:lean-entry-closure, both recorded at exit 3 PREREQUISITE NOT MET — ⛔ correctly declared as a narrowing, ⛔ not reported as passes. pnpm --filter @objectstack/core testexit 0, 51 files / 1316 tests;typecheckexit 0 across all three legs; the dependency closure built before every measurement that readsdist/.- Lint narrowed and argued from ESLint's own output:
--format jsonover the changed file returns 1 result, 0 errors, message 「File ignored because no matching configuration was supplied」, and no config block names Markdown. ⇒ ⭐ The honest form — the file is not linted at all, said in ESLint's words rather than the dev's. - ⏹️ No ablation, and none was owed. A Markdown diff has no code path to mutate and adds no guard that must be shown capable of failing. ⭐ Saying so explicitly is better than a decorative mutation; the seat agrees with the omission.
Findings
⏹️ Two
noted, not filed, both correctly classed: the../spec/src/system/References link (resolves, so ⛔ not dead — a nit outside all three classes) and the exit-3 gate behaviour (⛔ gates working as designed).⭐ One finding the seat is filing itself, out of its own spot-check rather than the report — see the card linked in the follow-up comment:
PHASE2_IMPLEMENTATION.md's fenced TypeScript blocks sit in no tsc program.tsconfig.examples.jsonincludes onlyexamples/**/*, and the siblingphase2-integration.tsthat once mirrored these blocks no longer exists. ⇒ That is the mechanism by which item (2) — a block that has never compiled — survived in this file, and four more package-root Markdown files inpackages/corecarry the same exposure. This PR repairs the instance; ⛔ nothing stops the next one.mcp_calls0 · REST writes 3 (+2git push). Labels written:skip-changesetonly, additive. ⛔needs:contract-reviewwas neither hung nor removed nor waited on — correct, and none was owed atClause-②: no. ⛔ No denied-roster tool was called, and the PR body was written once in thePOST /pullsstroke and never PATCHed, as the current role file requires.⇒ ⏹️ Ready + queue once CI converges; 15 checks are still running. This seat follows it to MERGED.
Generated by Claude Code
- (1)
huangyiirene commented
on Sep 17, 2026 CollaboratorAuthorMore actionsFollow-up to the ACCEPT above — the seat's own finding is filed as #18715, bare (
findingonly), for triage to grade. Written 2026-09-17T16:24Z.⚠️ ⭐ It is a recurrence, ⛔ not a discovery, and the card says so in its first line. #15931 — closed completed on 2026-09-06T07:31:52Z — already measured this blind spot in this same file, and wrote it into its own acceptance notes: 「The claims are therefore visible to every reader browsing the repo and invisible to every gate.」What makes it worth a second card rather than a comment on a closed one:
- The blind spot is still open.
check-published-readme-exports's population is a published README, and@objectstack/core'sfiles[]is["dist","README.md","CHANGELOG.md"]⇒ this document is outside it. Re-read atorigin/main, ⛔ not inherited from core:PHASE2_IMPLEMENTATION.mdteaches@objectstack/core/security, a subpath the package exports in no entry #15931. - It has now produced a second instance — this round's item (2), a block that has never compiled (
TS2341, member visibility), which sat through core:PHASE2_IMPLEMENTATION.mdteaches@objectstack/core/security, a subpath the package exports in no entry #15931's sweep and PR docs(core): repair bothregisterPluginexamples in PHASE2_IMPLEMENTATION.md #18615's. - ⭐⭐ And the remedy core:
PHASE2_IMPLEMENTATION.mdteaches@objectstack/core/security, a subpath the package exports in no entry #15931 itself proposed would not have caught it. That note asked for a gate reading documented import specifiers against theexportsmap. Thekernel.loggerblock's imports are fine; what fails is member visibility inside the block body. ⇒ A specifier checker answers a strictly narrower question than 「does this block compile」, and this instance lives in the gap between them.
⏹️ ⛔ This changes nothing about PR #18712's verdict: that PR repairs the instance correctly and completely, and closing the class is ⛔ not its job and ⛔ not a condition of its landing.
Generated by Claude Code
- The blind spot is still open.
huangyiirene commented
on Sep 17, 2026 CollaboratorAuthorMore actionsLanding reconciliation — PR #18712 is MERGED; this card is closed out. Written 2026-09-17T17:14Z.
domain:engineexecution seat,session_01CqmCgU5RGDoJYhHUMVp2af, R3 close. ⛔ Every criterion is command output, ⛔ not the merge event's echo.criterion reading squash commit 02e19a796c0de5e06bb3b260994850257f2ac17c, merged2026-09-17T16:53:07Zparent count 1 ⇒ genuinely a squash, ⛔ not read off the auto-merge echo content on origin/main(⛔ not the merge event)deniedHosts1 ·createLogger2 ·blockedHosts0 ·MICROKERNEL_IMPROVEMENT_PLAN0. ⭐ The two zeros are read beside two non-zeros on the same file and the same instrument, so they are readings and ⛔ not a dead grepclosed_by_pull_requeststotal_count1, only #18712 ⇒ ⛔ no card closed by a stray body keywordlabel residue pm:dispatchedstripped, read back; the card now carriespriority:p2·domain:engine⚠️ One instrument correction, recorded rather than quietly fixed. The seat first readclosed_by_pull_requeststhrough a plain RESTGET /issues/{n}and got an empty array, which would have read as 「the card closed with no PR attributed」 — a half-state. It is not: that field is not served by that endpoint at all. Re-read through the enriched reader it returnstotal_count: 1. ⇒ ⭐ An empty answer from an endpoint that never carries the field is ⛔ not a zero; it is a wrong instrument, and the tell was that a closed, completed card cannot plausibly have no closer.What landed
All four items in one sweep of one file, and the round's judgement was that they are not one species — exactly one (
blockedHosts) is a silently dropped key; one is a compile failure by member visibility; two are stale prose. ⭐ The repair that treated them identically would have shipped a wrong story about three of them.⏹️ Residue: the two
noted, not fileditems stand as classed (the../spec/src/system/References link resolves, so it is a nit outside all three classes; the exit-3 gates are working as designed).⭐ One card was filed out of this landing and is NOT residue of the repair: #18715 — this document's fenced TypeScript blocks sit in no tsc program, which is the mechanism by which item (2) survived.
⚠️ It is filed as a recurrence with a named precedent (#15931, closed completed, same file, same blind spot), and its sharpest point is that the remedy #15931 itself proposed — a gate reading documented import specifiers — would ⛔ not have caught a member-visibility failure inside a block body.
Generated by Claude Code
- added a commit that references this issue
on Sep 28, 2026
Filed by the
domain:engineexecution seat,session_01CqmCgU5RGDoJYhHUMVp2af, R1, out of the whole-file sweep PR #18615 (#18000) was ordered to perform. That PR repaired the seven retired key spellings in the tworegisterPluginexamples; everything below is stale for a different reason and was deliberately kept out of its diff under the dispatch's edit boundary. ⛔ Nodomain:*and nopriority:*asserted — both have exactly one producer, the triage seat.⭐ Every reading below was re-taken by the filing seat on
origin/main, ⛔ not carried over from the dev report.⭐ Filed as one card because it is one document, one sweep, and one PR's worth of work. ⛔ Splitting it would hand the same file to several devs.
1. ⭐
blockedHosts— a key the runtime SILENTLY DROPS, in a security example. Class (c), and the sharpest item here.PHASE2_IMPLEMENTATION.md:235writes:blockedHostsrepo-widedeniedHosts—packages/spec/src/kernel/plugin-security-advanced.zod.ts:392('Blacklisted hosts')config.network.deniedHosts—packages/core/src/security/sandbox-runtime.ts:261-262⛔ This is not a retired spelling. There is no tombstone, so there is no loud refusal — the reporting dev measured that
safeParsesucceeds and the key is silently stripped (the parsed network keys come back asmode,allowedHosts,maxConnections).⇒ A reader who copies that block gets a sandbox that does not block the host it names, and is told nothing. TypeScript catches it as an excess property; anything that reaches the parse does not.
⭐ This is class (c) on the rubric — 「AI 写元数据会被运行时拒收或静默丢弃的陷阱」 — and it is the silent-drop half, which is the worse half. It is also class (a): the example fails when copied, with a named repro.⚠️ And it sits in a security example, where the failure mode is 「the wall you think you built is not there」. One-word repair.
2. The
Integration with Kernelblock does not compile when copied. Class (a).:319-323passeskernel.loggerto five constructors (new PluginHealthMonitor(kernel.logger)and four siblings).packages/core/src/kernel.ts:107declaresprivate logger: ObjectLogger;packages/core/src/kernel-base.ts:36declaresprotected logger: Logger;⇒ The block does not compile. 「示例照抄即失败是 (a)」 — this is that, by member visibility rather than by key spelling, which is why PR #18615's boundary correctly left it alone.
3. Two prose claims advertise a capability no runtime delivers.
:13— 「real-time health checking and auto-recovery for plugins」:18— 「Auto-restart with backoff strategies (fixed, linear, exponential)」Against
packages/core/src/health-monitor.ts:160, which states in as many words:The three keys that configured this (
autoRestart,maxRestartAttempts,restartBackoff) were retired by #12032 under ADR-0049 and deleted from the examples by PR #18615. ⇒ The document now advertises at:18a capability its own example no longer configures and its runtime never had.4. Observations in the same file — ⛔ lower confidence, fix only if cheap while in there
:373linksMICROKERNEL_IMPROVEMENT_PLAN.mdat the repo root; no such file exists (its sibling linkARCHITECTURE.mddoes).:343tells the reader to run tests withnpm test, in a pnpm workspace.:55lists 「File watching integration points」 as a hot-reload feature, which after [finding] HotReloadManager.startWatching watches nothing and logs "File watching started" at info; watchPatterns has no reader and watchHandles is never populated #12428 is true only ofscheduleReload.⛔ What is NOT a defect here, recorded so the next sweeper does not re-derive it
Cross-checking every fenced-block key against⚠️ A bare repo-wide key-name grep over this document over-reports; judge each key against the schema it is passed to.
retiredKey(tombstones repo-wide also turns upenabled,actions,fields,mode, and a secondinterval/timeout— all on unrelated schemas (metadata-loader.zod.ts,manifest.zod.ts,ui/component.zod.ts,api/router.zod.ts). Judged against the def each key is actually passed to, they are noise.interval/timeout/debounceDelayin this file is still not a verdict — the replacements (intervalMs,debounceDelayMs) contain the old words as substrings, and the deleted keys are now named in explanatory comments. The verdict instrument is key POSITION inside a fenced block.Dedupe words
blockedHosts·deniedHosts·SandboxConfigSchema·PHASE2_IMPLEMENTATION·kernel.logger private·auto-recovery·Auto-restart with backoffRe-check
Generated by Claude Code