@cassiomc1/forgeloop 1.13.0 → 1.14.0

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 (211) hide show
  1. package/AGENT_COMPATIBILITY.md +8 -0
  2. package/DOCS_INDEX.md +35 -3
  3. package/ENG/nodejs-backend-development-eng.md +2 -2
  4. package/ENG/sec-code-eng.md +7 -7
  5. package/EXECUTION_STATE.md +12 -0
  6. package/LOOP_ENGINEERING.md +28 -2
  7. package/ORCHESTRATOR_INTEGRATION.md +9 -5
  8. package/PROTOCOL_INTEGRATION.md +55 -2
  9. package/README.md +40 -25
  10. package/TERMINOLOGY.md +2 -0
  11. package/THREAT_MODEL.md +140 -1
  12. package/completions/_forgeloop +19 -1
  13. package/completions/forgeloop.bash +37 -1
  14. package/completions/forgeloop.fish +123 -1
  15. package/docs/ADVISORY_CONTEXT.md +25 -0
  16. package/docs/AGENT_BROWSER_ADAPTER.md +81 -0
  17. package/docs/AGENT_BROWSER_VERIFICATION.md +6 -0
  18. package/docs/AGENT_PROTOCOL_SUMMARY.md +27 -2
  19. package/docs/AGENT_SKILL.md +66 -0
  20. package/docs/ARTIFACT_REFERENCE.md +123 -0
  21. package/docs/AUDIT_UX.md +46 -0
  22. package/docs/BROWSER_VERIFICATION.md +136 -0
  23. package/docs/CLI_REFERENCE.md +366 -6
  24. package/docs/CODE_ATTESTATION.md +2 -2
  25. package/docs/DOCUMENTATION_GUIDE.md +32 -11
  26. package/docs/JEV_BENCHMARKS.md +31 -0
  27. package/docs/MODEL_ROUTING.md +37 -0
  28. package/docs/OPENSRC_ADAPTER.md +241 -0
  29. package/docs/PACKAGE_CONTENTS.md +35 -8
  30. package/docs/PROVIDERS.md +126 -0
  31. package/docs/PROVIDER_ARCHITECTURE.md +199 -0
  32. package/docs/RECIPES.md +9 -0
  33. package/docs/RELEASE_CHECKLIST.md +38 -5
  34. package/docs/SECURITY_REVIEW.md +71 -0
  35. package/docs/SEMANTIC_DECISION_PLANE.md +71 -0
  36. package/docs/TEST_INTELLIGENCE.md +29 -0
  37. package/docs/TEST_PRUNING.md +14 -0
  38. package/docs/TROUBLESHOOTING.md +198 -1
  39. package/docs/UNIVERSAL_INTEGRATION.md +31 -0
  40. package/docs/assets/diagrams/forgeloop-code-attestation-flow.html +2 -2
  41. package/docs/assets/diagrams/forgeloop-code-attestation-flow.receipt.json +5 -5
  42. package/docs/assets/diagrams/forgeloop-code-attestation-flow.svg +1 -1
  43. package/docs/assets/diagrams/forgeloop-engineering-flow.html +39 -26
  44. package/docs/assets/diagrams/forgeloop-engineering-flow.receipt.json +6 -6
  45. package/docs/assets/diagrams/forgeloop-engineering-flow.svg +26 -26
  46. package/docs/assets/diagrams/forgeloop-verification-trust-flow.html +2 -1
  47. package/docs/assets/diagrams/forgeloop-verification-trust-flow.receipt.json +5 -5
  48. package/docs/assets/diagrams/forgeloop-verification-trust-flow.svg +1 -1
  49. package/docs/diagrams/README.md +13 -9
  50. package/docs/diagrams/forgeloop-code-attestation-flow.workflow.json +1 -1
  51. package/docs/diagrams/forgeloop-engineering-flow.workflow.json +24 -19
  52. package/docs/diagrams/forgeloop-verification-trust-flow.workflow.json +1 -0
  53. package/docs/diagrams/reviews/forgeloop-code-attestation-flow.review.json +4 -4
  54. package/docs/diagrams/reviews/forgeloop-engineering-flow.review.json +4 -4
  55. package/docs/diagrams/reviews/forgeloop-verification-trust-flow.review.json +4 -4
  56. package/docs/documentation-manifest.json +750 -5
  57. package/docs/protocol-requirements.json +24 -0
  58. package/package.json +30 -3
  59. package/schemas/config.schema.json +14 -0
  60. package/schemas/context-plan.schema.json +18 -0
  61. package/schemas/semantic-decision.schema.json +46 -0
  62. package/schemas/test-utility.schema.json +44 -0
  63. package/scripts/CI_VALIDATORS.md +6 -6
  64. package/scripts/benchmark-jev.mjs +5 -0
  65. package/scripts/benchmark-test-intelligence.mjs +4 -0
  66. package/scripts/generate-agent-protocol-summary.mjs +4 -1
  67. package/scripts/generate-forgeloop-skill.mjs +133 -0
  68. package/scripts/jev-smoke.mjs +19 -0
  69. package/skills/forgeloop/README.md +9 -0
  70. package/skills/forgeloop/SKILL.md +77 -0
  71. package/skills/forgeloop/references/lifecycle.md +9 -0
  72. package/skills/forgeloop/references/recovery.md +7 -0
  73. package/skills/forgeloop/references/verification.md +7 -0
  74. package/src/adapters/agent-browser/assertions.js +47 -0
  75. package/src/adapters/agent-browser/commands.js +54 -0
  76. package/src/adapters/agent-browser/index.js +3 -0
  77. package/src/adapters/agent-browser/locator.js +40 -0
  78. package/src/adapters/agent-browser/process.js +215 -0
  79. package/src/adapters/agent-browser/provider.js +313 -0
  80. package/src/adapters/emulated-services/constants.js +24 -0
  81. package/src/adapters/emulated-services/index.js +7 -0
  82. package/src/adapters/emulated-services/process.js +162 -0
  83. package/src/adapters/emulated-services/provider.js +282 -0
  84. package/src/adapters/opensrc/normalize.js +90 -0
  85. package/src/adapters/opensrc/process.js +248 -0
  86. package/src/adapters/opensrc/provider.js +338 -0
  87. package/src/adapters/opensrc/search.js +264 -0
  88. package/src/adapters/typesafe/client.js +28 -0
  89. package/src/adapters/typesafe/engine.js +63 -0
  90. package/src/adapters/typesafe/normalize.js +41 -0
  91. package/src/cli.js +108 -0
  92. package/src/commands/checkpoint-revalidate.js +176 -0
  93. package/src/commands/context-plan.js +38 -0
  94. package/src/commands/contract-create.js +264 -0
  95. package/src/commands/contract-revise.js +236 -0
  96. package/src/commands/decision-show.js +14 -0
  97. package/src/commands/decision-status.js +22 -0
  98. package/src/commands/discover.js +41 -0
  99. package/src/commands/doctor.js +15 -0
  100. package/src/commands/gate-record.js +205 -0
  101. package/src/commands/gate-revalidate.js +137 -0
  102. package/src/commands/model-route.js +32 -0
  103. package/src/commands/route.js +146 -18
  104. package/src/commands/semantic-plan.js +17 -0
  105. package/src/commands/task-abandon.js +224 -0
  106. package/src/commands/task-migrate-contract-bootstrap-repair.js +288 -0
  107. package/src/commands/task-repair-contract-bootstrap.js +263 -0
  108. package/src/commands/test-inventory.js +5 -0
  109. package/src/commands/test-prune-plan.js +5 -0
  110. package/src/commands/test-prune-probe.js +5 -0
  111. package/src/commands/test-utility.js +5 -0
  112. package/src/commands/validate-protocol.js +10 -1
  113. package/src/core/artifact-registry.js +24 -0
  114. package/src/core/audit-ux.js +514 -0
  115. package/src/core/browser-verification/constants.js +149 -0
  116. package/src/core/browser-verification/normalize.js +254 -0
  117. package/src/core/browser-verification/provider.js +519 -0
  118. package/src/core/browser-verification/service.js +115 -0
  119. package/src/core/checkpoint-revalidation.js +319 -0
  120. package/src/core/cli-command-definitions.js +241 -0
  121. package/src/core/command-executors.js +110 -0
  122. package/src/core/command-input.js +115 -43
  123. package/src/core/completion-artifacts.js +14 -5
  124. package/src/core/completion.js +4 -6
  125. package/src/core/config.js +3 -0
  126. package/src/core/context-compiler/budget.js +9 -0
  127. package/src/core/context-compiler/candidates.js +39 -0
  128. package/src/core/context-compiler/compiler.js +63 -0
  129. package/src/core/context-compiler/fingerprint.js +11 -0
  130. package/src/core/context-compiler/policy.js +13 -0
  131. package/src/core/context-compiler/result.js +23 -0
  132. package/src/core/contract-bootstrap-recovery.js +655 -0
  133. package/src/core/contract-revision.js +210 -0
  134. package/src/core/decision/artifact.js +69 -0
  135. package/src/core/decision/benchmarks.js +103 -0
  136. package/src/core/decision/cache.js +27 -0
  137. package/src/core/decision/constants.js +58 -0
  138. package/src/core/decision/cutover.js +34 -0
  139. package/src/core/decision/engine.js +22 -0
  140. package/src/core/decision/errors.js +68 -0
  141. package/src/core/decision/events.js +101 -0
  142. package/src/core/decision/freshness.js +19 -0
  143. package/src/core/decision/normalizers/index.js +115 -0
  144. package/src/core/decision/policy.js +18 -0
  145. package/src/core/decision/projection.js +16 -0
  146. package/src/core/decision/question-registry.js +201 -0
  147. package/src/core/decision/request.js +26 -0
  148. package/src/core/decision/resolver.js +130 -0
  149. package/src/core/decision/result.js +58 -0
  150. package/src/core/decision/service.js +156 -0
  151. package/src/core/decision/state-builder.js +65 -0
  152. package/src/core/decision/task-bindings.js +30 -0
  153. package/src/core/decision/test-provider.js +32 -0
  154. package/src/core/decision/thresholds.js +15 -0
  155. package/src/core/error-codes.js +278 -0
  156. package/src/core/events.js +226 -57
  157. package/src/core/evidence-readiness.js +9 -0
  158. package/src/core/execution-prerequisites.js +14 -0
  159. package/src/core/execution-profile.js +63 -38
  160. package/src/core/gate-provenance.js +124 -0
  161. package/src/core/integration-invocation-policy.js +27 -4
  162. package/src/core/integration-resources.js +86 -61
  163. package/src/core/model-router/constants.js +10 -0
  164. package/src/core/model-router/policy.js +103 -0
  165. package/src/core/model-router/router.js +37 -0
  166. package/src/core/next-action-model.js +58 -0
  167. package/src/core/next-action-phases.js +130 -42
  168. package/src/core/next-action-refresh.js +43 -9
  169. package/src/core/next-action-review-phase.js +7 -2
  170. package/src/core/next-action.js +35 -7
  171. package/src/core/phase.js +128 -10
  172. package/src/core/preflight-consistency.js +23 -9
  173. package/src/core/preflight-loaders.js +37 -5
  174. package/src/core/protocol-info.js +65 -0
  175. package/src/core/protocol.js +20 -0
  176. package/src/core/reconcile-closure.js +128 -52
  177. package/src/core/recovery-history.js +1 -0
  178. package/src/core/resumability.js +154 -44
  179. package/src/core/route-artifact.js +15 -1
  180. package/src/core/router.js +67 -1
  181. package/src/core/runtime-context.js +118 -61
  182. package/src/core/schema-validation.js +3 -0
  183. package/src/core/security-review/constants.js +64 -0
  184. package/src/core/security-review/normalize.js +245 -0
  185. package/src/core/security-review/provider.js +204 -0
  186. package/src/core/security-review/service.js +134 -0
  187. package/src/core/semantic-planning/constants.js +19 -0
  188. package/src/core/semantic-planning/projection.js +94 -0
  189. package/src/core/semantic-planning/service.js +15 -0
  190. package/src/core/sources.js +37 -0
  191. package/src/core/task-claim-state.js +201 -1
  192. package/src/core/task-conflict-inspection.js +31 -5
  193. package/src/core/task-paths.js +13 -0
  194. package/src/core/task-recovery.js +1 -0
  195. package/src/core/templates.js +3 -0
  196. package/src/core/test-intelligence/benchmarks.js +68 -0
  197. package/src/core/test-intelligence/inventory.js +73 -0
  198. package/src/core/test-intelligence/prune.js +90 -0
  199. package/src/core/test-intelligence/semantic-state.js +15 -0
  200. package/src/core/test-intelligence/service.js +40 -0
  201. package/src/core/test-intelligence/utility.js +50 -0
  202. package/src/core/trace.js +11 -7
  203. package/src/core/transaction.js +1 -0
  204. package/src/integration.d.ts +492 -0
  205. package/src/integration.js +54 -0
  206. package/src/providers/README.md +47 -0
  207. package/src/providers/capabilities.js +46 -0
  208. package/src/providers/errors.js +15 -0
  209. package/src/providers/index.js +29 -0
  210. package/src/providers/json-snapshot.js +105 -0
  211. package/src/providers/registry.js +152 -0
