@aperant/framework 0.8.4 → 0.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/CHANGELOG.md +156 -0
  2. package/agents/apt-planner.md +34 -3
  3. package/dist/cli/commands/coverage-check.d.mts.map +1 -1
  4. package/dist/cli/commands/coverage-check.mjs +74 -7
  5. package/dist/cli/commands/coverage-check.mjs.map +1 -1
  6. package/dist/cli/commands/detect-runtime.d.mts.map +1 -1
  7. package/dist/cli/commands/detect-runtime.mjs +18 -12
  8. package/dist/cli/commands/detect-runtime.mjs.map +1 -1
  9. package/dist/cli/coverage-check/user-outcomes.d.mts +84 -0
  10. package/dist/cli/coverage-check/user-outcomes.d.mts.map +1 -0
  11. package/dist/cli/coverage-check/user-outcomes.mjs +265 -0
  12. package/dist/cli/coverage-check/user-outcomes.mjs.map +1 -0
  13. package/dist/cli/host/detect.mjs +1 -1
  14. package/dist/cli/host/detect.mjs.map +1 -1
  15. package/dist/cli/install/install-from-source.mjs +3 -3
  16. package/dist/cli/install/legacy-paths.d.mts.map +1 -1
  17. package/dist/cli/install/legacy-paths.mjs +2 -0
  18. package/dist/cli/install/legacy-paths.mjs.map +1 -1
  19. package/dist/cli/verify-proof/idl/index.d.mts +1 -1
  20. package/dist/cli/verify-proof/idl/index.mjs +7 -8
  21. package/dist/cli/verify-proof/idl/index.mjs.map +1 -1
  22. package/dist/cli/verify-proof/idl/types.d.ts +5 -4
  23. package/dist/cli/verify-proof/idl/types.d.ts.map +1 -1
  24. package/dist/cli/verify-proof/idl/types.js +4 -3
  25. package/dist/cli/verify-proof/idl/types.js.map +1 -1
  26. package/dist/cli/verify-proof/resolver.d.mts +63 -1
  27. package/dist/cli/verify-proof/resolver.d.mts.map +1 -1
  28. package/dist/cli/verify-proof/resolver.mjs +164 -4
  29. package/dist/cli/verify-proof/resolver.mjs.map +1 -1
  30. package/dist/cli/verify-proof/runtime-detect.d.mts +6 -3
  31. package/dist/cli/verify-proof/runtime-detect.d.mts.map +1 -1
  32. package/dist/cli/verify-proof/runtime-detect.mjs +104 -11
  33. package/dist/cli/verify-proof/runtime-detect.mjs.map +1 -1
  34. package/dist/cli/verify-proof/trust.d.mts +1 -1
  35. package/dist/cli/verify-proof/trust.d.mts.map +1 -1
  36. package/dist/cli/verify-proof/trust.mjs +1 -1
  37. package/dist/driver-sdk/conformance.d.ts +41 -0
  38. package/dist/driver-sdk/conformance.d.ts.map +1 -0
  39. package/dist/driver-sdk/conformance.js +123 -0
  40. package/dist/driver-sdk/conformance.js.map +1 -0
  41. package/dist/driver-sdk/errors.d.ts +75 -0
  42. package/dist/driver-sdk/errors.d.ts.map +1 -0
  43. package/dist/driver-sdk/errors.js +80 -0
  44. package/dist/driver-sdk/errors.js.map +1 -0
  45. package/dist/driver-sdk/idl.d.ts +221 -0
  46. package/dist/driver-sdk/idl.d.ts.map +1 -0
  47. package/dist/driver-sdk/idl.js +140 -0
  48. package/dist/driver-sdk/idl.js.map +1 -0
  49. package/dist/driver-sdk/index.d.ts +28 -0
  50. package/dist/driver-sdk/index.d.ts.map +1 -0
  51. package/dist/driver-sdk/index.js +28 -0
  52. package/dist/driver-sdk/index.js.map +1 -0
  53. package/dist/driver-sdk/manifest.d.ts +93 -0
  54. package/dist/driver-sdk/manifest.d.ts.map +1 -0
  55. package/dist/driver-sdk/manifest.js +12 -0
  56. package/dist/driver-sdk/manifest.js.map +1 -0
  57. package/dist/driver-sdk/retry.d.ts +33 -0
  58. package/dist/driver-sdk/retry.d.ts.map +1 -0
  59. package/dist/driver-sdk/retry.js +50 -0
  60. package/dist/driver-sdk/retry.js.map +1 -0
  61. package/dist/plugin/.claude-plugin/plugin.json +2 -1
  62. package/dist/plugin/agents/apt-planner.md +34 -3
  63. package/dist/plugin/skills/apt-plan/SKILL.md +50 -0
  64. package/dist/plugin/skills/apt-pr-review/SKILL.md +1 -1
  65. package/dist/plugin/skills/apt-research/SKILL.md +526 -0
  66. package/dist/plugin/skills/apt-research/appendices/budget-loop.md +397 -0
  67. package/dist/plugin/skills/apt-research/appendices/claim-graph-schema.md +206 -0
  68. package/dist/plugin/skills/apt-research/appendices/domain-tools.md +236 -0
  69. package/dist/plugin/skills/apt-spar/SKILL.md +19 -7
  70. package/dist/plugin/skills/apt-verify-proof/SKILL.md +41 -2
  71. package/dist/schemas/quick-task.d.ts +17 -17
  72. package/drivers/.gitkeep +0 -0
  73. package/drivers/api/README.md +40 -0
  74. package/drivers/api/driver.mjs +59 -0
  75. package/drivers/api/manifest.json +26 -0
  76. package/drivers/browser/README.md +105 -0
  77. package/drivers/browser/driver.mjs +134 -0
  78. package/drivers/browser/manifest.json +35 -0
  79. package/drivers/cli/README.md +44 -0
  80. package/drivers/cli/driver.mjs +62 -0
  81. package/drivers/cli/manifest.json +28 -0
  82. package/drivers/electron/README.md +64 -0
  83. package/drivers/electron/driver.mjs +87 -0
  84. package/drivers/electron/manifest.json +37 -0
  85. package/package.json +7 -3
  86. package/skills/apt-plan/SKILL.md +50 -0
  87. package/skills/apt-planner.md +16 -0
  88. package/skills/apt-pr-review/SKILL.md +1 -1
  89. package/skills/apt-research/SKILL.md +526 -0
  90. package/skills/apt-research/appendices/budget-loop.md +397 -0
  91. package/skills/apt-research/appendices/claim-graph-schema.md +206 -0
  92. package/skills/apt-research/appendices/domain-tools.md +236 -0
  93. package/skills/apt-spar/SKILL.md +19 -7
  94. package/skills/apt-verify-proof/SKILL.md +41 -2
  95. package/src/cli/commands/coverage-check.mjs +126 -44
  96. package/src/cli/commands/detect-runtime.mjs +23 -14
  97. package/src/cli/coverage-check/user-outcomes.mjs +273 -0
  98. package/src/cli/host/detect.mjs +1 -1
  99. package/src/cli/install/install-from-source.mjs +3 -3
  100. package/src/cli/install/legacy-paths.mjs +2 -0
  101. package/src/cli/verify-proof/idl/index.mjs +7 -8
  102. package/src/cli/verify-proof/idl/types.ts +5 -4
  103. package/src/cli/verify-proof/manifest-schema.json +2 -1
  104. package/src/cli/verify-proof/resolver.mjs +171 -4
  105. package/src/cli/verify-proof/runtime-detect.mjs +99 -10
  106. package/src/cli/verify-proof/trust.mjs +1 -1
  107. package/templates/proof-verification.md +32 -3
  108. package/workflows/verify-proof.md +78 -9
