Repository navigation
Closed
Labels
effort/sSmall: expected under 2 hours of workSmall: expected under 2 hours of workkind/enhancementpriority/normalOrdinary priority (the default)Ordinary priority (the default)source/design-architectFiled by the repo design architect jobFiled by the repo design architect jobstatus/needs-triageNot yet triaged; needs a first lookNot yet triaged; needs a first looktask/small-fixQueue packet kind: bounded fix with reproduction and targeted testsQueue packet kind: bounded fix with reproduction and targeted tests
Description
Phase 3 of design #2953 ("define, don't assign" — the write-side prototype contract). Phases 1–2 are adopted origin issues: Phase 1 = #2941 (aggregator snapshots), Phase 2 = #2828 (bin/record) + #2851 (aggregator cost-explorer). This phase is the closing inventory audit + contract statement. Gated on Phases 1–2 landing — do not start the audit before both land.
Design doc: files/designs/code-proto-write-side.md in the keep-the-four-repos-healthy goal workspace.
Scope
- Inventory. Grep the repo's TS/JS/mjs (excluding vendored assets such as
pm-stack/aggregator/src/assets/datastar.js, and tests) for the four non-conforming write forms with dynamic keys:obj[key] = vwhere the key is not a literal;obj[key] ??= …accumulators;- copy loops
dst[k] = src[k]overObject.entries/Object.keys; Object.assign(dst, src)with a non-literalsrc.
- Disposition every hit as exactly one of:
- (a) covered by Phases 1–2 of Design: define, don't assign — untrusted keys are stored with define semantics, never through the __proto__ setter #2953;
- (b) external-key (a caller, document, feed, file, peer, or user can spell the key) — fix it under this design before closing, or file it as a named follow-up issue linked here;
- (c) internal-only (all keys code-constructed) — named in the closing evidence with the reason.
Candidates already visible at design time — disposition them, do not pre-judge: antigravity-direct's schema walkers inbin/antigravity-direct.mjs(merged[k],sub[name],props[name]— keys from external tool schemas);bin/provider-catalog-sync.mjs(report.providers[providerId],(added[pid] ??= []));pkgs/id/web/src/world.ts:181Object.assign(records, frame.records ?? {})(a peer-supplied frame);bin/sync-models.mjs'sprov.models[baseId]family (parsed config keys). Also report any recursive/deep-merge helper the sweep finds (the design doc's open question — report, don't pre-decide its shape).
- Contract statement. Write the define-semantics rule (one paragraph + the probe matrix) into the docs that already state contracts for the covered surfaces: the aggregator README (or its snapshots/cost-explorer docs, wherever its store contracts live) and the
bin/record.mjsheader comment if it does not already carry it. No new docs files. - Close Design: define, don't assign — untrusted keys are stored with define semantics, never through the __proto__ setter #2953 with the audit evidence (the disposition table) posted as a comment on Design: define, don't assign — untrusted keys are stored with define semantics, never through the __proto__ setter #2953 and on this issue.
Acceptance criteria
- The disposition table covers every grep hit from step 1, with the grep commands recorded so the sweep is reproducible.
- Every (b) hit is either fixed under this issue (with the design's probe matrix as tests:
__proto__string value,__proto__object value,constructor,toString, ordinary key — own property present, JSON round-trip preserves, container +Object.prototypeprototypes unmoved) or filed as a named follow-up issue linked here. - design(own-key lookups): a plain object is not a map for untrusted keys — one own-key rule for every dynamic lookup #2792's Phase 3 read-side audit is not duplicated: read-only lookup sites found by the sweep are listed in the closing evidence as "design(own-key lookups): a plain object is not a map for untrusted keys — one own-key rule for every dynamic lookup #2792 scope" and not fixed here.
- Contract statement landed in the docs named in step 3.
- Closing evidence posted on Design: define, don't assign — untrusted keys are stored with define semantics, never through the __proto__ setter #2953 and this issue; Design: define, don't assign — untrusted keys are stored with define semantics, never through the __proto__ setter #2953 closed or its remaining follow-ups named.
Out of scope
- Re-litigating the decisions recorded on Design: define, don't assign — untrusted keys are stored with define semantics, never through the __proto__ setter #2953 (preserve-don't-reject; accumulators fixed by container construction, not
hasOwn). - Read-side lookups (design(own-key lookups): a plain object is not a map for untrusted keys — one own-key rule for every dynamic lookup #2792's phases own them, including today's id(web): mimeToExtension returns Object.prototype members for prototype-named MIME types — 'constructor' yields the Object constructor instead of 'bin', corrupting paste filenames #2920/id(web): terminalBytesForKey treats Object.prototype members as special keys — 'toString'/'constructor' send native-function source bytes as world terminal input instead of null #2919).
- Any site whose keys are verified internal-only — disposition (c) is a complete outcome for those.
Metadata
Metadata
Assignees
Labels
effort/sSmall: expected under 2 hours of workSmall: expected under 2 hours of workkind/enhancementpriority/normalOrdinary priority (the default)Ordinary priority (the default)source/design-architectFiled by the repo design architect jobFiled by the repo design architect jobstatus/needs-triageNot yet triaged; needs a first lookNot yet triaged; needs a first looktask/small-fixQueue packet kind: bounded fix with reproduction and targeted testsQueue packet kind: bounded fix with reproduction and targeted tests
Activity
dezren39 commentedon Oct 31, 2026
agent-note:v1 — design-architect pass 24 (2026-10-31): filed this pass as Phase 3 of design #2953 (define, don't assign). Gated on Phases 1–2 (Phase 1 = #2941; Phase 2 = #2828 + #2851), hence status/blocked; linked as a sub-issue of #2953 (verified in its sub_issues list). Triage: record the gating and the phase structure, do NOT re-file/re-scope/split, and do not start the audit until both phases have landed — the inventory is only meaningful once the covered sites are converted. Candidate sites to disposition (not pre-judged) are named in this issue's body; read-side hits belong to #2792's audit and are listed, not fixed, here.
dezren39 commentedon Oct 31, 2026
🤖 Agent note · parked — triage verdict for queue task 4234
Scope: CONFIRMED. This phase is exactly as #2953's design scopes it: the closing inventory audit of the four non-conforming dynamic-key write forms (
obj[key] = v,??=accumulators,Object.entries/Object.keyscopy loops,Object.assignwith non-literal src) across the repo's TS/JS/mjs (vendored assets and tests excluded), a disposition for every hit — (a) covered by Phases 1–2, (b) external-key → fix here or file a named follow-up, (c) internal-only → named with reason — the design's probe matrix as the test shape for (b) fixes, the contract statement into the aggregator store docs +bin/record.mjsheader, and closing evidence on #2953 + here. The candidate sites named at design time (antigravity-direct schema walkers, provider-catalog-sync,pkgs/id/web/src/world.ts:181Object.assign on a peer frame, sync-models) are to be dispositioned, not pre-judged. Read-side sites belong to #2792 and are listed, not fixed.Gating: NOT cleared (fresh check 2026-10-31T06:45Z). All three adopted origin issues are still OPEN:
__proto__grouping) — OPEN__proto__drop) — OPEN__proto__setup) — OPENPer this issue's own terms ("do not start the audit before both land"), the audit does not start and the implementation follow-up packet is NOT enqueued yet — it gets enqueued, with these acceptance criteria intact, once the gating clears. This issue keeps
status/blocked(per its acceptance criteria) and gainsqueue/parked+work/assignedfor this task's park; the worker task is parked on the gate.Recovery note (transparency): this task was claimed at 05:52Z, but the claim output shown to the claiming lane was corrupted in transit (it displayed a different, non-existent packet), so the claim sat unworked until the true claim output surfaced and the task was recovered by heartbeat at ~06:44Z. No parallel work was started in the meantime.
dezren39 commentedon Oct 31, 2026
🤖 Agent note · parked
status/needs-triage,queue/queued)status/needs-triage,queue/queued)status/needs-triage,queue/queued)status/blocked. Resume when aggregator(snapshots): SnapshotStore groups by serviceId into plain objects — a '__proto__'/'constructor'/'toString' serviceId crashes byService (blanking all snapshot history) and pollutes Object.prototype during compact #2941, record(loose): a '__proto__' field in loose text is silently dropped — parseLoose assigns into a plain object, so the field never reaches the JSONL line (the JSON path preserves it) #2828, and aggregator(cost-explorer): a setup named '__proto__' is silently never saved — save/import assign into a plain object, so the name becomes the store's prototype instead of an entry #2851 have all merged.dezren39 commentedon Oct 31, 2026
🤖 Agent note · gate re-checked fresh, still not met — parked
status/blockedstays; no label change needed.dezren39 commentedon Oct 31, 2026
🤖 Agent note · parked
57 remaining items
dezren39 commentedon Nov 3, 2026
agent-note:v1
state: picked-up
task 7683 (small_fix, lane code-j, direct) claimed 2026-11-03T14:16Z — the implementation follow-up from task 4234's triage (comment 6604140489). Gate verified cleared there fresh today (#2941/#2828/#2851 all CLOSED). Running the closing inventory audit at current main: four grep forms over bin/, pm-stack/, pkgs/ (vendored + tests excluded), disposition every hit, fix external-key hits with the probe matrix as tests, contract statement into pm-stack/aggregator/README.md and bin/record.mjs header, closing evidence on #2954 and #2953.
Merge pull request #4956 from developing-today/queue/7683-2954-define…
dezren39 commentedon Nov 3, 2026
agent-note:v1
state: done — Phase 3 closing inventory audit complete
task 7683 (small_fix, lane code-j). Gate was verified cleared by task 4234 (comment 6604140489): #2941, #2828, #2851 all CLOSED. Fixes landed in PR #4956 (merged, 05fd4bb). This comment is the closing evidence; the same table is posted on #2953, which is closed with its one remaining follow-up named.
Sweep (reproducible)
Run at origin/main bc50cba over
bin pm-stack pkgs,--include='*.ts' --include='*.tsx' --include='*.js' --include='*.mjs', excluding the vendoredpm-stack/aggregator/src/assets/datastar.jsand test files:grep -rnE '\][[:space:]]*=[^=]'→ 579 hitsgrep -rnE '\][[:space:]]*\?\?='→ 5 hitsObject.entries/Object.keyssubset of G1, dispositioned individually belowgrep -rnE 'Object\.assign\('→ 21 hitsDisposition table
(a) Covered by Phases 1–2 (verified landed at current main by task 4234): aggregator snapshots grouping (
snapshots.ts— Map +Object.fromEntries), cost-explorer save/import store (render.ts—Object.create(null)container),bin/record.mjsparseLoose(Object.defineProperty). The remainingrender.tsG1 hits are DOM/render-internal writes in the same file — class (c).(b) External-key — FIXED in PR #4956 (define semantics; probe matrix as tests where a harness exists):
bin/antigravity-direct.mjsschema walkers — sibling-merge keys, schema-map names, property names (external tool schemas) →defineValue(Object.defineProperty). The same function's allowlist-filtered writes (SCHEMA_FIELDS/SCHEMA_VALUE_KEYS/SCHEMA_MAP_KEYSmembership) are class (c): the key set is code-defined.bin/provider-catalog-sync.mjs—report.providers×3 andapplyReport.providers×2 (provider ids from parsed config),applyAdditionsaccumulator (??=→ Map +Object.fromEntries),commonSuffixcounts (model-name tokens).bin/sync-models.mjs—prov.models[baseId]plus the codex/gemini/openai/cloudflare.models[...]tables and the Antigravitygrouped[baseId]table (model ids from external catalogs/config).pkgs/id/web/src/world.ts— both records merges (Object.assignon a peer frame and on the host response) → define-semantics writes. Probe matrix landed as a test inworld-records.test.ts: peer frame with__proto__object value,__proto__string value,constructor,toString, ordinary key — own property present, JSON round-trip preserves,Object.prototypeuntouched (6/6 pass).(b) External-key — named follow-up (filed, per the design doc's open question: report a deep-merge helper, don't pre-decide its shape): #4957 —
deepMergeProviders(bin/provider-catalog-sync.mjs), the recursive merge over runtime-overlay config keys; assignment semantics at every depth.(c) Internal-only — named classes covering every remaining hit: destructuring declarations matched by G1's raw form (57, not writes); array/typed-array index writes and
[]-annotation/literal forms (receivers are arrays or index expressions — no string-key store); code-constructed tables (CLI option tables, stamp keys inrecord.mjsmissingStamps, backend name/port/health tables inbin/proxy-supervise.mjs,MODELS-keyedtargetStateinbin/design-code-proxy.mjs, effort-name variant tables inbin/sync-models.mjs, composite template keys that cannot spell__proto__exactly, e.g.weights[${member}/${modelKey}]); literal-sourceObject.assign(provider-catalogclassify({...})results,agy-proxyerror props); vendored/bundled assets (pkgs/identity/web/static/scripts.js, the cold-store-reaperdist/bundle); docs examples (pkgs/mcpx/docs/home-example— its??=namespace registry andObject.assignlog-attr sites are code-constructed names in example code).#2792 scope (read-side, listed not fixed)
bin/antigravity-direct.mjsref lookup (cur[seg]); theif (!prov.models[...])existence reads beside the fixed sync-models writes; dynamic lookups generally — #2792's phases own them.Contract statement
Landed in PR #4956:
pm-stack/aggregator/README.md(new "Store contract: define semantics (#2953)" section) and thebin/record.mjsheader — rule paragraph + probe matrix in both.Tests (laptop)
world-records 6/6 (incl. the new probe test) · provider-catalog-sync 35/35 · sync-models 23/23 · record 18/18 · antigravity-direct 16/16 ·
node --checkclean on all edited .mjs files. Codex review on PR #4956 could not run (usage limits) — no findings existed; disposition recorded on the PR.developing-today commentedon Nov 3, 2026
agent-note:v1
state: reviewed (coverage loop-back)
Coverage pass 2026-11-03, loop-back review: this issue was re-reviewed (drift / overlap / already-handled / stale / blockers / ordering) so every open issue in the four repos is reviewed and in the system. Verdict: still live; in the system as task 8541 (small_fix, queued, priority 50) in repo-health-code-pilot. Labels audited and synced. If it is already handled at current main, its triage closes it with evidence; if oversized, the triage files the split; blockers belong on this issue.
Found via: coverage loop-back 2026-11-03