@@ -44,6 +44,8 @@ All artifact schemas are defined in `schemas/*.schema.json`. Persisted artifact
44
44
  | `task-state/<task-key>/attestations/code-manifest.json` | `code-manifest` | Protocol Generated | Immutable Once Written | Content Integrity Snapshot |
45
45
  | `task-state/<task-key>/attestations/statement.json` | `in-toto-statement` | Protocol Compiled | Immutable Once Written | Code Attestation Statement |
46
46
  | `task-state/<task-key>/attestations/statement.sigstore.json` | `null` | External Signing Provider | External Immutable | External Signature Bundle |
47
+ | `task-state/<task-key>/decisions/<decision-id>.json` | `semantic-decision` | Protocol Compiled | Immutable Once Written | Semantic Decision |
48
+ | `task-state/<task-key>/test-utility.json` | `test-utility` | Protocol Compiled | Overwritten On Analysis | Non Evidence Test Analysis |
47
49
 
48
50
  <!-- END FORGELOOP GENERATED: artifact-registry -->
49
51
 
@@ -51,6 +53,99 @@ All artifact schemas are defined in `schemas/*.schema.json`. Persisted artifact
51
53
 
52
54
  ## 2. Canonical Artifact Specifications
53
55
 
56
+ ### 2.0 `semantic-decision`
57
+
58
+ <!-- forgeloop-doc: schema=semantic-decision artifact=.forgeloop/task-state/<task-key>/decisions/<decision-id>.json -->
59
+
60
+ Semantic decisions are advisory, fingerprint-bound projections. They do not
61
+ authorize lifecycle transitions, evidence, ownership, installation, or
62
+ completion.
63
+
64
+ <!-- BEGIN FORGELOOP GENERATED: schema:semantic-decision -->
65
+
66
+ - `schemaVersion` *(number, required, const: 1)*
67
+ - `protocolVersion` *(number, required, const: 1)*
68
+ - `taskId` *(string, required, minLength: 1)*
69
+ - `decisionId` *(string, required, pattern: `^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$`)*
70
+ - `decisionKind` *(string, required, minLength: 1)*
71
+ - `engine` *(string, required, const: `typesafe-jev`)*
72
+ - `model` *(string, required, const: `jev-1.13.0`)*
73
+ - `questionSetId` *(string, required, minLength: 1)*
74
+ - `questionSetVersion` *(integer, required, minimum: 1)*
75
+ - `questionSetFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
76
+ - `questionSet` *(object, optional)*
77
+ - `id` *(string, required, minLength: 1)*
78
+ - `version` *(integer, required, minimum: 1)*
79
+ - `decisionKind` *(string, required, minLength: 1)*
80
+ - `questions` *(object, required)*
81
+ - `fingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
82
+ - `candidateIds` *(array<string>, optional)*
83
+ - `metadata` *(object, optional)*
84
+ - `policyVersion` *(number, required, const: 1)*
85
+ - `stateFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
86
+ - `taskStateFingerprint` *(string or null, optional)*
87
+ - `semanticStateFingerprint` *(string or null, optional)*
88
+ - `policyFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
89
+ - `repositoryFingerprint` *(string or object or null, optional)*
90
+ - `contractFingerprint` *(string or null, optional)*
91
+ - `routeFingerprint` *(string or null, optional)*
92
+ - `verificationCycle` *(integer or null, optional)*
93
+ - `candidateSetFingerprint` *(string or null, optional)*
94
+ - `answers` *(object, required)*
95
+ - `confidence` *(object, required)*
96
+ - `decision` *(object, required)*
97
+ - `usage` *(object, required)*
98
+ - `inputTokens` *(integer or null, required)*
99
+ - `outputTokens` *(integer or null, required)*
100
+ - `reportedBy` *(string, required, enum: `PROVIDER`, `HOST`, `UNKNOWN`)*
101
+ - `latencyMs` *(integer or null, optional)*
102
+ - `authority` *(string, required, const: `SEMANTIC_DECISION`)*
103
+ - `evidenceAuthority` *(string, required, const: `NONE`)*
104
+ - `lifecycleAuthority` *(boolean, required, const: false)*
105
+ - `completionAuthority` *(boolean, required, const: false)*
106
+ - `ownershipAuthority` *(boolean, required, const: false)*
107
+ - `installationAuthority` *(boolean, required, const: false)*
108
+ - `recordedAt` *(string, required, minLength: 1)*
109
+
110
+ <!-- END FORGELOOP GENERATED: schema:semantic-decision -->
111
+
112
+ ### 2.0.1 `test-utility`
113
+
114
+ <!-- forgeloop-doc: schema=test-utility artifact=.forgeloop/task-state/<task-key>/test-utility.json -->
115
+
116
+ Non-evidence test inventory and utility analysis. It never authorizes deletion
117
+ or completion.
118
+
119
+ <!-- BEGIN FORGELOOP GENERATED: schema:test-utility -->
120
+
121
+ - `schemaVersion` *(number, required, const: 1)*
122
+ - `protocolVersion` *(number, required, const: 1)*
123
+ - `taskId` *(string, required, minLength: 1)*
124
+ - `generatedAt` *(string, required, minLength: 1)*
125
+ - `inventoryFingerprint` *(string, required, pattern: `^[a-f0-9]{64}$`)*
126
+ - `semanticStatus` *(string, required, enum: `PROVIDER_REPORTED`, `UNAVAILABLE`, `NOT_REQUESTED`)*
127
+ - `decisionId` *(string, optional, pattern: `^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$`)*
128
+ - `semanticDecisionFingerprint` *(string, optional, pattern: `^[a-f0-9]{64}$`)*
129
+ - `decisionIds` *(array<string>, optional)*
130
+ - `semanticDecisionFingerprints` *(array<string>, optional)*
131
+ - `tests` *(array<object>, required)*
132
+ - `testId` *(string, required, pattern: `^test-[a-f0-9]{24}$`)*
133
+ - `file` *(string, required, minLength: 1)*
134
+ - `framework` *(string, required, minLength: 1)*
135
+ - `suite` *(string, optional)*
136
+ - `name` *(string, required, minLength: 1)*
137
+ - `line` *(integer, optional, minimum: 1)*
138
+ - `sourceSummary` *(string, optional)*
139
+ - `targets` *(array<string>, optional)*
140
+ - `runtimeMs` *(number,null, optional, minimum: 0)*
141
+ - `uniqueBranches` *(integer,null, optional, minimum: 0)*
142
+ - `classification` *(string, required, enum: `KEEP_REQUIRED`, `KEEP_UNIQUE`, `KEEP_RISK_GUARD`, `KEEP_AUTHORITY_BOUNDARY`, `KEEP_RECOVERY_INVARIANT`, `KEEP_RELEASE_SMOKE`, `KEEP_MIGRATION_COMPATIBILITY`, `KEEP_PLATFORM_BEHAVIOR`, `KEEP_DOCUMENTATION_VALUE`, `KEEP_INTEGRATION_GUARD`, `OBSOLETE_CANDIDATE`, `FLAKY_LOW_SIGNAL`, `EXPENSIVE_LOW_SIGNAL`, `UNKNOWN`, `REDUNDANT_CANDIDATE`)*
143
+ - `recommendation` *(string, required, enum: `KEEP`, `REWRITE`, `PROBE_REMOVAL`, `BLOCKED`, `REVIEW`)*
144
+ - `protected` *(boolean, required)*
145
+ - `signals` *(object, optional)*
146
+
147
+ <!-- END FORGELOOP GENERATED: schema:test-utility -->
148
+
54
149
  ### 2.1 `task-state/<taskKey>/contract.json`