@@ -0,0 +1,93 @@
1
+ /**
2
+ * manifest.ts — TypeScript shape of a driver manifest.
3
+ *
4
+ * Mirrors `packages/framework/src/cli/verify-proof/manifest-schema.json`
5
+ * (ST03) one-to-one. The JSON Schema is the runtime validator (publish-
6
+ * time + load-time); this TS type is what third-party driver authors
7
+ * `import type` to author manifests with intellisense.
8
+ *
9
+ * Spec authority: spec.md §ID-03 (trust tiers) + §ID-04 (driver layout).
10
+ */
11
+ export type TrustTier = 'first_party_signed' | 'community_verified' | 'community_unverified' | 'local_unverified';
12
+ export type Stability = 'experimental' | 'beta' | 'ga';
13
+ export type SandboxProfile = 'read_only' | 'workspace_write' | 'system_write';
14
+ export type NetworkPosture = 'deny' | 'allowlist' | 'allow';
15
+ /** Structured local-command — strings are NEVER accepted (ID-03). */
16
+ export interface LocalCommand {
17
+ readonly binary: string;
18
+ readonly args: readonly string[];
19
+ }
20
+ /** Transport — exactly one of the variants. */
21
+ export type Transport = {
22
+ readonly mcp_server_id: string;
23
+ } | {
24
+ readonly local_command: LocalCommand;
25
+ } | {
26
+ readonly http_endpoint: string;
27
+ } | {
28
+ readonly npm_package: string;
29
+ } | {
30
+ readonly builtin: true;
31
+ };
32
+ export interface Publisher {
33
+ readonly name: string;
34
+ readonly npm_scope?: string;
35
+ readonly github_org?: string;
36
+ readonly verified?: boolean;
37
+ }
38
+ export interface Provenance {
39
+ readonly scheme?: 'sigstore' | 'npm-provenance' | 'gpg' | 'none';
40
+ readonly identity?: string;
41
+ readonly signature?: string;
42
+ readonly certificate?: string;
43
+ }
44
+ export interface Integrity {
45
+ readonly manifest_sha256?: string;
46
+ readonly artifact_digest?: string;
47
+ }
48
+ export interface TrustBlock {
49
+ readonly tier: TrustTier;
50
+ readonly publisher?: Publisher;
51
+ readonly provenance?: Provenance;
52
+ readonly integrity?: Integrity;
53
+ }
54
+ export interface SecurityBlock {
55
+ readonly sandbox_profile: SandboxProfile;
56
+ readonly network: NetworkPosture;
57
+ readonly allowed_executables?: readonly string[];
58
+ readonly allow_shell?: boolean;
59
+ readonly requires_user_approval?: boolean;
60
+ }
61
+ export interface AuditBlock {
62
+ readonly log_invocations: boolean;
63
+ readonly log_manifest_hash: boolean;
64
+ }
65
+ export interface PreflightCheck {
66
+ readonly name: string;
67
+ readonly command?: LocalCommand;
68
+ readonly required: boolean;
69
+ }
70
+ export interface DriverManifest {
71
+ readonly driverId: string;
72
+ readonly version: string;
73
+ readonly targets: readonly string[];
74
+ readonly capabilities: readonly string[];
75
+ readonly evidence_capabilities?: readonly string[];
76
+ readonly frameworkApiRange: string;
77
+ readonly requires?: {
78
+ readonly allOf?: readonly string[];
79
+ readonly anyOf?: readonly string[];
80
+ };
81
+ readonly os?: readonly string[];
82
+ readonly arch?: readonly string[];
83
+ readonly container_support?: boolean;
84
+ readonly conflicts_with?: readonly string[];
85
+ readonly priority: number;
86
+ readonly stability: Stability;
87
+ readonly trust: TrustBlock;
88
+ readonly security: SecurityBlock;
89
+ readonly audit?: AuditBlock;
90
+ readonly preflight?: readonly PreflightCheck[];
91
+ readonly transport: Transport;
92
+ }
93
+ //# sourceMappingURL=manifest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../src/driver-sdk/manifest.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * manifest.ts — TypeScript shape of a driver manifest.
3
+ *
4
+ * Mirrors `packages/framework/src/cli/verify-proof/manifest-schema.json`
5
+ * (ST03) one-to-one. The JSON Schema is the runtime validator (publish-
6
+ * time + load-time); this TS type is what third-party driver authors
7
+ * `import type` to author manifests with intellisense.
8
+ *
9
+ * Spec authority: spec.md §ID-03 (trust tiers) + §ID-04 (driver layout).
10
+ */
11
+ export {};
12
+ //# sourceMappingURL=manifest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../src/driver-sdk/manifest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * retry.ts — exponential backoff helper with abort signal.
3
+ *
4
+ * Used by driver implementations that want to retry transient transport
5
+ * failures (DriverInvocationError) before giving up. Pure, dependency-free.
6
+ */
7
+ export interface RetryOptions {
8
+ /** Total maximum attempts including the first. Default 3. */
9
+ readonly max_attempts?: number;
10
+ /** Initial delay in ms before the second attempt. Default 100. */
11
+ readonly base_delay_ms?: number;
12
+ /** Cap each delay at this many ms. Default 5000. */
13
+ readonly max_delay_ms?: number;
14
+ /**
15
+ * Multiplier applied to delay after each failed attempt. Default 2 →
16
+ * 100ms, 200ms, 400ms, 800ms, …
17
+ */
18
+ readonly multiplier?: number;
19
+ /** Optional AbortSignal — abort short-circuits the retry loop. */
20
+ readonly signal?: AbortSignal;
21
+ /**
22
+ * Optional predicate. When provided, only retry when shouldRetry(err) is
23
+ * true; otherwise re-throw immediately. Default: retry every error.
24
+ */
25
+ readonly shouldRetry?: (err: unknown) => boolean;
26
+ }
27
+ /**
28
+ * Run `fn` with exponential backoff. Returns the result of the first
29
+ * successful call. If every attempt fails (or the signal aborts), throws
30
+ * the last error.
31
+ */
32
+ export declare function retryWithBackoff<T>(fn: () => Promise<T>, opts?: RetryOptions): Promise<T>;
33
+ //# sourceMappingURL=retry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../../src/driver-sdk/retry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,YAAY;IAC5B,6DAA6D;IAC7D,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B,kEAAkE;IAClE,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,oDAAoD;IACpD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;IAC9B;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,kEAAkE;IAClE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAA;IAC7B;;;OAGG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAA;CAChD;AAED;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EACvC,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,GAAE,YAAiB,GACrB,OAAO,CAAC,CAAC,CAAC,CAqCZ"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * retry.ts — exponential backoff helper with abort signal.
3
+ *
4
+ * Used by driver implementations that want to retry transient transport
5
+ * failures (DriverInvocationError) before giving up. Pure, dependency-free.
6
+ */
7
+ /**
8
+ * Run `fn` with exponential backoff. Returns the result of the first
9
+ * successful call. If every attempt fails (or the signal aborts), throws
10
+ * the last error.
11
+ */
12
+ export async function retryWithBackoff(fn, opts = {}) {
13
+ const maxAttempts = Math.max(1, opts.max_attempts ?? 3);
14
+ const baseDelay = Math.max(0, opts.base_delay_ms ?? 100);
15
+ const maxDelay = Math.max(0, opts.max_delay_ms ?? 5000);
16
+ const multiplier = opts.multiplier ?? 2;
17
+ const signal = opts.signal;
18
+ const shouldRetry = opts.shouldRetry ?? (() => true);
19
+ let lastErr;
20
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
21
+ if (signal?.aborted) {
22
+ throw signal.reason instanceof Error ? signal.reason : new Error('retryWithBackoff aborted');
23
+ }
24
+ try {
25
+ return await fn();
26
+ }
27
+ catch (err) {
28
+ lastErr = err;
29
+ if (attempt >= maxAttempts)
30
+ break;
31
+ if (!shouldRetry(err))
32
+ break;
33
+ const delay = Math.min(maxDelay, baseDelay * multiplier ** (attempt - 1));
34
+ await new Promise((resolve, reject) => {
35
+ const timer = setTimeout(resolve, delay);
36
+ if (signal) {
37
+ const onAbort = () => {
38
+ clearTimeout(timer);
39
+ reject(signal.reason instanceof Error
40
+ ? signal.reason
41
+ : new Error('retryWithBackoff aborted'));
42
+ };
43
+ signal.addEventListener('abort', onAbort, { once: true });
44
+ }
45
+ });
46
+ }
47
+ }
48
+ throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
49
+ }
50
+ //# sourceMappingURL=retry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/driver-sdk/retry.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAuBH;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACrC,EAAoB,EACpB,OAAqB,EAAE;IAEvB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,IAAI,CAAC,CAAC,CAAA;IACvD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,IAAI,GAAG,CAAC,CAAA;IACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,CAAA;IACvD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,CAAC,CAAA;IACvC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAA;IAC1B,MAAM,WAAW,GAAG,IAAI,CAAC,WAAW,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;IAEpD,IAAI,OAAgB,CAAA;IACpB,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,WAAW,EAAE,OAAO,EAAE,EAAE,CAAC;QACzD,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;YACrB,MAAM,MAAM,CAAC,MAAM,YAAY,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAA;QAC7F,CAAC;QACD,IAAI,CAAC;YACJ,OAAO,MAAM,EAAE,EAAE,CAAA;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACd,OAAO,GAAG,GAAG,CAAA;YACb,IAAI,OAAO,IAAI,WAAW;gBAAE,MAAK;YACjC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC;gBAAE,MAAK;YAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,SAAS,GAAG,UAAU,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAA;YACzE,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACrC,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;gBACxC,IAAI,MAAM,EAAE,CAAC;oBACZ,MAAM,OAAO,GAAG,GAAG,EAAE;wBACpB,YAAY,CAAC,KAAK,CAAC,CAAA;wBACnB,MAAM,CACL,MAAM,CAAC,MAAM,YAAY,KAAK;4BAC7B,CAAC,CAAC,MAAM,CAAC,MAAM;4BACf,CAAC,CAAC,IAAI,KAAK,CAAC,0BAA0B,CAAC,CACxC,CAAA;oBACF,CAAC,CAAA;oBACD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;gBAC1D,CAAC;YACF,CAAC,CAAC,CAAA;QACH,CAAC;IACF,CAAC;IACD,MAAM,OAAO,YAAY,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAA;AACtE,CAAC"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aperant",
3
- "version": "0.8.4",
3
+ "version": "0.8.6",
4
4
  "description": "AI coding framework — composable skills for planning, executing, verifying, and reviewing code with any LLM provider. Works as Claude Code commands, Codex tasks, or programmatically.",
