Skip to content

refactor(move): collocation batch 1 — allocator contract into managed-allocation - #3287

Merged
thymikee merged 3 commits into
mainfrom
refactor/ws5-collocation-moves
Oct 7, 2026
Merged

thymikee merged 3 commits into
mainfrom
refactor/ws5-collocation-moves

Conversation

@thymikee

@thymikee thymikee commented Oct 7, 2026 •

Copy link
Copy Markdown
Member

Summary

Part of #3276 §5. Closes #3281.

  • Adds ADR 0033 (renumbered from 0032 this round: docs(adr): retain the current layering engine (ADR 0032) #3286 already claims 0032-layering-graph-engine.md). This PR's README change adds only the 0033 row; docs(adr): retain the current layering engine (ADR 0032) #3286 has since merged with the 0032 row, and the rebase keeps both rows side by side: a decision table with one row per candidate file in the umbrella's collocation list — move, merge, or keep with the direction that was checked and fails. Required behavior (a) of Architecture WS5: collocation decisions and first refactor(move) batch #3281.
  • Lands the batch-1 refactor(move): packages/contracts/src/managed-device-allocation.ts → packages/managed-allocation/src/managed-device-allocation.ts, new @agent-device/managed-allocation/managed-device-allocation subpath; contracts drops the old subpath. The port and its lease vocabulary had no importer outside managed-allocation and the daemon composition that already depends on it.
  • The other listed batch moves failed the mandated re-verification and the ADR rows are the record: the four capture-kit admission ledgers and durable-json.ts cannot move to managed-allocation because managed-allocation already depends on capture-kit (the move would invert an existing package edge), and the three limrun files have no seam — src/sdk/limrun.ts is the published agent-device/limrun facade entry, limrun-runtime-types.ts is a public-type refinement colliding with the package-internal names, and src/provider-limrun-runtime.ts self-builds the root's ADR-0019 dependency factory in its constructor.

33 files; the move itself is rename-only (git diff -M90% --summary shows the file at 98% similarity; the rest are one-line import re-points and docs). The ADR 0021 link edit is independent of the renumber (it points at the moved contract file, not an ADR number).

Validation

  • Head d4ac51874 (rebase onto origin/main after docs(adr): retain the current layering engine (ADR 0032) #3286/refactor(layering): rank every root module so R5 sees through (root) #3288 merged; conflict resolved keep-both in docs/adr/README.md, 0032 + 0033 rows side by side): pnpm check:affected --run exit 0, "all runnable checks passed"; check:layering green on the new spine (R80/R6 at the new merge-base).
  • Previous head 6701ab987 (ADR reconciliation with refactor(layering): rank every root module so R5 sees through (root) #3288/Architecture WS9: physical root-pass moves for daemon-diagnostics-scope, runtime-command-surface, runtime-factory #3294 after the design follow-up): pnpm check:affected --run exit 0, "all runnable checks passed".
  • Previous head 161b02234 (prose-only ADR intro rewording): pnpm check:affected --run exit 0, "all runnable checks passed".
  • Previous head d7239c323: pnpm check:affected --run exit 0, "all runnable checks passed" (59 selected checks; the single check:affected: lint failed. line in the log is check:affected:test's own envelope fixture, reproduced identically on every run at the same position — standalone pnpm lint exits 0).
  • Previous head 62200ec25 passed the same gate; this round changed only docs/adr/ files.
  • check:layering, check:agent-guidance, typecheck, format:check, focused vitest (managed-allocation package + daemon allocation + reachability + allocator-fake, 116 tests) green.
  • check:production-exports: identical finding count on origin/main and head (55), so no export-surface delta.
  • Declared-zone modularity re-measured with the umbrella's method on both trees: 0.3732 → 0.3745 (before-value reproduces the issue's 0.373; small improvement, not chased).

Docs-only ADR rows need no runtime evidence.

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Size Report

Metric Base Current Diff
Installed (including dependencies) 5.13 MB 5.13 MB -2.9 kB
Package (unpacked) 5.13 MB 5.13 MB -2.9 kB
Package (download) 1.54 MB 1.54 MB -984 B

Startup median (7 runs, lower is better):

Scenario Base Current Diff
CLI --version 19.3 ms 20.5 ms +1.2 ms
CLI --help 55.5 ms 57.1 ms +1.6 ms

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 33 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="docs/adr/0032-collocation-decision-table.md">

<violation number="1" location="docs/adr/0032-collocation-decision-table.md:28">
P3: The File column in the capture-kit table mixes path prefixes: the four admission-ledger rows write `capture-admission/audio-probe-admission-ledger.ts` (no `src/`), while the other four rows in the same table write `src/durable-json.ts` and `src/snapshot/...`. Every other zone's rows consistently use the `src/` prefix. Since this column is the table's key (one row per candidate), normalize the ledger rows to `src/capture-admission/...` (files live at `packages/capture-kit/src/capture-admission/`) so all eight rows resolve the same way.</violation>

<violation number="2" location="docs/adr/0032-collocation-decision-table.md:40">
P3: The contracts-section prologue says "every candidate below has dependents in two or more higher-ranked zones, so no single consumer zone can own it without inverting the spine (R5)" — but the `managed-device-allocation.ts` row directly below it is the counterexample: it was moved into managed-allocation precisely because that single consumer zone can own it without new edges (daemon already depends on the package). The universal wording contradicts the table's own outcome and muddies the R5 rationale for a reader checking why this one file moved. Scope the claim to the keep rows, or add the exception.</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

Comment thread docs/adr/0032-collocation-decision-table.md Outdated
Comment thread docs/adr/0032-collocation-decision-table.md Outdated
Comment thread docs/adr/0032-collocation-decision-table.md Outdated
@thymikee
thymikee force-pushed the refactor/ws5-collocation-moves branch from 62200ec to d7239c3 Compare October 7, 2026 15:16
@thymikee

thymikee commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

This PR is ready at d7239c3, and all 19 checks pass. The diff only touches type imports, the export maps and the ADR docs, so any export-resolution failure would have shown in the typecheck and layering jobs, which are green. There are no conflicts.

Not blocking: the intro sentence in docs/adr/0033-collocation-decision-table.md (https://github.com/callstack/agent-device/blob/d7239c3/docs/adr/0033-collocation-decision-table.md#L6) is hard to read and links ADR 0021 for no clear reason, so a rewrite without that link would help. The PR body also says the README lists 0032, but only the 0033 row was added, so there is a 0032 gap until #3286 merges. You can take or leave both.

I did not re-run check:affected, check:layering, check:production-exports or the modularity measurement, and I relied on CI and the PR-body numbers for those. I also did not check the R-number reasons on the keep rows (R13, R18, R78) against the layering model.

@thymikee thymikee added the ready-for-human Valid work that needs human implementation, judgment, or maintainer merge label Oct 7, 2026
@thymikee
thymikee force-pushed the refactor/ws5-collocation-moves branch from d7239c3 to 161b022 Compare October 7, 2026 16:39
@thymikee

thymikee commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

Closing the loop on the two non-blocking items — both accepted, pushed as a prose-only amend at 161b02234 (check:affected --run exit 0 on that head):

  1. ADR intro rewrite: accepted. The garbled "recorded in [ADR 0021]-style alignment notes" sentence is gone; the intro now ends at "Moves land as refactor(move) PRs; batch 1 is the companion PR to this decision." Per your parenthetical, the 0021 reference was kept only where a row needs it — the managed-device-allocation.ts move row now cites (ADR 0021 §3) inline.
  2. PR-body README wording: accepted. The Summary now states this PR adds only the 0033 README row and that the 0032 row arrives with docs(adr): retain the current layering engine (ADR 0032) #3286 (index gap until one merges, whichever lands second keeps both rows). No 0032 index row added here, as instructed.

@thymikee

thymikee commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

Design follow-up on 161b02234: the allocator-contract move is well scoped, and rejecting moves justified only by community membership is the right call. Two ADR details need reconciliation with the broader work:

  1. “Keep” should distinguish sound ownership from a mechanical-move constraint. The root platform-runtime rows cite R13/R76's exact paths as reasons to keep files. Those declarations describe today's placement; needing to update them does not itself prove the placement is best. Keep this PR's move-only scope, but describe such rows as “retain for this batch; relocation requires coordinated ownership changes.” Likewise, a package-cycle result rejects the proposed move, not every possible future design. No new refactor or issue per row is requested.
  2. The root-pass handoff currently doesn't match refactor(layering): rank every root module so R5 sees through (root) #3288. ADR 0033 marks daemon-diagnostics-scope.ts, runtime-command-surface.ts, and runtime-factory.ts as “move (root pass)”. At 5c90cdfcb, refactor(layering): rank every root module so R5 sees through (root) #3288 assigns logical zones but leaves these files in place. Please reconcile the rows and the existing issue checklist: either the physical moves remain outstanding, or record an explicit keep/reconsidered decision and its ownership rationale. Do not count reclassification as completed collocation.

The enduring rule should be ownership and reduced change coupling. Dependency-community scores identify candidates; current guard filenames are constraints to account for, not independent evidence that a location must stay forever.

@thymikee

thymikee commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

Both reconciliations landed at 6701ab987 (check:affected --run exit 0 on that head; docs-only delta, rebased onto origin/main):

  1. Path-keyed keeps reworded. The four platform-runtime-* root rows now read retain for this batch and say explicitly that R13/R76's path lists constrain a relocation rather than prove the placement. Same framing promoted to a "Rules at a glance" bullet, and the capture-kit cycle rows now say the proposed direction/sequence is rejected — a future design that first removes the load-bearing capture-kit import stays open ("this row refuses the sequence, not the destination"). The enduring rule is recorded at the ADR close: judge collocation by ownership / fewer independently maintained declarations per change; community scores identify candidates, guard filenames are constraints.
  2. Root-pass handoff reconciled with refactor(layering): rank every root module so R5 sees through (root) #3288 via Architecture WS9: physical root-pass moves for daemon-diagnostics-scope, runtime-command-surface, runtime-factory #3294. My previous push had gone the other way (keep/reconsidered citing the zone assignments) — corrected per your shared decision. The three rows are now move (outstanding, #3294), the (root) prologue states reclassification is not completed collocation, the Follow-ups section links #3294, and the Architecture WS5: collocation decisions and first refactor(move) batch #3281 checklist gained the unchecked item linking Architecture WS9: physical root-pass moves for daemon-diagnostics-scope, runtime-command-surface, runtime-factory #3294. Note for the Architecture WS9: physical root-pass moves for daemon-diagnostics-scope, runtime-command-surface, runtime-factory #3294 owner recorded in the rows: daemon-diagnostics-scope.ts's importers include daemon-registration-owner.ts (static, line 25), which refactor(layering): rank every root module so R5 sees through (root) #3288 classifies as daemon-contracts, and runtime-command-surface.ts/runtime-factory.ts are statically imported by src/runtime.ts (command-runtime) — the physical destination has to respect R5 against those lowest-ranked importers, which is presumably why the moves are their own workstream.

…ed-allocation

The port and its lease vocabulary had no importer outside managed-allocation
and the daemon composition that already depends on that package, so the
types now live beside the allocation operations that implement them. The
package gains an @agent-device/managed-allocation/managed-device-allocation
subpath and contracts drops the old one; consumers re-point to the new
specifier.
One row per file in #3276 section 5: move, merge, or keep with the
checked direction that fails. Batch 1 moves only the managed-device
allocator contract into managed-allocation; the limrun files have no
seam and the capture-kit ledger moves would invert an existing package
edge. ADR 0021's contract link follows the moved file.
@thymikee
thymikee force-pushed the refactor/ws5-collocation-moves branch from 6701ab9 to d4ac518 Compare October 7, 2026 18:25
@thymikee

thymikee commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

The code in 6701ab9 looks good. The move diff is identical to the head I reviewed earlier (d7239c3), so my earlier clean result still holds. Both ADR wording fixes from that round are now in place. All 19 checks pass, and there are no conflicts. I did not re-run the layering or check gates locally, and I did not re-read the full move diff, so this relies on the CI results and the identical diff. Of the three cubic-dev-ai threads, the ADR line 144 thread (#3287 (comment)) and the capture-admission path prefix thread (#3287 (comment)) are fixed at this head, so you can resolve them. The Contracts prologue wording thread (#3287 (comment)) does not apply, since the meaning is unchanged and it is docs-only, so you can resolve it too. Nothing else stands in the way of merging.

Since then the branch was rebased to d4ac518. The range-diff shows the same commits, with only the ADR index context changed after ADR 0032 merged, so this result should carry over once CI finishes there.

@thymikee
thymikee merged commit 4565606 into main Oct 7, 2026
19 checks passed
@thymikee
thymikee deleted the refactor/ws5-collocation-moves branch October 7, 2026 18:48
@github-actions

github-actions Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1
Preview removed because the pull request was closed.
2026-10-07 18:48 UTC

thymikee added a commit that referenced this pull request Oct 17, 2026
The base text says the row and Batch 1 record a move that landed in #3287 and
that the package removal then deleted. The rewrite dropped that the move landed.

#3731 (comment)
thymikee added a commit that referenced this pull request Oct 17, 2026
…oved

The row is history: the move landed in #3287, and the package removal on
2026-10-10 deleted the file. State this in the row, as the Status note does,
so the row does not read as a live move target.

#3731 (comment)
thymikee added a commit that referenced this pull request Oct 17, 2026
The base text says the row and Batch 1 record a move that landed in #3287 and
that the package removal then deleted. The rewrite dropped that the move landed.

#3731 (comment)
thymikee added a commit that referenced this pull request Oct 17, 2026
…oved

The row is history: the move landed in #3287, and the package removal on
2026-10-10 deleted the file. State this in the row, as the Status note does,
so the row does not read as a live move target.

#3731 (comment)
thymikee added a commit that referenced this pull request Oct 18, 2026
* docs(adr): delete completed ADR 0019 checkpoint history

* docs(adr): write ADR 0019 in ASD-STE100

* docs(adr): write ADR 0021 in ASD-STE100

* docs(adr): delete retired ADR 0022 classification procedure

* docs(adr): write ADR 0022 in ASD-STE100

* docs(adr): delete completed ADR 0023 revision history

* docs(adr): write ADR 0023 in ASD-STE100

* docs(adr): delete superseded ADR 0025 Device Hub process

* docs(adr): write ADR 0025 in ASD-STE100

* docs(adr): write ADR 0026 in ASD-STE100

* docs(adr): write ADR 0027 in ASD-STE100

* docs(adr): write ADR 0029 in ASD-STE100

* docs(adr): write ADR 0030 in ASD-STE100

* docs(adr): write ADR 0031 in ASD-STE100

* docs(adr): write ADR 0032 in ASD-STE100

* docs(adr): delete completed ADR 0033 move batches

* docs(adr): write ADR 0033 in ASD-STE100

* docs(adr): delete completed ADR 0019 substrate adoption instructions

* docs(adr): restore the ADR 0019 move-unit size rule

The deletion of the completed checkpoint history (667484c) also removed the
operative size rule of section 8. The language commit re-added only one
sentence of it. Restore the full rule: the original-baseline and stack-base
bounds, the zero-or-negative expected delta, the root-versus-package byte
report, the named justification of each addition, type inflation as size
growth, and the #1739 evidence home.

* docs(adr): restore the frozen meaning in ADR 0021

Restore "replaced" in Status and the "ADR text before 2026-10-10"
recovery pointer. Restore the leased-device scope of remote access, the
"is the device leased" check, the Simlock owner of the HTTP API, and the
"address a device" requirement. Keep the base sentence about the adb
server, because its "which" referent is ambiguous.

* docs(adr): restore the frozen meaning in ADR 0022

Rewrite the R75 glance rule as the membership ratchet that the gate
enforces. Name the whole root platform-runtime family, which includes
src/platform-runtime.ts. Restore the querySelector CONDITIONAL attribution,
the separate landed child issues, "leaked", the generic hook bag
prohibition, the kill criterion, the request-spine guards, the owning seam,
and "fold"/"collapse" as two separate words.

* docs(adr): restore the frozen meaning in ADR 0023

Restore the comparability sentence for the counting definition, the
collapse and fold vocabulary of the ≤14 section, the decision (not the
wrappers) as the thing outside this route's ownership, the seam and kept-depth
terms, the wiring rows, "multiple" calls, the capture as the ineligible
subject, and adapter examples as examples. Revert the generalized 38/29
sentence to the base text; its stale "higher" claim is a discrepancy for the
PR body, not a language fix.

* docs(adr): restore the frozen meaning in ADR 0025

Restore the accepted gap that the hinge stream never ran on a physical
device, which the Device Hub deletion removed. Restore the glance rows for
an unsettled hinge, the refusal of any pose that never agrees, and the
panel-power-only pose report. Restore "only when neither window resolves",
the two facts of the ADR in the Android amendment, the 27.1 toolchain check,
the former half-open rule, the unverified refusal, and the dangling
private-API pointer.

* docs(adr): restore the frozen meaning in ADR 0026

Restore that a weak signal reaches only the scroll-band site and that
directional hints are its outlet only when nothing is the indicator's
parent. Restore "characterize each site before you reshape any of them",
the subject and "only" of the frame-change glance row, examples as
examples, the refuted alternatives as hypotheticals, and the pinned scroll
host as the test subject.

* docs(adr): restore the frozen meaning in ADR 0027

Restore "exactly when it is a split" as "if and only if", the glance rule
that the tolerance guarantees only flat weight over a preserved base
closure, and the code-quoted terms "wiring lines", "loading-shape probe",
"loading property", and "façade exactness". Restore "two or more shared"
statements, "exactly these facts", the like-for-like replacement scope, and
the refuted alternatives as hypotheticals.

* docs(adr): restore the frozen meaning in ADR 0029

Restore "the only exception" for the capability gate, the examples of
protocol plumbing as examples, the remote agent and the simulator as the
referents in Context, the three enforcement "points" and the backstop
rule, the client reuse of a daemon, "every" earlier admission decision,
and the per-daemon floor.

* docs(adr): restore the frozen meaning in ADR 0030

Restore that daemon registration keeps the same daemon.lock path and
refuses legacy files instead of reclaiming them. Make the separate state
directory conditional on the failure to stop every user again. Restore
"after that bound", "guard path", the scope "those paths" for the legacy
ban, the guard's paths, the unexpanded support contract, and "any retained"
guard. Keep the base "its directory guard": its referent is ambiguous.

* docs(adr): restore the frozen meaning in ADR 0031

Restore the code term "helper-routed" and "exactly", the passive
member-by-member assembly, the 48-level limit as a maximum, the runner as
the actor that moves the shared pointer, and "dropped" as the one word for
lost events.

* docs(adr): restore the frozen meaning in ADR 0032

Remove the added "only" from the fallow revisit rule. Make "replaceable"
describe the model implementation again. Restore the code term "lazy
seams", the parseImports miss as the gap, "misses none of these edges",
"with either engine", and "does not include" for tsconfig.

* docs(adr): restore the frozen meaning in ADR 0033

Restore "seam" wherever the base used it; "boundary" stays only where the
base used it. Restore that contracts holds wire vocabulary under R18, that
exports", path-keyed rules as examples of a class, the rejected proposal as
a hypothetical, and "the next pass re-opens it".

Keep the Follow-ups deletion: #3281 and #3294 are closed and every listed
move landed, so the suggested "moves continue under #3294" would be wrong.

* docs(adr): restore the frozen meaning in ADR 0019

Restore the shape rule in section 2 as a plain statement in force,
including the timing "at the point the shape is requested"; #2808, #2806,
and the web runtime tests already rely on it. The Status line keeps its
"proposed" wording, so the conflict stays visible.

Restore the operative half of the deleted section 6 substrate paragraph:
no duplication or package-to-root back-import of shared Apple-runner or
Android-helper mechanics, the injected-capability path, and one execution
owner. Repoint the dangling substrate references in sections 6, 10, and the
ADR 0009 relationship.

Restore the Status outcome of the adoption checkpoint, the kernel helper
scope, the only static value-import sites, the owning provider, owner cell,
freezes, the time-bound await using ban, the trust choke point, "seam" as
the code term, the conditional scope of the preferred/required rule, the
loading shape, the "yet" qualifiers of the End state, and the declared
host-port adapter.

* docs(adr): restore three conditions dropped by sentence splits

- ADR 0025: emit apple_display_primary_geometry_conflict only when the
  primary panel is also the largest.
- ADR 0025: keep the pre-panel normalization only when the runner reports
  no panel metadata.
- ADR 0032: the revisit trigger is an engine that can supply the shared import
  model, not one that already supplies it.

Found in review round 2.

* docs(adr): keep translation hops in the ADR 0022 route-depth rule

The base decision applies the deletion test to pass-through and translation hops
and endorses only the proven removable hop. The glance named only pass-through
hops. Restore the selector "seam" term from the base rationale.

#3731 (comment)

* docs(adr): restore that the ADR 0033 managed-allocation move landed

The base text says the row and Batch 1 record a move that landed in #3287 and
that the package removal then deleted. The rewrite dropped that the move landed.

#3731 (comment)

* docs(adr): restore the ADR 0025 rule that the fold press is not evidence

The Device Hub deletion also removed the base sentence that fold sets the pose
and that only the read-back is evidence. Point to the HID amendment that
replaced the Device Hub press.

#3731 (comment)

* docs(adr): state the ADR 0022 route-depth rule with its base scope

Name pass-through and translation hops in one rule, as the base deletion test
does, and drop the commit hash that the base does not attach to the verdict.

#3731 (comment)

* docs(adr): cite R76's path-family ban in ADR 0033

ADR 0022 records that #3430 emptied the R76 inventory and reduced R76 to a
plain ban on the src/platform-runtime-*.ts family. The ban still keys on these
paths, so the retain-for-this-batch rationale holds; only the noun was stale.

#3731 (comment)

* docs(adr): mark the ADR 0033 managed-allocation row as landed and removed

The row is history: the move landed in #3287, and the package removal on
2026-10-10 deleted the file. State this in the row, as the Status note does,
so the row does not read as a live move target.

#3731 (comment)

* docs(adr): restore scope words in ADR 0033 rows and prose

Restore base scope dropped in the rewrite: "design, not a move" for the limrun
rows, the shared reason and "all" for snapshot-freshness, the fingerprint and
policy-file links, the real-seam conditions, "every edge" and "at all" for
client imports, "the platform package's", the capture-kit back-edge, R11's
"from a non-test file", and the daemon entry's re-export scope.

* docs(adr): restore scope words and a fixture ban in ADR 0019

Restore "provider" and "concrete" in the bindDevice glance, the conditional
parity evidence that explains why, "touches" for the SessionState unit, "not
pass-through layers" for the declared boundaries, and "grab bag". Restore the
operative ban that temporary fixtures never authorize a production bridge,
duplicate route, or package back-import; the section 7 deletion removed it.

* docs(adr): restore scope words found by the 12-ADR drift pass

ADR 0021: restore the two "so" consequences. ADR 0023: name `isEligible` as
the fallback condition, and describe the adb-host binding instead of a
permission. ADR 0025: limit "never promoted to a verified pose" to the
`screen` evidence. ADR 0026: name the ledger as the shape to extend, not an
order. ADR 0027: restore "carry no code", "new code", and "all". ADR 0029:
restore the "HTTP edge" term. ADR 0032: restore "only", "one more", the
"and" between edge kinds, and the "because" link.

* docs(adr): restore ADR 0022 wording dropped by the rewrite

Found by the second meaning-drift pass against base 59fdf00.

* docs(adr): restore ADR 0023 wording dropped by the rewrite

Found by the second meaning-drift pass against base 59fdf00.

* docs(adr): restore ADR 0031 wording dropped by the rewrite

Found by the second meaning-drift pass against base 59fdf00.

* docs(adr): restore ADR 0032 wording dropped by the rewrite

Found by the second meaning-drift pass against base 59fdf00.

* docs(adr): restore ADR 0033 wording dropped by the rewrite

Found by the second meaning-drift pass against base 59fdf00.

* docs(adr): restore ADR 0025 wording dropped by the rewrite

Found by the second meaning-drift pass against base 59fdf00.

* docs(adr): restore ADR 0026 wording dropped by the rewrite

Found by the second meaning-drift pass against base 59fdf00.

* docs(adr): restore ADR 0027 wording dropped by the rewrite

Found by the second meaning-drift pass against base 59fdf00.

* docs(adr): restore ADR 0019 wording dropped by the rewrite

Found by the second meaning-drift pass against base 59fdf00. Also repair the
review instruction that pointed at the deleted substrate paragraph.

* docs(adr): restore the ADR 0021 claim guard wording

Base: "device claims still guard against two sessions ... driving the same device".
"prevent" claimed a stronger guarantee.

* docs(adr): scope the ADR 0025 defensible-source claim to the recorded poses

Base: "Poses came from the hinge read-back, not from the pose that was requested;
the amendment above is why that is the only defensible source".

#3731 (comment)
thymikee added a commit that referenced this pull request Oct 18, 2026
Item 13. ADR 0021 section 3 now states consequences, including deletion of managed-allocation. Section 4 records the withdrawn allocator design and its ownership. 4565606 (#3287) is the historical collocation move; retain the historical row and point its rationale to section 4.
thymikee added a commit that referenced this pull request Oct 18, 2026
Item 13. ADR 0021 section 3 now states consequences, including deletion of managed-allocation. Section 4 records the withdrawn allocator design and its ownership. 4565606 (#3287) is the historical collocation move; retain the historical row and point its rationale to section 4.
thymikee added a commit that referenced this pull request Oct 18, 2026
* docs(adr): identify the derived daemon registry owners

Item A. packages/command-registry/src/registry.ts declares the separately typed daemon facet; daemon-command-descriptor.ts owns DaemonCommandDescriptor. packages/daemon/src/core/daemon-command-registry.ts derives the table and exposes predicates. Its tests pin policy and routes.

4648051 (#906) introduced the dormant descriptor and parity tests. 47abc8c (#907) activated derivation and deleted the hand table. This corrects the brief attribution to #906 alone.

Known invariant-3 gap: types.ts CommandDescriptorBase exposes daemon?: DaemonCommandTraits, and src/cli/command-explain.ts describeCommandDaemon reads and publishes route/traits. Preserve the invariant and report the gap; do not change behavior.

* docs(adr): match guarantee declarations and fixture consumers

Items 1 and 2. packages/contracts/src/interaction-guarantees.ts declares 14 guarantees, including keyboardOcclusion, parentOwnedTouchPoint, settleObservation, resolutionDisclosure, outcomeObservation, and targetStability. Match the complete list. rg finds only the TypeScript snapshot-visibility-tap-point-policy.test.ts and RunnerTests+TapPointPolicyTests.swift reading tap-point-policy.json; the matrix parityTable is metadata. No fake runner reads it. Keep migration step 3 open.

* docs(adr): correct the default lease inactivity period

Item 3. packages/daemon/src/resources/lease-registry-scope.ts DEFAULT_LEASE_TTL_MS = 60_000; normalizeLeaseTtlMs uses it when no positive TTL is supplied. The admitted-work section already states one minute.

* docs(adr): record the active settle timing detector

Item 4. gh issue view 1299 reports CLOSED, closedAt 2026-07-21T08:54:50Z. packages/maestro/test/conformance/differential/scenarios.ts settle-after-tap has no knownDivergence and requires settleLatches >= 1 and settleTimeouts <= 0. invariants.test.ts exercises synthetic traces. This is repository evidence, not a new live-device result.

* docs(adr): include recording consumers of the gesture codec

Item 5. a13a683 (#1567) added target-authored drag. packages/daemon/src/execution/interaction/internal/interaction-gesture.ts calls gesturePayloadToPositionals; packages/daemon/src/core/session-script-writer.ts calls dragGesturePayloadFromPositionals. PUBLIC_GESTURE_SYNTAX still defines arity for the two parsers.

* docs(adr): record retired aliases and current client result gaps

Items A and 6. 47abc8c (#907) activated the derived daemon table after parity in 4648051 (#906). Mark the hand-table inventory as pre-migration context. 189b062 (#960) moved client-types.ts into client/. 494eb52 (#1877) removed read. gh issue view 1153 reports CLOSED, closedAt 2026-07-08T16:35:29Z, but src/client/client-types.ts alert and reactNative still return CommandRequestResult. Do not infer total narrowing from closure.

* docs(adr): exclude bridge preparation from the generation circuit

Item 7. packages/platform-apple/src/snapshot-route.ts opensGenerationCircuit excludes failure.kind === preparing and WINDOW_COORDINATE_SPACE_UNRESOLVED. snapshot-route.test.ts pins that bridge preparation sends only the current capture to XCTest. Keep glance and body consistent.

* docs(adr): replace deleted migration references in code

Item 8. ADR 0011 Layer 2 and ADR 0014 Mutation admission and read behavior / Command effects are daemon-owned and completely classified replace removed phase, step, and escape-hatch references. Change comments and one test name only.

R56 evidence: c77bc40 (#2021) deleted the legacy src/core/dispatch.ts app-switcher arm and dispatch facet. The current descriptor retains daemon.route generic, but platformExecution is device-runtime; generic-runtime-execution.ts routes system buttons through system-button-runtime.ts, whose app-switcher row uses appSwitcherRuntimeUse. Retained generic routing is intentional, not evidence of a surviving legacy leaf or runtime bug. Clarify that distinction.

* docs(adr): identify the current generic-dispatch rejection boundary

Item 9. c77bc40 (#2021) retired src/core/dispatch.ts and dispatchKnownCommand. packages/daemon/src/server/request-router.ts calls resolveGenericRuntimeExecution before dispatchGenericCommand. packages/daemon/src/execution/generic-runtime-execution.ts rejects its default with COMMAND_FAILED / generic-route-runtime-missing. Its __tests__/generic-route-runtime-completeness.test.ts pins unknown-command rejection. No dispatch-keyboard.test.ts exists. Keep the proposed fragment INVALID_ARGS contract conditional and identify the absent format-specific proof rather than claim this routing-gap test proves it.

* docs(adr): remove the dangling historical hard-reject pointer

Item 10. git log -S hard-reject identifies 66fe801 (#1177), which held the rejection rationale in Consequences, not Alternatives. The later structural-equivalence amendment superseded geometric mutation selection; 36957e8 rewrote the retained consequence. Remove only the dangling pointer in historical acceptance evidence. Do not restore an obsolete current selection rule.

* docs(adr): align the proposed durable-resource amendment

Item 11. ADR 0019 section 5 proposed amendment already requires native-path disposition, retention by fence generation until both facts settle, and a failed-finish test for each kind before its cleanup changes. ADR 0024 sections 2.4 and 2.5 already retain archived generations; glance rule 6 already has the per-kind test gate. Match section 2.7 to these constraints. Both ADRs remain Proposed for this amendment.

* docs(adr): point exhaustive runtime facts to section 2

Item 12. ADR 0019 section 2 Runtime use joins facts and narrows the bound runtime contains the exhaustive per-device-shape fact rule. Section 3 owns provider resolution. Change the citation only.

* docs(adr): cite the withdrawn allocator design for its historical move

Item 13. ADR 0021 section 3 now states consequences, including deletion of managed-allocation. Section 4 records the withdrawn allocator design and its ownership. 4565606 (#3287) is the historical collocation move; retain the historical row and point its rationale to section 4.

* docs(adr): record the coupling ban and its landing date

Item 14. 1612e33 (#3431) and b9005d8 (#3430) both landed on 2026-10-12. The latter removed the remaining selector coupling and replaced R76 classification machinery with a ban. Status now matches Decision and enforcement; do not claim a current classification inventory.

* docs(adr): record the active shape rule and shared test owner

Items 15 and 16. Root src/__tests__/install-source.test.ts exercises shared provision-kit behavior and family adapters; cli-install-from-source.test.ts exercises the CLI boundary. Add the missing body owner matching the existing glance. efd2108 (#2808) added the no-fact-cell rule; 746e9b3 (#2806) enforces shape refusal at the web owner, pinned by packages/platform-web/src/runtime.test.ts. Mark the rule in force and correct its section pointer to section 2. Item 11: the section 5 proposed amendment is already correct and remains unchanged.

* docs(adr): correct the direction of the superseded hop comparison

Item 17. The ADR trace counts 41 distinct files for press/Android and 30 shared plus 17 AX / 19 runner for snapshot/iOS (47/49). Both exceed the superseded 38/29. The facade PRs predate e624ef9, so they cannot explain the difference; the old count is not higher.

* docs(adr): date hinge-stream evidence by toolchain

Item 18. 057dfb7 (2026-09-20) recorded the initial toolchain examination; e8da1e1 (2026-09-21, #2717) and 6cb160a (#2734) recorded a working stream. 590f171 (2026-10-14, #3587) records no motion subcommand in devicectl 651.13.5 / Xcode 27.1 build 27A9275, then called RC, and adds dispatched-unverified refusal. Read-only host check on 2026-10-16: xcodebuild -version reports Xcode 27.1, 27A9275; devicectl --version reports 651.13.5; device help lists no motion subcommand. Preserve dated successes without claiming every 27.1 build supports the stream. Sync the glance to existing no-sample behavior. No device state changed.

* docs(adr): describe the permitted capture-only second bind

Item 19. ADR 0019 section 9 permits one second bind for --settle when the action use has no capture, after facts admission. The second bind is capture-only; captureSnapshot in the action use reuses the cached binding. Correct the fixture comment only.

* docs(adr): date the completed root-pass move correction

Item 20. gh issue view 3294: CLOSED 2026-10-08T07:57:29Z. gh issue view 3281: CLOSED 2026-10-07T18:48:47Z. 8c5bce0 (#3297) moved daemon diagnostics to src/daemon-contracts; 75b414a (#3299) moved the assembly pair into src/command-runtime. Current owners are packages/daemon-contracts/src/daemon-diagnostics-scope.ts and src/command-runtime/{runtime-command-surface,runtime-factory}.ts. Add a 2026-10-16 correction to the dated observation without declaring every root move complete.

* docs(adr): record daemon trait enforcement gaps

M1. Registry tests pin the derived table; types do not fully enforce invariants 3 and 4. Keep both invariants required and synchronize Rules at a glance.

Evidence: packages/command-registry/src/types.ts:213 makes daemon optional. DaemonCommandDescriptor requires command and route but makes the other traits optional. packages/daemon/src/core/daemon-command-registry.ts:34-35 defaults missing descriptors to generic. src/cli/command-explain.ts:205-210 reads daemon traits in the public CLI projection. Registry policy pins are in packages/daemon/src/core/__tests__/daemon-command-registry.test.ts.

Maintainer follow-up: determine how types should enforce invariant 4 without weakening the accepted declaration boundary.

* docs(adr): describe pending bridge preparation precisely

L6. Describe a bridge preparation that is still running. Do not invent a preparation queue.

Evidence: packages/platform-apple/src/snapshot-source/preparation.ts:119-123 reports bridge-preparation-pending through attempts.value. packages/platform-apple/src/snapshot-route.ts:314-315 excludes preparing failures from the generation circuit. The existing glance exception already agrees.

* docs(adr): restore client result migration prerequisites

M2, L1, L2. Restore the contract-move prerequisite and its reason. State the full extent of broad client results. Retain the historical client path and restore prerequisite wording without the unrelated ADR 0010 pointer. Synchronize the client-contract rule in Rules at a glance.

Evidence: src/client/client-types.ts has 21 Promise<CommandRequestResult> methods, including alert, reactNative, and interactions.swipe. packages/command-registry/src/command-result.ts:41-47 documents dynamic payload exclusions; its result map remains nonexhaustive. packages/daemon/src/execution/interaction/internal/interaction-gesture.ts:59-74 retains local result types and Record payloads. Git commit 189b062 (#960) moved src/client-types.ts into src/client/. gh issue view 1153 confirms CLOSED at 2026-07-08T16:35:29Z.

* docs(adr): restore the retained rejection rationale pointer

L7. Repoint the historical hard-reject rationale to Consequences instead of deleting the useful pointer or restoring an obsolete alternative.

Evidence: git log -S hard-reject identifies 66fe801 (#1177), 36957e8, and 9362026. The current Consequences paragraph at line 1356 retains the reason blanket rejection is unsuitable: RN row/button/text wrapper chains. The structural-equivalence amendment remains authoritative.

* docs(adr): include replay and publication gesture codec callers

L3. Add the two omitted consumers of the positional drag codec.

Evidence: packages/replay-port/src/daemon-port/target-token.ts:13 calls dragGesturePayloadFromPositionals to select a source or destination target. packages/daemon/src/core/session-script-active-publication.ts:129 calls it through readRecordedDrag; assertPortableDragBindings at lines 102-123 validates portable endpoints and recorded target evidence before publication. No syntax or migration rule changes.

* docs(adr): trace old-reader guard failures without a codec promise

M3. Keep failure before platform execution as the proposed safety property. Record the session-dependent guard-request errors and the unresolved INVALID_ARGS requirement. A future codec cannot change an old reader. Keep Rules at a glance and both body descriptions aligned.

Evidence path: packages/ad-script/src/internal/script.ts:270-283,483 accepts an unknown command as an action. packages/ad-replay/src/internal/verify-dispatch.ts:65,280-287 dispatches the unannotated action. packages/replay-port/src/daemon-port/session-replay-runtime-engine-adapter.ts:221-237 calls invokeReplayAction. session-replay-action-runtime.ts:171,199 preserves the command. packages/daemon/src/server/request-router.ts:407,658-662 returns unknown replay actions to the full request path because core/daemon-command-registry.ts:58-59 has no replayScopedAction trait for them.

After admission, request-router.ts:346,393 reaches sessions/request-handler-chain.ts:127 and core/daemon-command-registry.ts:34-35. The unknown command routes to generic; the handler at request-handler-chain.ts:110-112 returns null. request-router.ts:596-598 returns noActiveSessionError with no session; packages/kernel/src/contracts.ts:263-264 sets SESSION_NOT_FOUND. With a session, request-router.ts:602-617 reaches execution/generic-runtime-execution.ts:116-123, which returns COMMAND_FAILED / generic-route-runtime-missing before dispatchGenericCommand at request-router.ts:619-620.

The replay adapter wraps the failure through session-replay-runtime-engine-adapter.ts:295-303,384-398 and session-replay-runtime-failure.ts:106. session-replay-runtime-failure-response.ts:108 emits REPLAY_DIVERGENCE. packages/ad-replay/src/internal/step-loop.ts:178-185 stops the loop before later open or include actions. These are the current paths after admission, not universal error guarantees for every historical release. The existing generic-route completeness test proves only the resolver branch.

Maintainer question: accept the existing old-reader errors, or keep INVALID_ARGS as an unresolved requirement?

* docs(adr): scope hop counts to their recorded trace

L9. Attribute 41 and 47/49 to this trace, without claiming that they are current repository counts.

Evidence: the Counting definition names commit 27a97ee and the retained trace tables measure press/Android and the two snapshot/iOS arms. Only the attribution changes; the counts and scope remain unchanged.

* docs(adr): retain the outstanding physical module moves

L4. Retain the dated corrections for completed moves and explicitly state that other physical moves remain outstanding as of 2026-10-16.

Evidence: scripts/layering/root-module-zones.ts:9-14 states that logical classification is not physical collocation and that the table should shrink. Its core, command-runtime, and platform-runtime entries still name root src/*.ts modules. No layering rule or completed-move claim changes.

* docs(adr): qualify the capture-only second bind

L5. Add the missing condition to the fixture comment: the settle observation may acquire a second capture-only bind only when the action use has no capture.

Evidence: docs/adr/0019-request-bound-platform-runtime.md:762-768 permits that second bind and requires reuse when the action already requires captureSnapshot. This commit changes only the comment.

Validation: pnpm format passed. All five fixture consumer suites and generic-route-runtime-completeness.test.ts passed: 6 files, 58 tests.

* docs(adr): state that the ADR 0020 old-reader trace starts after admission

Admission can resolve a device for lock and provider selection
(request-binding.ts, request-platform-provider-context.ts). It only reads the
inventory, so the safety property holds, but the trace does not cover
admission-time failures. Found in review round 2.

* docs(adr): align ADR 0003 invariants 3 and 4 with the shipped derivation

The 2026-06 update required types to stop every public projection from
reading daemon traits and a compile error for a missing trait. The shipped
derivation (#906, #907) does neither: the daemon facet is optional, a command
without one gets the generic route, and command explain displays the facet.

Invariant 3 now bans public contracts (CLI grammar, Node options, MCP schemas,
help, capability support) that derive from daemon traits, and allows a
diagnostic display. Only command-explain.ts and the daemon's own policy file
(daemon-policy-file.ts) read the facet. Invariant 4 now requires one daemon
facet per command and no second table. Decided with the maintainer.

* docs(adr): accept existing old-reader errors in ADR 0020

An old reader cannot learn a new error from a later codec. The traced path
already fails before platform execution with SESSION_NOT_FOUND or
COMMAND_FAILED (generic-route-runtime-missing), wrapped as REPLAY_DIVERGENCE.
The proposal now accepts these errors for old readers and keeps INVALID_ARGS
for readers that ship with the fragment codec. Decided with the maintainer.

* docs(adr): list the full provider-scenario exclusion buckets in ADR 0001

* docs(adr): scope the Android helper rule to instrumentation touch in ADR 0002

* docs(adr): record the exempt commands and grown allowlist in ADR 0005

* docs(adr): state per-fate wire-gate outcomes in ADR 0006

* docs(adr): name the platformExecution facet and execute seam in ADR 0008

* docs(adr): point the visionOS discovery claim at its test file in ADR 0009

* docs(adr): state the remote logPathUnavailable case in ADR 0010

* docs(adr): correct the scroll keyboard-probe condition in ADR 0011

* docs(adr): scope the linear-schedule sentence to endpoint-hold in ADR 0013

* docs(adr): name the frame value module and empty-result rule in ADR 0014

* docs(adr): add the we-are-lenient outcome to ADR 0015

* docs(adr): state the session event hides fill text in ADR 0017

* docs(adr): include translation hops in the collapse rule of ADR 0022

* docs(adr): separate the runner capture path and complete refusal causes in ADR 0025

* docs(adr): scope the novelty fact to verbatim transplants in ADR 0027

* docs(adr): correct the freshness row and cycle wording in ADR 0033

* docs(adr): state the platformExecution execution shapes in ADR 0008

platformExecution is a discriminated union of none, host, inventory, and
device-runtime (packages/contracts/src/command-platform-execution.ts). The
active design claimed it always names a runtime use; only the device-runtime
variants do. Describe the shape and qualify the bound runtime use to those
variants.

Fixes #3796 review thread discussion_r4306650944.

* docs(adr): match the active design to platformExecution in ADR 0009

The active design still said it composes with ADR 0008's descriptor capability
facet. That facet is retired; the per-OS predicates live in request-bound
runtime facts (packages/platform-apple/src/gesture-facts.ts and siblings).
Match ADR 0008's platformExecution declaration. Dated history and the
retirement notes keep their wording.

Fixes #3796 review thread discussion_r4306650938.

* docs(adr): scope the diagnostic fields to the request scope in ADR 0010

Malformed RPC method params throw in packages/daemon/src/server/http/http-rpc-methods.ts
before the router opens the request diagnostics scope (request-router.ts
handleRequestOnLedger), so http-server.ts answers with normalizeError output
that carries neither diagnosticId nor logPath; the validation tests pin that
400 / -32602 envelope. Scope the flush and field guarantee to errors inside a
request diagnostics scope and state that pre-scope failures omit the fields.
The remote logPathUnavailable rule is unchanged.

Fixes #3796 review thread discussion_r4306650954.

* docs(adr): confine frame construction claims to the slot class in ADR 0014

ref-frame.ts calls issuedRefFrame (ref-frame.ts activateRefFrame) and derives
expiry through expiredRefFrame, both exported factories of ref-frame-slot.ts.
The original sentence claimed no module outside the slot file can construct or
derive a frame value. Confine the claim to the private class, its private
fields, and direct construction; state the exported factory APIs and keep
transitions and admission owned by ref-frame.ts. The slot-file comment carried
the same overstatement and is corrected at the same scope.

Fixes #3796 review thread discussion_r4306650966.

* docs(core): state the pinned-generation warning exception in ref-frame.ts

resolveRefStalenessWarning (execution/session-snapshot.ts) warns on an active
frame when a pinned ref's generation differs from the frame epoch; the
existing test covers all three branches (expired any-ref, active plain/matching
pin clean, active mismatched pin warns). The header comment claimed an active
frame never warns. State the exact behavior.

Fixes #3796 review thread discussion_r4306650958.

* docs(adr): qualify the runner fallback policy and record the panel refusal in ADR 0025

shouldFallbackToRunner gates the runner path in
packages/platform-apple/src/core/screenshot.ts: a failure the policy rejects
rethrows before any runner capture. The glance row implied the runner follows
every simctl failure. State the policy condition. The app-window display facts
are unchanged.

#3761 merged into main as feca8cb (2026-10-18). When neither the sole lit
panel nor CoreDevice's primary panel identifies a panel,
resolveAppleCaptureTarget now refuses with COMMAND_FAILED and
details.reason capture-panel-unidentified (display-inventory.ts); array order
is never used. Update the Capture target body and add the glance row. The
former deferred claim is removed.

Fixes #3796 review thread discussion_r4306650971.

* docs(registry): separate app-switcher admission from execution

admitRuntimeOperations (packages/daemon/src/core/runtime-admission.ts) performs
the side-effect-free facts inspection of the owner's appSwitcher fact and only
then hands back the binding gateway; execution
(packages/daemon/src/execution/system-button-runtime.ts) uses the bound
operation. The comment implied admission itself uses the bound operation.
State the two stages separately.

Fixes #3796 review thread discussion_r4306650973.

* test(help): pin the foldable first-screen rule to the merged #3761 contract

The gate asserted the pre-#3761 help literal, so the merged pair (#3788 test,
#3761 help owner) fails only in combination on main. Replace the stale rule
with the current full contract line, including the capture-panel-unidentified
refusal. The help text itself is unchanged; the assertion now matches the
rendered first screen.

CI evidence: Coverage job 117649571201 at 73d562b fails this assertion on
unchanged-base integration; it is not caused by this PR's edits and not a
flake.

* docs(adr): state the attempted flush and field conditions in ADR 0010

withDiagnosticsScope (packages/host-kit/src/internal/diagnostics.ts) runs no
finalizer. Only finalizeThrownRequestError (request-router.ts) flushes, and it
is reached by thrown errors alone: the token refusal in runRequestWithinScope
is a returned normalizeError output without context, and
flushDiagnosticsToSessionFile returns no record for zero events or a write
failure, so an in-scope thrown error can still omit logPath. State that a
thrown request error attempts one forced flush, diagnosticId requires an
active scope, logPath appears only when the flush produces a file, and
returned or pre-scope failures may omit both fields. The remote
logPathUnavailable rule and the no-secrets rule are unchanged.

Follow-up qualification on discussion_r4306650954.

* docs(adr): scope the primary-panel fallback row to a primary panel in ADR 0025

buildInventory names the primary panel and emits apple_display_capture_ambiguous
only when a primary panel exists (display-inventory.ts: the capture display is
the sole lit panel or the primary panel); with neither, resolveAppleCaptureTarget
refuses with capture-panel-unidentified. The two glance rows overlapped on zero
or multiple lit panels. Qualify the fallback row condition.

Fixes #3796 review thread discussion_r4306742872.

* docs(adr): scope the flush owner to the router finalizer in ADR 0010

The previous sentence generalized over every thrown request error, but a
malformed-RPC throw never reaches the router. Name the owner: the router's
thrown-error finalizer attempts the flush. Replace the generic
returned/pre-scope sentence with the two concrete cases that omit both fields,
so the text no longer claims every returned or pre-scope failure must omit
them; normalization preserves any existing metadata.

Completes the qualification on discussion_r4306650954.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-human Valid work that needs human implementation, judgment, or maintainer merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Architecture WS5: collocation decisions and first refactor(move) batch

1 participant