55
150
 
56
151
  <!-- forgeloop-doc: schema=current-contract artifact=.forgeloop/task-state/<task-key>/contract.json -->
@@ -178,6 +273,11 @@ Readiness attestation evaluated prior to implementation.
178
273
 
179
274
  Discovered repository facts, platforms, runtimes, and dependencies.
180
275
 
276
+ Built-in `contract-preset:documentation`, `contract-preset:bug`,
277
+ `contract-preset:feature`, and `contract-preset:release` references are
278
+ ForgeLoop-owned provenance and do not require an entry in this registry. Every
279
+ other contract source reference still requires a valid registry entry.
280
+
181
281
  #### Canonical Fields
182
282
 
183
283
  <!-- BEGIN FORGELOOP GENERATED: schema:source-registry -->
@@ -252,6 +352,14 @@ Local ForgeLoop configuration settings and policy bindings.
252
352
  - `policy` *(string, optional, minLength: 1)*
253
353
  - `requiredGates` *(array<string>, optional)*
254
354
  - `requiredEvidence` *(array<string>, optional)*
355
+ - `decisionEngine` *(object, optional)*
356
+ - `required` *(boolean, required, const: true)*
357
+ - `provider` *(string, required, const: `typesafe-jev`)*
358
+ - `model` *(string, required, const: `jev-1.13.0`)*
359
+ - `policyVersion` *(number, required, const: 1)*
360
+ - `requestTimeoutMs` *(integer, required, minimum: 500, maximum: 60000)*
361
+ - `maxRetries` *(integer, required, minimum: 0, maximum: 3)*
362
+ - `cache` *(boolean, required)*
255
363
  - `structuralQuality` *(object, optional)*