5
5
  "author": {
6
6
  "name": "Mikalsen AI",
@@ -46,6 +46,7 @@
46
46
  "skills/apt-prototype",
47
47
  "skills/apt-quick",
48
48
  "skills/apt-release-notes",
49
+ "skills/apt-research",
49
50
  "skills/apt-resume",
50
51
  "skills/apt-review",
51
52
  "skills/apt-roadmap",
@@ -240,6 +240,11 @@ survives the task as a second-consumer document.
240
240
 
241
241
  ### 4.B. STANDARD / DEEP / COMPLEX — PRD-shaped spec.md
242
242
 
243
+ **Three orthogonal user-facing sections — keep them distinct.** User
244
+ Stories (motivation prose), User Outcomes (verify-proof input contract),
245
+ and Acceptance Criteria (code-level invariants) serve distinct
246
+ purposes. Do NOT collapse them — STANDARD/DEEP specs carry all three.
247
+
243
248
  ```markdown
244
249
  # Spec: {task title}
245
250
 
@@ -257,6 +262,22 @@ survives the task as a second-consumer document.
257
262
  {One **US-NN (persona).** story per user-value slice. Stories map 1:1
258
263
  onto subtasks in implementation_plan.json.}
259
264
 
265
+ ## User Outcomes
266
+ {Verify-proof input contract. One bolded `**Epic:**` headline + N
267
+ atomic outcomes. Authors write the LITERAL string `**ON**` — IDs are
268
+ POSITIONAL and synthesized by the parser (first row becomes O1, second
269
+ O2, ...). Closed surface set: `electron | web | cli | api | electron+web`.
270
+ Optional cross-refs via `*(requires ON N)*`. Refactor-only specs MAY
271
+ use the empty-with-note escape (verbatim string,
272
+ italic underscores + em dash + period required):}
273
+
274
+ `_No user-observable changes — pure refactor._`
275
+
276
+ **Epic:** {one-sentence user-facing capability headline}
277
+
278
+ - **ON** [surface]: {user does X; system shows/does Y}
279
+ - **ON** [surface]: {user does X; system shows/does Y} *(requires ON 1)*
280
+
260
281
  ## Implementation Decisions
261
282
  {Load-bearing principles carried into every subtask. Format:
262
283
  "### ID-NN: {title}" + rationale + practical consequence.}
@@ -279,9 +300,19 @@ reference these IDs via the per-subtask `acceptance_criteria` field.}
279
300
  ```
280
301
 
281
302
  **PRD section ordering is load-bearing.** `apt-tools coverage-check
282
- validate` greps `## Acceptance Criteria`; `apt-tools consistency check`
283
- greps `## Solution` and `## User Stories`. Renaming or reordering these
284
- sections breaks downstream tooling and the C15 consistency rules.
303
+ validate` greps `## Acceptance Criteria` AND `## User Outcomes`;
304
+ `apt-tools consistency check` greps `## Solution` and `## User Stories`.
305
+ Renaming or reordering these sections breaks downstream tooling and the
306
+ C15 consistency rules.
307
+
308
+ **`## User Outcomes` synthesis directive.** Outcomes are
309
+ user-observable (a user does X; the system shows/does Y); Acceptance
310
+ Criteria are code-level invariants (a function returns X; a config key
311
+ exists). Do NOT collapse them — they parse through different gates and
312
+ serve different consumers. STANDARD/DEEP specs carry both sections in
313
+ parallel. IDs are POSITIONAL: the parser counts outcome rows in
314
+ document order and synthesizes `O1`, `O2`, ... — authors MUST write
315
+ the literal `**ON**` token, never `**O1**`/`**O2**`.
285
316
 
286
317
  **Do NOT interview the user.** The PRD is synthesized from the task
287
318
  description + codebase investigation + AGENTS.md, not from a clarifying
@@ -161,6 +161,14 @@ and is committable as a second-consumer document. Section ordering is
161
161
  **load-bearing** — downstream tooling (`apt-tools coverage-check`,
162
162
  `apt-tools consistency check`) reads sections by header.
163
163
 
164
+ **Three orthogonal user-facing sections — keep them distinct.** User
165
+ Stories carry product motivation, User Outcomes carry the
166
+ verify-proof input contract, and Acceptance Criteria carry code-level
167
+ invariants. The three do NOT subsume each other; a STANDARD/DEEP spec
168
+ carries all three. See the `## User Outcomes` block below for the
169
+ verify-proof unit shape (Epic line + atomic outcomes + surface tags
170
+ + empty-with-note escape).
171
+
164
172
  ```markdown
165
173
  # Spec: {task title}
166
174
 
@@ -184,6 +192,29 @@ ships: new files, modified files, new flags, new config, new skills.}
184
192
  {persona}, when I {trigger}, I want {behavior} so I can {outcome}."
185
193
  Stories map 1:1 onto subtasks in implementation_plan.json.}
186
194
 
195
+ ## User Outcomes
196
+
197
+ {The verify-proof input contract. One bolded `**Epic:**` headline + N
198
+ atomic outcomes tagged by surface. Authors write the LITERAL string
199
+ `**ON**` — IDs are POSITIONAL and synthesized by the parser (the first
200
+ outcome row becomes `O1`, the second `O2`, etc.). Closed surface set:
201
+ `electron | web | cli | api | electron+web`. Optional cross-references
202
+ via `*(requires ON N)*` where `N` is the digit of a prior outcome's
203
+ position. For pure-refactor specs with no user-observable changes, the
204
+ body MAY be exactly `_No user-observable changes — pure refactor._`
205
+ (italic underscores required, exact em dash, period mandatory).
206
+ Coverage-check parses this section into a `user_outcomes` payload —
207
+ see the gate table below.}
208
+
209
+ **Epic:** {one-sentence user-facing capability headline}
210
+
211
+ - **ON** [surface]: {user does X; system shows/does Y}
212
+ - **ON** [surface]: {user does X; system shows/does Y} *(requires ON 1)*
213
+ - **ON** [electron+web]: {cross-surface outcome — runs twice, once per surface}
214
+
215
+ (Refactor-only escape:)
216
+ _No user-observable changes — pure refactor._
217
+
187
218
  ## Implementation Decisions
188
219
 
189
220
  {Load-bearing principles carried forward into every subtask. Format:
@@ -215,6 +246,25 @@ ID. Subtasks reference these IDs via their per-subtask
215
246
  plan-coverage-check input.}
216
247
  ```
217
248
 
249
+ **`## User Outcomes` is the verify-proof input contract (STANDARD/DEEP
250
+ only — QUICK is hard-exempt per ID-05 / Fast Path Guarantee).** The
251
+ section sits between `## User Stories` (product motivation prose) and
252
+ `## Implementation Decisions` (load-bearing engineering principles).
253
+ Coverage-check (`apt-tools coverage-check validate .`) parses the
254
+ section into a `user_outcomes` payload with this gate behavior:
255
+
256
+ | Header present? | Body shape | Gate result (v0.8.x) | v0.9.0 hard cutover |
257
+ |---|---|---|---|
258
+ | no | — | `warn` (migration deadline emitted) | `block` |
259
+ | yes | `outcomes` (≥1 `**ON**` row) | `pass` | `pass` |
260
+ | yes | exactly `_No user-observable changes — pure refactor._` | `pass` | `pass` |
261
+ | yes | empty (header but nothing under it) | `block` | `block` |
262
+
263
+ Closed surface set: `electron | web | cli | api | electron+web`. The
264
+ `electron+web` tag means the outcome runs on both surfaces during
265
+ verify-proof (split screenshot trees, two test entries in
266
+ `verification.json`).
267
+
218
268
  **Constraint — do NOT interview the user.** The PRD is synthesized from
219
269
  the task description + codebase investigation + AGENTS.md, not from a
220
270
  clarifying interview. If a section truly cannot be filled, write
@@ -1081,7 +1081,7 @@ For every finding with `validation_status == "confirmed_valid"` AND `severity
1081
1081
  - `{REVIEWER_EVIDENCE}` — the finding's `evidence` field verbatim.
1082
1082
  3. Invoke codex using the shape configured at `.aperant/config.json:router.llm.providers.codex`:
1083
1083
  ```bash
1084
- codex exec --model gpt-5.3-codex --input-file /tmp/fp-gate-${FINDING_ID}.md
1084
+ codex exec --input-file /tmp/fp-gate-${FINDING_ID}.md
1085
1085
  ```
1086
1086
  Parse the JSON response `{verdict, reasoning, evidence_quote, severity_assessment}`.
1087
1087
  4. If `verdict == "falsify"`, set the finding's `validation_status = "dismissed_cross_model_falsification"` and copy the codex response into `fp_gate_result`. If `verdict == "confirm"`, pass through unchanged.