opencode-wait-a-minute 0.0.0-stage → 1.1.0-rc.8

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 (207) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +318 -2
  3. package/index.js +1836 -0
  4. package/package.json +70 -4
  5. package/skills/codebase-design/SKILL.md +114 -0
  6. package/skills/design-contract/SKILL.md +27 -0
  7. package/skills/design-critique/SKILL.md +19 -0
  8. package/skills/design-system/SKILL.md +17 -0
  9. package/skills/design-system/references/image-analysis.md +14 -0
  10. package/skills/design-system/references/tokens.md +32 -0
  11. package/skills/design-system/references/ui-rules.md +14 -0
  12. package/skills/diagnosing-bugs/SKILL.md +138 -0
  13. package/skills/frontend-design/SKILL.md +36 -0
  14. package/skills/handoff/SKILL.md +16 -0
  15. package/skills/improve-codebase-architecture/SKILL.md +71 -0
  16. package/skills/linter-negative/SKILL.md +74 -0
  17. package/skills/no-slop-ui/SKILL.md +26 -0
  18. package/skills/prototype/SKILL.md +26 -0
  19. package/skills/registry.json +44087 -0
  20. package/skills/tastemaker/SKILL.md +8 -0
  21. package/skills/tastemaker/references/tastemaker.md +14 -0
  22. package/skills/tdd/SKILL.md +38 -0
  23. package/skills/visual-review/SKILL.md +103 -0
  24. package/skills/visual-review/references/review-gates.md +42 -0
  25. package/skills/visual-review/references/surface-archetypes.md +37 -0
  26. package/skills/wizard/SKILL.md +44 -0
  27. package/skills/writing-for-agents/SKILL.md +81 -0
  28. package/src/cognition/cognition-store.js +251 -0
  29. package/src/cognition/cognitive-state.js +126 -0
  30. package/src/cognition/hypothesis-manager.js +113 -0
  31. package/src/cognition/observation-engine.js +112 -0
  32. package/src/cognition/observation-provenance.js +268 -0
  33. package/src/context/active-context-boundary.js +68 -0
  34. package/src/context/assembly.js +494 -0
  35. package/src/context/assessment-rules.js +55 -0
  36. package/src/context/capsule-staleness.js +267 -0
  37. package/src/context/capsules.js +2 -0
  38. package/src/context/compare-array.js +98 -0
  39. package/src/context/compare-object.js +89 -0
  40. package/src/context/compare-values.js +42 -0
  41. package/src/context/context-assembly-contract.js +71 -0
  42. package/src/context/context-budget-manager.js +232 -0
  43. package/src/context/context-builder.js +49 -0
  44. package/src/context/context-cache.js +55 -0
  45. package/src/context/context-capture.js +243 -0
  46. package/src/context/context-classification.js +199 -0
  47. package/src/context/context-compaction.js +179 -0
  48. package/src/context/context-decision-audit.js +267 -0
  49. package/src/context/context-demotion.js +173 -0
  50. package/src/context/context-dictionary.js +106 -0
  51. package/src/context/context-drift-detection.js +225 -0
  52. package/src/context/context-evaluation.js +374 -0
  53. package/src/context/context-event-ingress.js +100 -0
  54. package/src/context/context-event-normalization.js +224 -0
  55. package/src/context/context-feedback-loop.js +216 -0
  56. package/src/context/context-freshness.js +21 -0
  57. package/src/context/context-graph-builder.js +71 -0
  58. package/src/context/context-graph.js +451 -0
  59. package/src/context/context-history-relevance.js +321 -0
  60. package/src/context/context-interception.js +145 -0
  61. package/src/context/context-invalidation-events.js +154 -0
  62. package/src/context/context-lifecycle.js +170 -0
  63. package/src/context/context-loop-prevention.js +347 -0
  64. package/src/context/context-manager.js +340 -0
  65. package/src/context/context-memory-layers.js +265 -0
  66. package/src/context/context-minimality.js +166 -0
  67. package/src/context/context-normalization.js +130 -0
  68. package/src/context/context-optimization-metrics.js +434 -0
  69. package/src/context/context-output-policy.js +135 -0
  70. package/src/context/context-pack-authority.js +157 -0
  71. package/src/context/context-promotion.js +172 -0
  72. package/src/context/context-query-contract.js +101 -0
  73. package/src/context/context-ranking.js +164 -0
  74. package/src/context/context-rate-distortion.js +261 -0
  75. package/src/context/context-recovery.js +209 -0
  76. package/src/context/context-retrieval-integration.js +60 -0
  77. package/src/context/context-retrieval.js +93 -0
  78. package/src/context/context-router.js +457 -0
  79. package/src/context/context-routing-evaluation.js +331 -0
  80. package/src/context/context-routing-observability.js +296 -0
  81. package/src/context/context-routing-shadow.js +237 -0
  82. package/src/context/context-scope.js +181 -0
  83. package/src/context/context-snapshot.js +226 -0
  84. package/src/context/context-source-registry.js +95 -0
  85. package/src/context/context-sufficiency-gate.js +120 -0
  86. package/src/context/context-sufficiency-oracle.js +167 -0
  87. package/src/context/context-telemetry.js +176 -0
  88. package/src/context/context.js +633 -0
  89. package/src/context/dependency-closure.js +246 -0
  90. package/src/context/page-fault-tracker.js +275 -0
  91. package/src/context/prompt-engine.js +74 -0
  92. package/src/context/runtime-context-graph.js +260 -0
  93. package/src/context/selection.js +2 -0
  94. package/src/context/session.js +2 -0
  95. package/src/context/sufficiency-contract.js +300 -0
  96. package/src/context/tokenizer.js +17 -0
  97. package/src/context-benchmark-router.mjs +125 -0
  98. package/src/evidence/evidence-engine.js +161 -0
  99. package/src/evidence/evidence-factory.js +3 -0
  100. package/src/evidence/evidence-freshness.js +463 -0
  101. package/src/evidence/evidence-gap.js +76 -0
  102. package/src/evidence/evidence-lineage.js +525 -0
  103. package/src/evidence/evidence.js +136 -0
  104. package/src/evidence/freshness-validation.js +187 -0
  105. package/src/evidence/lineage.js +4 -0
  106. package/src/execution/action-evaluation.js +179 -0
  107. package/src/execution/circuit-breaker.js +70 -0
  108. package/src/execution/claim-interception.js +63 -0
  109. package/src/execution/execution-engine.js +258 -0
  110. package/src/execution/execution-intent.js +69 -0
  111. package/src/execution/execution-state.js +89 -0
  112. package/src/execution/formatting.js +60 -0
  113. package/src/execution/l1-sanitize.js +16 -0
  114. package/src/execution/l2-resource-guards.js +19 -0
  115. package/src/execution/l3-invariant-checker.js +5 -0
  116. package/src/execution/l4-containment.js +6 -0
  117. package/src/execution/runtime-guards.js +106 -0
  118. package/src/execution/strategy-identity.js +162 -0
  119. package/src/execution/tool-interceptor.js +7 -0
  120. package/src/execution/tool-result-classifier.js +63 -0
  121. package/src/integration/canary-deploy.js +143 -0
  122. package/src/integration/collector.js +59 -0
  123. package/src/integration/error-recovery.js +6 -0
  124. package/src/integration/event-bus.js +66 -0
  125. package/src/integration/health-checker.js +57 -0
  126. package/src/integration/logger.js +39 -0
  127. package/src/integration/message-handler.js +611 -0
  128. package/src/integration/opencode-db.js +153 -0
  129. package/src/integration/orchestration.js +419 -0
  130. package/src/integration/part-provenance.js +65 -0
  131. package/src/integration/rate-limiter.js +55 -0
  132. package/src/integration/release-gate.js +336 -0
  133. package/src/integration/rollback-manager.js +164 -0
  134. package/src/integration/router-adapter.js +269 -0
  135. package/src/integration/telemetry.js +45 -0
  136. package/src/integration/update-checker.js +10 -0
  137. package/src/persistence/event-sourcing.js +75 -0
  138. package/src/persistence/memory.js +501 -0
  139. package/src/persistence/migration-runner.js +16 -0
  140. package/src/persistence/persistence-manager.js +39 -0
  141. package/src/persistence/transaction-log.js +157 -0
  142. package/src/policy/action-capabilities.js +116 -0
  143. package/src/policy/action-policy.js +4 -0
  144. package/src/policy/assessment-engine.js +104 -0
  145. package/src/policy/assumption-tracking.js +66 -0
  146. package/src/policy/budget-enforcer.js +7 -0
  147. package/src/policy/config-validator.js +102 -0
  148. package/src/policy/execution-assessment.js +142 -0
  149. package/src/policy/failure-classification.js +5 -0
  150. package/src/policy/feature-flags.js +65 -0
  151. package/src/policy/governance-enforcement.js +118 -0
  152. package/src/policy/locale.js +15 -0
  153. package/src/policy/multi-signer.js +151 -0
  154. package/src/policy/policy-state-machine.js +97 -0
  155. package/src/policy/ponytail-constraint.js +38 -0
  156. package/src/policy/project-inspector.js +93 -0
  157. package/src/policy/query-builder.js +14 -0
  158. package/src/policy/request-classifier.js +79 -0
  159. package/src/policy/risk-engine.js +266 -0
  160. package/src/policy/scope-enforcement.js +140 -0
  161. package/src/policy/secret-scanner.js +68 -0
  162. package/src/policy/skill-routing.js +104 -0
  163. package/src/policy/strategy-capabilities.js +211 -0
  164. package/src/policy/strategy.js +6 -0
  165. package/src/policy/uncertainty.js +117 -0
  166. package/src/shared/container.js +44 -0
  167. package/src/shared/decision-types.js +24 -0
  168. package/src/shared/simple-test.js +160 -0
  169. package/src/shared/wam-events.js +52 -0
  170. package/src/skills/engine.js +1705 -0
  171. package/src/skills/skill-registry.js +19 -0
  172. package/src/skills/skill-routing.js +340 -0
  173. package/src/state/lifecycle-manager.js +113 -0
  174. package/src/state/operational-state.js +198 -0
  175. package/src/state/projections.js +47 -0
  176. package/src/state/replay-engine.js +5 -0
  177. package/src/state/requirement-ownership.js +20 -0
  178. package/src/state/requirement-state.js +152 -0
  179. package/src/state/run-event-identity.js +172 -0
  180. package/src/state/state-engine.js +19 -0
  181. package/src/state/state-machine.js +119 -0
  182. package/src/state/state-schema.js +318 -0
  183. package/src/state/state-store.js +335 -0
  184. package/src/state/state-transition.js +84 -0
  185. package/src/state/task-dependencies.js +287 -0
  186. package/src/state/task-execution.js +217 -0
  187. package/src/state/task-lifecycle.js +59 -0
  188. package/src/state/task-runs.js +361 -0
  189. package/src/state/task-state-file.js +86 -0
  190. package/src/state/task-state.js +41 -0
  191. package/src/state/task-status.js +54 -0
  192. package/src/state/task-store.js +48 -0
  193. package/src/state/wam-state.js +148 -0
  194. package/src/verification/completion-gate-simple.js +8 -0
  195. package/src/verification/completion-gate.js +183 -0
  196. package/src/verification/contract.js +9 -0
  197. package/src/verification/contradiction-resolution.js +255 -0
  198. package/src/verification/diagnostic-engine.js +659 -0
  199. package/src/verification/false-completion-prevention.js +100 -0
  200. package/src/verification/hook-validator.js +6 -0
  201. package/src/verification/requirements.js +6 -0
  202. package/src/verification/verification-context.js +162 -0
  203. package/src/verification/verification-lifecycle.js +66 -0
  204. package/src/verification/verification-model.js +89 -0
  205. package/src/verification/verification-persistence.js +129 -0
  206. package/src/verification/verification-policy.js +127 -0
  207. package/src/verification/verification.js +415 -0
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Context Freshness Validation — derives verification from evidence lineage.
3
+ *
4
+ * The Context Graph should NOT be a second source of truth for
5
+ * epistemological state. It should derive it from Evidence Lineage.
6
+ *
7
+ * Rule: `verified` on a ContextNode cannot survive invalidated
8
+ * supporting evidence. Validity must be resolved from lineage/provenance.
9
+ */
10
+
11
+ /**
12
+ * @typedef {Object} FreshnessResult
13
+ * @property {string} nodeId
14
+ * @property {boolean} effectiveVerified
15
+ * @property {string} reason
16
+ * @property {string} derivedFrom
17
+ * @property {number} derivedAt
18
+ */
19
+
20
+ /**
21
+ * @typedef {Object} EvidenceStatus
22
+ * @property {string} id
23
+ * @property {string} status - "valid" | "superseded" | "invalidated" | "unverified"
24
+ * @property {number} updatedAt
25
+ */
26
+
27
+ /**
28
+ * Derive effective verification status for a node.
29
+ *
30
+ * A node is effectively verified only if:
31
+ * 1. It is marked as verified in the graph
32
+ * 2. ALL supporting evidence is valid (not invalidated)
33
+ *
34
+ * @param {Object} node - Context node
35
+ * @param {EvidenceStatus[]} supportingEvidence - Evidence that supports this node
36
+ * @returns {FreshnessResult}
37
+ */
38
+ export function deriveVerification(node, supportingEvidence = []) {
39
+ if (!node) {
40
+ return {
41
+ nodeId: null,
42
+ effectiveVerified: false,
43
+ reason: "node not found",
44
+ derivedFrom: "none",
45
+ derivedAt: Date.now(),
46
+ };
47
+ }
48
+
49
+ // If node is not verified, it's not verified
50
+ if (!node.verified) {
51
+ return {
52
+ nodeId: node.id,
53
+ effectiveVerified: false,
54
+ reason: "node not verified in graph",
55
+ derivedFrom: "graph",
56
+ derivedAt: Date.now(),
57
+ };
58
+ }
59
+
60
+ // Check if any supporting evidence is invalidated
61
+ const invalidated = supportingEvidence.filter((e) => e.status === "invalidated");
62
+ if (invalidated.length > 0) {
63
+ return {
64
+ nodeId: node.id,
65
+ effectiveVerified: false,
66
+ reason: `${invalidated.length} supporting evidence invalidated`,
67
+ derivedFrom: "evidence-lineage",
68
+ derivedAt: Date.now(),
69
+ };
70
+ }
71
+
72
+ // Check if all supporting evidence is superseded
73
+ const superseded = supportingEvidence.filter((e) => e.status === "superseded");
74
+ if (superseded.length > 0 && superseded.length === supportingEvidence.length) {
75
+ return {
76
+ nodeId: node.id,
77
+ effectiveVerified: false,
78
+ reason: "all supporting evidence superseded",
79
+ derivedFrom: "evidence-lineage",
80
+ derivedAt: Date.now(),
81
+ };
82
+ }
83
+
84
+ // Check if there's any valid evidence
85
+ const valid = supportingEvidence.filter((e) => e.status === "valid");
86
+ if (supportingEvidence.length > 0 && valid.length === 0) {
87
+ return {
88
+ nodeId: node.id,
89
+ effectiveVerified: false,
90
+ reason: "no valid supporting evidence",
91
+ derivedFrom: "evidence-lineage",
92
+ derivedAt: Date.now(),
93
+ };
94
+ }
95
+
96
+ // Node is verified and has valid supporting evidence
97
+ return {
98
+ nodeId: node.id,
99
+ effectiveVerified: true,
100
+ reason: "verified with valid supporting evidence",
101
+ derivedFrom: "combined",
102
+ derivedAt: Date.now(),
103
+ };
104
+ }
105
+
106
+ /**
107
+ * Check if evidence invalidation affects graph nodes.
108
+ *
109
+ * @param {string} evidenceId - Invalidated evidence ID
110
+ * @param {Object} graph - Context graph
111
+ * @returns {string[]} Affected node IDs
112
+ */
113
+ export function findAffectedNodes(evidenceId, graph) {
114
+ const affected = [];
115
+
116
+ // Find all nodes that depend on this evidence
117
+ const edges = graph.getEdgesToByType
118
+ ? graph.getEdgesToByType(evidenceId, "supports")
119
+ : [];
120
+
121
+ for (const edge of edges) {
122
+ const node = graph.getNode(edge.from);
123
+ if (node && node.verified) {
124
+ affected.push(node.id);
125
+ }
126
+ }
127
+
128
+ return affected;
129
+ }
130
+
131
+ /**
132
+ * Mark graph nodes as stale when evidence is invalidated.
133
+ *
134
+ * @param {string} evidenceId - Invalidated evidence ID
135
+ * @param {Object} graph - Context graph
136
+ * @returns {string[]} Nodes that were marked stale
137
+ */
138
+ export function markStaleOnInvalidation(evidenceId, graph) {
139
+ const affected = findAffectedNodes(evidenceId, graph);
140
+
141
+ for (const nodeId of affected) {
142
+ const node = graph.getNode(nodeId);
143
+ if (node) {
144
+ node.verified = false;
145
+ node.metadata = node.metadata || {};
146
+ node.metadata.staleReason = `evidence ${evidenceId} invalidated`;
147
+ node.metadata.staleAt = Date.now();
148
+ }
149
+ }
150
+
151
+ return affected;
152
+ }
153
+
154
+ /**
155
+ * Generate freshness report for a set of nodes.
156
+ *
157
+ * @param {Object[]} nodes
158
+ * @param {Object} evidenceStore - Evidence lookup function
159
+ * @returns {Object} Freshness report
160
+ */
161
+ export function generateFreshnessReport(nodes, evidenceStore) {
162
+ const results = [];
163
+ let verified = 0;
164
+ let stale = 0;
165
+
166
+ for (const node of nodes) {
167
+ const evidence = evidenceStore?.getSupportingEvidence?.(node.id) || [];
168
+ const result = deriveVerification(node, evidence);
169
+ results.push(result);
170
+
171
+ if (result.effectiveVerified) {
172
+ verified++;
173
+ } else if (node.verified && !result.effectiveVerified) {
174
+ stale++;
175
+ }
176
+ }
177
+
178
+ return {
179
+ total: nodes.length,
180
+ verified,
181
+ stale,
182
+ unverified: nodes.length - verified - stale,
183
+ results,
184
+ };
185
+ }
186
+
187
+ export default deriveVerification;
@@ -0,0 +1,4 @@
1
+ export function createLineage(reqId, hypId, expId, obsId, evId) {
2
+ return { requirementId: reqId, hypothesisId: hypId, experimentId: expId, observationId: obsId, evidenceId: evId };
3
+ }
4
+ export function getLineage(evidenceId) { return null; }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Action Evaluation — Separation of action results, observations,
3
+ * requirement evaluation, and task verification.
4
+ *
5
+ * Core insight: ActionResult ≠ Observation ≠ RequirementEvaluation ≠ TaskVerification
6
+ * A tool succeeding does NOT mean its requirement is satisfied.
7
+ */
8
+
9
+ // -- ActionResult: directly from tool execution --
10
+
11
+ /**
12
+ * @typedef {Object} ActionResult
13
+ * @property {string} actionId
14
+ * @property {boolean} success
15
+ * @property {number} exitCode
16
+ * @property {string} output
17
+ * @property {number} durationMs
18
+ * @property {number} timestamp
19
+ */
20
+
21
+ /**
22
+ * Creates an ActionResult directly from tool execution metadata.
23
+ */
24
+ export function createActionResult({
25
+ actionId,
26
+ success,
27
+ exitCode,
28
+ output,
29
+ durationMs,
30
+ timestamp = Date.now(),
31
+ }) {
32
+ return { actionId, success, exitCode, output, durationMs, timestamp };
33
+ }
34
+
35
+ // -- Observation: interpretation of action result --
36
+
37
+ /**
38
+ * @typedef {Object} Observation
39
+ * @property {string} id
40
+ * @property {string} actionId
41
+ * @property {string} requirementId
42
+ * @property {string} observation
43
+ * @property {"direct" | "derived" | "inferred"} relevance
44
+ * @property {number} timestamp
45
+ */
46
+
47
+ /**
48
+ * Creates an Observation — an interpretation of what happened during execution.
49
+ */
50
+ export function createObservation({
51
+ actionId,
52
+ requirementId,
53
+ observation,
54
+ relevance = "direct",
55
+ }) {
56
+ return {
57
+ id: `obs-${actionId}-${Date.now().toString(36)}`,
58
+ actionId,
59
+ requirementId,
60
+ observation,
61
+ relevance,
62
+ timestamp: Date.now(),
63
+ };
64
+ }
65
+
66
+ // -- Requirement evaluation: mapping observation to requirement --
67
+
68
+ /**
69
+ * @typedef {Object} RequirementEvaluation
70
+ * @property {string} requirementId
71
+ * @property {string} observationId
72
+ * @property {"unknown" | "supports" | "contradicts" | "neutral"} evaluation
73
+ * @property {string} reason
74
+ * @property {number} timestamp
75
+ */
76
+
77
+ import { assessObservation, AssessmentResult } from "../policy/assessment-engine.js";
78
+ const EVALUATION_BY_RESULT = { [AssessmentResult.SUPPORTED]: "supports", [AssessmentResult.CONTRADICTED]: "contradicts", [AssessmentResult.INCONCLUSIVE]: "unknown" };
79
+ /**
80
+ * Evaluates an observation against a requirement.
81
+ * Returns an evaluation, NOT a status change. Delegates to assessment-engine.
82
+ */
83
+ export function evaluateObservationAgainst(observation, requirement) {
84
+ const expected = (requirement && (requirement.expectedObservation ?? requirement.description)) ?? undefined;
85
+ const actual = (observation && (observation.observation ?? observation.actual)) ?? undefined;
86
+ const assessment = assessObservation({ expectedObservation: expected }, actual);
87
+ const evaluation = EVALUATION_BY_RESULT[assessment.result] || "unknown";
88
+ const isNoExpected = assessment.reasoning === "No expectedObservation defined for this experiment.";
89
+ return { requirementId: observation.requirementId, observationId: observation.id, evaluation, reason: isNoExpected ? "" : assessment.reasoning || "", timestamp: Date.now(), assessment };
90
+ }
91
+
92
+ // -- Task verification: final result --
93
+
94
+ /**
95
+ * @typedef {Object} TaskVerification
96
+ * @property {string} taskId
97
+ * @property {boolean} verified
98
+ * @property {RequirementEvaluation[]} evaluations
99
+ * @property {string} summary
100
+ * @property {number} timestamp
101
+ */
102
+
103
+ /**
104
+ * Verifies a task by aggregating all requirement evaluations.
105
+ */
106
+ export function verifyTask({ taskId, evaluations, summary }) {
107
+ const verified =
108
+ evaluations.length > 0 &&
109
+ evaluations.every((e) => e.evaluation === "supports");
110
+ return {
111
+ taskId,
112
+ verified,
113
+ evaluations,
114
+ summary,
115
+ timestamp: Date.now(),
116
+ };
117
+ }
118
+
119
+ // -- Classic bug demonstrations --
120
+
121
+ /**
122
+ * Bug demo #1: Command succeeded ≠ Requirement satisfied.
123
+ * A command exiting with 0 does not prove the underlying requirement is met.
124
+ */
125
+ export function demoCommandSucceedsNotRequirementSatisfied() {
126
+ const actionResult = createActionResult({
127
+ actionId: "act-1",
128
+ success: true,
129
+ exitCode: 0,
130
+ output: "Chromium executable exists at /usr/bin/chromium",
131
+ durationMs: 12,
132
+ });
133
+
134
+ const observation = createObservation({
135
+ actionId: actionResult.actionId,
136
+ requirementId: "req-playwright-chromium",
137
+ observation: "Chromium executable exists",
138
+ relevance: "direct",
139
+ });
140
+
141
+ const requirement = {
142
+ id: "req-playwright-chromium",
143
+ description: "Playwright can launch required Chromium",
144
+ };
145
+
146
+ const evaluation = evaluateObservationAgainst(observation, requirement);
147
+
148
+ return { actionResult, observation, requirement, evaluation };
149
+ }
150
+
151
+ /**
152
+ * Bug demo #2: Tool output exists ≠ Requirement verified.
153
+ * Having output does not mean the requirement is actually satisfied.
154
+ */
155
+ export function demoToolOutputExistsNotRequirementVerified() {
156
+ const actionResult = createActionResult({
157
+ actionId: "act-2",
158
+ success: true,
159
+ exitCode: 0,
160
+ output: "npm install completed with 0 warnings",
161
+ durationMs: 4500,
162
+ });
163
+
164
+ const observation = createObservation({
165
+ actionId: actionResult.actionId,
166
+ requirementId: "req-deps-installed",
167
+ observation: "npm install completed",
168
+ relevance: "derived",
169
+ });
170
+
171
+ const requirement = {
172
+ id: "req-deps-installed",
173
+ description: "All runtime dependencies are installed and importable",
174
+ };
175
+
176
+ const evaluation = evaluateObservationAgainst(observation, requirement);
177
+
178
+ return { actionResult, observation, requirement, evaluation };
179
+ }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Circuit Breaker — fail-fast pattern for unreliable calls.
3
+ *
4
+ * States: "closed" (allow), "open" (reject fast), "half-open" (probe).
5
+ * After `threshold` consecutive failures the breaker opens; after
6
+ * `timeout` ms it transitions to half-open to allow one probe.
7
+ *
8
+ * Production hardening (M5-53).
9
+ */
10
+
11
+ /**
12
+ * @typedef {"closed"|"open"|"half-open"} BreakerState
13
+ */
14
+
15
+ /**
16
+ * @typedef {Object} CircuitBreaker
17
+ * @property {() => BreakerState} getState
18
+ * @property {<T>(fn: () => Promise<T>) => Promise<T>} execute
19
+ * @property {() => void} reset
20
+ * @property {() => number} failures
21
+ */
22
+
23
+ /**
24
+ * @param {{threshold?: number, timeout?: number}} opts
25
+ * @returns {CircuitBreaker}
26
+ */
27
+ export function createCircuitBreaker(opts = {}) {
28
+ const threshold = opts.threshold ?? 3;
29
+ const timeout = opts.timeout ?? 1000;
30
+ /** @type {BreakerState} */
31
+ let state = "closed";
32
+ let failures = 0;
33
+ let openedAt = 0;
34
+
35
+ function getState() {
36
+ if (state === "open" && Date.now() - openedAt >= timeout) {
37
+ state = "half-open";
38
+ }
39
+ return state;
40
+ }
41
+
42
+ async function execute(fn) {
43
+ const cur = getState();
44
+ if (cur === "open") {
45
+ throw new Error("circuit breaker is OPEN");
46
+ }
47
+ try {
48
+ const result = await fn();
49
+ // success: close if half-open, reset counter
50
+ state = "closed";
51
+ failures = 0;
52
+ return result;
53
+ } catch (err) {
54
+ failures++;
55
+ if (failures >= threshold || state === "half-open") {
56
+ state = "open";
57
+ openedAt = Date.now();
58
+ }
59
+ throw err;
60
+ }
61
+ }
62
+
63
+ function reset() {
64
+ state = "closed";
65
+ failures = 0;
66
+ openedAt = 0;
67
+ }
68
+
69
+ return { getState, execute, reset, failures: () => failures };
70
+ }
@@ -0,0 +1,63 @@
1
+ import { classifyClaim } from "../verification/false-completion-prevention.js";
2
+
3
+ export function interceptAgentClaim(message) {
4
+ const claimPatterns = {
5
+ FACT: /\b(is|exists|present|available|installed|configured|has|have)\b/i,
6
+ HYPOTHESIS: /\b(think|believe|probably|might|could be|suspect)\b/i,
7
+ OBSERVATION: /\b(see|observe|notice|found|detected)\b/i,
8
+ INTENT: /\b(will|going to|plan|should|need to|want to)\b/i,
9
+ CONCLUSION: /\b(therefore|so|thus|conclude)\b/i,
10
+ COMPLETION: /\b(done|fixed|working|solved|completed|implemented|resolved|ready)\b/i
11
+ };
12
+
13
+ const claims = [];
14
+
15
+ for (const [type, pattern] of Object.entries(claimPatterns)) {
16
+ const match = message.match(pattern);
17
+ if (match) {
18
+ claims.push({
19
+ type,
20
+ text: match[0],
21
+ position: match.index,
22
+ context: message.slice(Math.max(0, match.index - 20), match.index + 20)
23
+ });
24
+ }
25
+ }
26
+
27
+ return claims;
28
+ }
29
+
30
+ export function createClaim(text, type, source = "agent") {
31
+ return {
32
+ id: `claim-${Date.now().toString(36)}`,
33
+ text,
34
+ type,
35
+ source,
36
+ timestamp: Date.now(),
37
+ validated: false
38
+ };
39
+ }
40
+
41
+ export function validateClaim(claim, taskState) {
42
+ const result = {
43
+ claimId: claim.id,
44
+ valid: false,
45
+ requiresVerification: false,
46
+ reason: ""
47
+ };
48
+
49
+ if (claim.type === "COMPLETION") {
50
+ result.requiresVerification = true;
51
+ result.reason = "Completion claim requires verification";
52
+ } else if (claim.type === "HYPOTHESIS") {
53
+ result.reason = "Hypothesis requires validation";
54
+ } else if (claim.type === "FACT") {
55
+ result.requiresVerification = true;
56
+ result.reason = "Fact claims should be verified";
57
+ } else {
58
+ result.valid = true;
59
+ result.reason = "Observation or intent does not require verification";
60
+ }
61
+
62
+ return result;
63
+ }