256
364
  - `mode` *(string, optional, enum: `off`, `observe`, `gate`)*
257
365
  - `provider` *(string, optional, pattern: `^[a-z][a-z0-9-]{0,63}$`)*
@@ -304,6 +412,21 @@ Local ForgeLoop configuration settings and policy bindings.
304
412
 
305
413
  Pre-implementation gate approval artifact recording decisions, bound artifact hashes, and evidence.
306
414
 
415
+ Use `node src/cli.js gate-record` to create or replace this artifact. The
416
+ command computes SHA-256 values from project-relative regular files; callers
417
+ must not provide digests or edit gate JSON manually. Preflight checks these
418
+ hashes for staleness, and gate mutation is available only before execution.
419
+ Caller-recorded evidence is descriptive local input, not host attestation,
420
+ ForgeLoop execution evidence, or remote authority.
421
+
422
+ `requiredBy` records only the provenance that actually requires the gate:
423
+ guides whose metadata declares it, plus the stable `config.requiredGates`
424
+ marker when `config.requiredGates` requires it. Programmatic gate-record
425
+ inputs are bounded (32 repeatable entries, 2000-character strings, 4 MiB
426
+ per bound artifact, 64 KiB per evidence file) and refuse stale routes when
427
+ the persisted route, work state, or current contract fingerprints no longer
428
+ agree, before any gate is written.
429
+
307
430
  #### Canonical Fields
