Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/agents/adr-0019-unit.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Each step names its declaration site; read that, not prose.
| --- | --- |
| Declare the use(s) with the one neutral `defineUse`; required-only by default, a preferred operation needs a recorded measurement in the unit review (§9) | `packages/contracts/src/platform-runtime-operations.ts` |
| Plan resolution is pure and lives in contracts (`resolve<Command>RuntimePlan`), never in the handler | `packages/contracts/src/*-runtime-plan.ts` |
| Handler: resolve plan → `inspectRequiredRuntimeUse({ device, use: plan.use, inspectFacts })` → on `admitted`, bind **once** with that plan's use → operate. No admission-only binds, no `requireCommandSupported`, no capability bucket. (#1841 replaces this with `admitRuntimePlan({ device, plan, inspectFacts })`, whose returned token names both device and plan and is what the binder requires; this row follows it when it lands) | `src/daemon/handlers/session-runtime-admission.ts`; the `snapshot` route in `src/daemon/snapshot-runtime.ts` + `snapshot-runtime-binding.ts` as the model |
| Handler: resolve plan → `admitRuntimePlan({ device, plan, inspectFacts })` → hand the returned `AdmittedRuntimePlan` to the command's facts-first binder, which unwraps it (`unwrapAdmittedRuntimePlan`) and binds **once**, on the admitted device, with the admitted plan's use → operate. The token is minted only by admission and read back by exact identity, so admit-before-bind — and admit-*this-device*-before-binding-it — is a type and runtime fact, not a gate. No admission-only binds, no `requireCommandSupported`, no capability bucket | `src/daemon/handlers/session-runtime-admission.ts`; the shared snapshot/diff owning interface `resolveBoundSnapshotCaptureRuntime` in `src/daemon/snapshot-runtime-binding.ts` as the model |
| Descriptor flips to `platformExecution: { kind: 'device-runtime', use(s) }` in the same PR; the discriminator is exhaustive, so a forgotten descriptor fails typecheck | `src/core/command-descriptor/registry.ts` |
| Each platform package reports exact-owner facts and implements the operations; provider ownership fails closed (missing behavior never falls through to a local owner) | `packages/platform-*/src/**`, `packages/provider-*/src/**` |
| Add one row to the parametrized cutover table: `legacyRetirement` (what must be gone), `runtimeTypeNames`, `operations`, `singularExecution` with lexical `operationOwners`. The mechanism already carries the planted-red proof; a row that leaves a claim unstated is rejected by `cutoverRowDefects` | `scripts/layering/runtime-command-cutover-table.ts` (rule ids allocate upward; snapshot is R32) |
Expand Down
4 changes: 4 additions & 0 deletions scripts/layering/runtime-command-cutover-policy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ test('the parametrized gate goes red on a planted row across every generalized c
"import { resolvePlantedBackend } from './planted-legacy.ts';",
"requireCommandSupported('planted', device);",
'const widened = runtime as PlantedRuntimeOperations;',
'const forged = { admitted: true, plan } as AdmittedRuntimePlan<PlantedPlan>;',
"function handlePlantedCommand() { widened.operations['plantedDump']({}); }",
].join('\n'),
],
Expand All @@ -44,6 +45,9 @@ test('the parametrized gate goes red on a planted row across every generalized c
'src/daemon/planted-handler.ts: legacy planted route resolvePlantedBackend',
'src/daemon/planted-handler.ts: legacy planted capability admission requireCommandSupported',
'src/daemon/planted-handler.ts: widened planted runtime type assertion',
// The admission proof is shared across rows: a route that casts its way to an
// AdmittedRuntimePlan has manufactured the facts-first admission the binder requires.
'src/daemon/planted-handler.ts: widened planted runtime type assertion',
'src/daemon/planted-handler.ts: bracketed planted operation access',
'src/core/command-descriptor/registry.ts: planted descriptor retains legacy capability admission',
'src/core/capabilities.ts: static platform command set retains planted admission',
Expand Down
8 changes: 6 additions & 2 deletions scripts/layering/runtime-command-cutover-policy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ import { memberName, propertyName, visitAst, type ProductionSource } from './cut

type AstNode = Record<string, unknown>;

const SHARED_RUNTIME_TYPE_NAME = 'BoundDeviceRuntime';
// Types no daemon route may manufacture with an assertion: the bound runtime itself, and the
// admission proof a facts-first binder requires (`AdmittedRuntimePlan`, minted only by
// `admitRuntimePlan`). Together with the row's own runtime type names they are the
// manufactured-proof column — a cast to any of them is a route repairing missing proof.
const SHARED_RUNTIME_TYPE_NAMES = ['BoundDeviceRuntime', 'AdmittedRuntimePlan'] as const;

/**
* The one parametrized runtime-command-cutover gate (ADR 0019 §8). Every migrated
Expand Down Expand Up @@ -372,7 +376,7 @@ function narrowingViolations(
// An inventory row binds no device runtime, so it has nothing to re-widen.
if (!file.path.startsWith('src/daemon/') || row.execution !== 'device-runtime') return [];
const violations: UnruledViolation[] = [];
const runtimeTypes = new Set([SHARED_RUNTIME_TYPE_NAME, ...row.runtimeTypeNames]);
const runtimeTypes = new Set([...SHARED_RUNTIME_TYPE_NAMES, ...row.runtimeTypeNames]);
visitAst(program, (node) => {
if (
(node['type'] === 'TSAsExpression' || node['type'] === 'TSTypeAssertion') &&
Expand Down
80 changes: 0 additions & 80 deletions scripts/layering/runtime-command-cutover-snapshot.test.ts

This file was deleted.

134 changes: 0 additions & 134 deletions scripts/layering/runtime-command-cutover-snapshot.ts

This file was deleted.

6 changes: 1 addition & 5 deletions scripts/layering/runtime-command-cutover-table.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,7 @@ test('R32 snapshot rejects legacy admission and dispatcher projection', () => {
}
function resolveBoundSnapshotCaptureRuntime(params) {
const plan = resolveSnapshotRuntimePlan(normalizedIntent);
inspectRequiredRuntimeUse({
device,
use: plan.use,
inspectFacts: params.inspectFacts,
});
admitRuntimePlan({ device, plan, inspectFacts: params.inspectFacts });
return bindSnapshotCaptureRuntime(params.bindDevice, device, plan);
}
`,
Expand Down
3 changes: 1 addition & 2 deletions scripts/layering/runtime-command-cutover-table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import {
runtimeLifecycleRouteBindingViolations,
sourceExecutedUsingDeclarationViolations,
} from './runtime-command-cutover-extensions.ts';
import { snapshotPlatformPolicyBranchViolations } from './runtime-command-cutover-snapshot.ts';
import { recordRuntimeDaemonMechanicsViolations } from './record-runtime-mechanics-policy.ts';
import { retiredDispatchProjectionViolations } from './runtime-command-cutover-descriptor.ts';

Expand Down Expand Up @@ -471,7 +470,7 @@ export const MIGRATED_COMMAND_CUTOVERS: readonly MigratedCommandCutover[] = [
captureSnapshotWithoutActiveApp: ['selectSnapshotWithoutActiveApp'],
},
},
extensions: [snapshotRetiredDispatchProjectionProof, snapshotPlatformPolicyBranchViolations],
extensions: [snapshotRetiredDispatchProjectionProof],
},
{
rule: 'R33 diff-runtime-cutover',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,7 @@
import { readFileSync } from 'node:fs';
import { snapshotRuntimePlanUses } from '@agent-device/contracts/platform';
import { expect, test } from 'vitest';
import { commandDescriptors } from '../registry.ts';

const snapshotRuntimeSource = readFileSync(
new URL('../../../daemon/snapshot-runtime.ts', import.meta.url),
'utf8',
);
const snapshotRuntimeBindingSource = readFileSync(
new URL('../../../daemon/snapshot-runtime-binding.ts', import.meta.url),
'utf8',
);
const snapshotRuntimeCommandSource = readFileSync(
new URL('../../../daemon/snapshot-command-runtime.ts', import.meta.url),
'utf8',
);

test('snapshot descriptor declares its complete planned capture uses with no legacy projection', () => {
const snapshot = commandDescriptors.find(({ name }) => name === 'snapshot');

Expand Down Expand Up @@ -43,39 +29,3 @@ test('diff descriptor reuses the complete snapshot plan uses with no legacy proj
uses: snapshotRuntimePlanUses,
});
});

test('shared snapshot owning interface inspects facts and binds the declared use exactly once', () => {
const publicRoute = snapshotRuntimeSource.slice(
snapshotRuntimeSource.indexOf('export async function dispatchSnapshotViaRuntime'),
snapshotRuntimeSource.indexOf('function publishedSnapshotGeneration'),
);
const owningInterface = snapshotRuntimeBindingSource.slice(
snapshotRuntimeBindingSource.indexOf(
'export async function resolveBoundSnapshotCaptureRuntime',
),
snapshotRuntimeBindingSource.indexOf('async function bindSnapshotCaptureRuntime'),
);

expect(publicRoute).toContain('dispatchSnapshotRuntimeCommand({');
expect(
snapshotRuntimeCommandSource.match(
/resolveBoundSnapshotCaptureRuntime\(params, params\.command\)/g,
),
).toHaveLength(1);
expect(owningInterface.match(/resolveSnapshotRuntimePlan\(\{/g)).toHaveLength(1);
expect(owningInterface.match(/inspectRequiredRuntimeUse\(\{/g)).toHaveLength(1);
expect(
owningInterface.match(/bindSnapshotCaptureRuntime\(params\.bindDevice, device, plan\)/g),
).toHaveLength(1);
expect(
owningInterface.match(/use: plan\.use,[\s\S]*inspectFacts: params\.inspectFacts/g),
).toHaveLength(1);
expect(
snapshotRuntimeBindingSource.match(/const bind = requireRuntimeBinding\(bindDevice\)/g),
).toHaveLength(1);
expect(owningInterface.match(/runtime\.captureSnapshot\(/g)).toHaveLength(1);
expect(publicRoute).not.toContain("requireCommandSupported('snapshot'");
for (const policyName of ['isIosFamily', 'isIosSimulator', 'providerOwned']) {
expect(snapshotRuntimeBindingSource).not.toContain(policyName);
}
});
Loading
Loading