308
431
 
309
432
  <!-- BEGIN FORGELOOP GENERATED: schema:gate -->
@@ -0,0 +1,46 @@
1
+ # Audit UX read model
2
+
3
+ `task/audit-view` is a bounded, read-only Integration API resource for audit
4
+ and operator interfaces. It composes canonical ForgeLoop projections; it does
5
+ not become a second lifecycle, evidence, ownership, or completion authority.
6
+
7
+ ```js
8
+ import { readForgeLoopIntegrationResource } from "@cassiomc1/forgeloop/integration";
9
+
10
+ const view = await readForgeLoopIntegrationResource("task/audit-view", {
11
+ taskId: "task-1",
12
+ limit: 50,
13
+ categories: ["LIFECYCLE", "CHECK", "DIAGNOSTIC"],
14
+ });
15
+ ```
16
+
17
+ The projection includes lifecycle and health; a deterministic sequence-backed
18
+ timeline with explicit `null` timestamps when the ledger has no authoritative
19
+ timestamp; bounded checks, attempts, diagnostics, approvals, durable-action
20
+ summaries, recovery history, completion status, and canonical ownership; and
21
+ integrity and reason-code summaries that remain fail-closed when source
22
+ projections are inconsistent.
23
+
24
+ Timeline pagination accepts `limit`, `beforeSequence`, `afterSequence`, and a
25
+ bounded category allowlist. Without a cursor, the latest bounded page is
26
+ returned. `beforeSequence` performs backward pagination and returns the
27
+ nearest earlier matching events; its `nextBeforeSequence` cursor is the first
28
+ returned sequence when another page exists. `afterSequence` performs forward
29
+ pagination and returns the earliest later matching events; its
30
+ `nextAfterSequence` cursor is the last returned sequence when another page
31
+ exists. Pages never skip matching sequence numbers within the filtered event
32
+ stream, and combining the two cursors is rejected.
33
+
34
+ The projection redacts general POSIX (including single-segment), Windows, UNC,
35
+ and local `file://` absolute paths; environment assignments; common credential
36
+ assignments; authorization headers; complete `Cookie` and `Set-Cookie` header
37
+ values; and URL userinfo credentials. It does not return raw event payloads,
38
+ commands, or provider output. These are presentation-boundary redactions, not a
39
+ replacement for secret-handling controls at the source. The resource never
40
+ invokes a provider, executes a command, writes an artifact, changes lifecycle
41
+ state, or releases claims.
42
+
43
+ `auditUx` is advertised during capability discovery with version `1` and
44
+ `readOnly: true`. Hosts must use the canonical CLI/API lifecycle commands for
45
+ all mutations and must treat this view as presentation and diagnostic context
46
+ only.
@@ -0,0 +1,136 @@
1
+ # Browser Verification
2
+
3
+ ## Status
4
+
5
+ Browser verification is a provider-neutral, host-injected v1 observation
6
+ contract. It is experimental and explicit. ForgeLoop does not select a browser
7
+ vendor, install a browser, or invoke verification from lifecycle commands.
8
+
9
+ ## Purpose and Architecture
10
+
11
+ `runBrowserVerification` validates a bounded request, resolves one registered
12
+ provider, and turns its untrusted observation into an immutable result. Core
13
+ does not perform browser I/O. The runtime registry is inert at context
14
+ construction; factories are lazy and are invoked only by the explicit API call.
15
+
16
+ ## Invocation
17
+
18
+ Provide an explicit task, target, requirement, and verification identity along
19
+ with `runtimeContext.browserVerificationProviders`:
20
+
21
+ ```js
22
+ const result = await runBrowserVerification({
23
+ taskId: "task-123",
24
+ target: "/workspace/project",
25
+ providerName: "playwright",
26
+ verificationId: "checkout",
27
+ requirement: "Checkout is usable",
28
+ startUrl: "https://app.example.test/checkout",
29
+ allowedOrigins: ["https://app.example.test"],
30
+ steps: [{ id: "open", kind: "NAVIGATE", url: "https://app.example.test/checkout" }],
31
+ assertions: [{ id: "title", kind: "TITLE_EQUALS", expected: "Checkout" }],
32
+ runtimeContext: { browserVerificationProviders: { playwright: provider } },
33
+ });
34
+ ```
35
+
36
+ Providers are registered by ID and must expose `verify(input)`. Factories are
37
+ lazy and are resolved only when the explicit invocation runs. Provider input
38
+ contains the normalized request, `signal`, and remaining `timeoutMs`. The
39
+ `AbortSignal` is an invocation control, not protocol state.
40
+
41
+ ## Request Model
42
+
43
+ Requests require `taskId`, `target` (or `projectPath`), `verificationId`,
44
+ `requirement`, `startUrl`, `allowedOrigins`, at least one bounded step, and at
45
+ least one bounded assertion. Optional viewport, screenshot capture policy, and
46
+ timeout values are bounded. Unknown request, step, locator, assertion, capture,
47
+ or viewport fields are rejected. Arbitrary scripts, headers, cookies, uploads,
48
+ downloads, shell commands, and executable paths are not part of this contract.
49
+
50
+ Supported steps are `NAVIGATE`, `CLICK`, `FILL`, `PRESS`, and `WAIT_FOR`.
51
+ Supported assertions include visibility, text, value, attribute, URL, title,
52
+ and their documented bounded variants. Assertion results must match the
53
+ requested IDs, kinds, cardinality, and order exactly.
54
+
55
+ `WAIT_FOR` is strict: visibility, hidden-state, and text waits require a
56
+ locator; text and URL waits require an expected value, and URL wait values must
57
+ also be in the exact origin allowlist.
58
+
59
+ ## Origins and Navigation
60
+
61
+ Authored URLs and provider-reported `finalUrl` and `navigations` must use
62
+ `http:` or `https:`, contain no credentials, and have an exact origin in
63
+ `allowedOrigins`. Hostnames are case-normalized and trailing-dot hostnames are
64
+ rejected. `localhost` and IPv4 origins are supported; bracketed IPv6 literals
65
+ are intentionally excluded in v1. The allowlist is an observation policy, not
66
+ a network sandbox: providers remain responsible for browser network access.
67
+
68
+ ## Result Model
69
+
70
+ The normalized result contains task and requirement binding, provider identity,
71
+ assertions, final navigation state, diagnostics, optional accessibility
72
+ snapshots, and structured screenshot metadata. Raw image bytes are never
73
+ returned. Artifact references are portable, bounded, credential-free metadata
74
+ with a lowercase SHA-256 digest.
75
+
76
+ ForgeLoop derives overall status: any `FAIL` assertion yields `FAIL`, otherwise
77
+ any `BLOCKED` yields `BLOCKED`, otherwise all assertions yield `PASS`. A raw
78
+ provider status is optional and, when present, must match that derived value.
79
+ Provider output cannot choose lifecycle state, evidence, completion, claims, or
80
+ next actions. Unknown top-level fields and authority-bearing fields fail closed.
81
+
82
+ Snapshots are optional explicit `ACCESSIBILITY` observations with bounded
83
+ portable text. They are never assertion status or authority.
84
+
85
+ ## Timeout and Cancellation
86
+
87
+ Factory resolution, provider validation, provider verification, and result
88
+ normalization share one ForgeLoop-owned deadline. On expiry ForgeLoop aborts
89
+ the shared signal, allows only bounded cooperative cleanup, and returns
90
+ `E_BROWSER_VERIFICATION_TIMEOUT`. Late provider resolution cannot change the
91
+ returned result. Providers must observe the signal and clean up resources they
92
+ own; synchronous JavaScript cannot be forcibly preempted.
93
+
94
+ ## Trust Boundary and Credentials
95
+
96
+ Provider output is untrusted and normalized under strict size limits. Results
97
+ are stamped with `authority: "OBSERVATION"`, `evidenceAuthority: "NONE"`,
98
+ `actionability: "NON_EXECUTABLE"`, `lifecycleAuthority: false`, and
99
+ `completionAuthority: false`. Provider output cannot substitute for ForgeLoop
100
+ validation or lifecycle evidence.
101
+
102
+ Provider errors are mapped to generic, secret-safe public errors. Raw causes,
103
+ stacks, stderr, cookies, tokens, signed URLs, and local paths are not public
104
+ metadata. Credentials must not be placed in requests, URLs, artifacts,
105
+ diagnostics, or snapshots.
106
+
107
+ ## Evidence Boundary
108
+
109
+ Results are observation-only: `persisted: false`, `evidenceAuthority: "NONE"`,
110
+ `completionAuthority: false`, and `evidenceRequiresForgeLoopValidation: true`.
111
+ Running this API does not mutate tasks, claims, routes, contracts, events,
112
+ receipts, checks, evidence, recovery, or actions.
113
+
114
+ ## Network and Session Semantics
115
+
116
+ The origin allowlist does not provide browser isolation or prevent provider
117
+ network access. Providers own browser sessions and must not reuse credentials
118
+ or session state across unrelated invocations. No automatic browser install,
119
+ executable discovery, browser adapter, or auto-invocation is provided.
120
+
121
+ ## Future Adapters and Troubleshooting
122
+
123
+ The optional Agent Browser adapter implements this provider contract through
124
+ `createAgentBrowserVerificationProvider`. It requires a host-supplied absolute
125
+ executable and never installs Agent Browser or Chrome. No vendor is canonical,
126
+ and no lifecycle command invokes the adapter. See
127
+ [`AGENT_BROWSER_ADAPTER.md`](./AGENT_BROWSER_ADAPTER.md) for its process,
128
+ session, screenshot, and troubleshooting boundaries. For malformed requests,
129
+ invalid results, origin escapes, provider failures, and timeouts, use the
130
+ stable error codes in `docs/TROUBLESHOOTING.md`.
131
+
132
+ ## Compatibility
133
+
134
+ The canonical public operation is `runBrowserVerification`. The runtime
135
+ registration key remains `browserVerificationProviders`, and the provider kind
136
+ remains `BROWSER_VERIFICATION`.