opencode-wait-a-minute 0.0.0-stage → 1.1.0-rc.10
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.
- package/LICENSE +21 -0
- package/README.md +318 -2
- package/index.js +1836 -0
- package/package.json +70 -4
- package/skills/codebase-design/SKILL.md +114 -0
- package/skills/design-contract/SKILL.md +27 -0
- package/skills/design-critique/SKILL.md +19 -0
- package/skills/design-system/SKILL.md +17 -0
- package/skills/design-system/references/image-analysis.md +14 -0
- package/skills/design-system/references/tokens.md +32 -0
- package/skills/design-system/references/ui-rules.md +14 -0
- package/skills/diagnosing-bugs/SKILL.md +138 -0
- package/skills/frontend-design/SKILL.md +36 -0
- package/skills/handoff/SKILL.md +16 -0
- package/skills/improve-codebase-architecture/SKILL.md +71 -0
- package/skills/linter-negative/SKILL.md +74 -0
- package/skills/no-slop-ui/SKILL.md +26 -0
- package/skills/prototype/SKILL.md +26 -0
- package/skills/registry.json +44087 -0
- package/skills/tastemaker/SKILL.md +8 -0
- package/skills/tastemaker/references/tastemaker.md +14 -0
- package/skills/tdd/SKILL.md +38 -0
- package/skills/visual-review/SKILL.md +103 -0
- package/skills/visual-review/references/review-gates.md +42 -0
- package/skills/visual-review/references/surface-archetypes.md +37 -0
- package/skills/wizard/SKILL.md +44 -0
- package/skills/writing-for-agents/SKILL.md +81 -0
- package/src/cognition/cognition-store.js +251 -0
- package/src/cognition/cognitive-state.js +126 -0
- package/src/cognition/hypothesis-manager.js +113 -0
- package/src/cognition/observation-engine.js +112 -0
- package/src/cognition/observation-provenance.js +268 -0
- package/src/context/active-context-boundary.js +68 -0
- package/src/context/assembly.js +494 -0
- package/src/context/assessment-rules.js +55 -0
- package/src/context/capsule-staleness.js +267 -0
- package/src/context/capsules.js +2 -0
- package/src/context/compare-array.js +98 -0
- package/src/context/compare-object.js +89 -0
- package/src/context/compare-values.js +42 -0
- package/src/context/context-assembly-contract.js +71 -0
- package/src/context/context-budget-manager.js +232 -0
- package/src/context/context-builder.js +49 -0
- package/src/context/context-cache.js +55 -0
- package/src/context/context-capture.js +243 -0
- package/src/context/context-classification.js +199 -0
- package/src/context/context-compaction.js +179 -0
- package/src/context/context-decision-audit.js +267 -0
- package/src/context/context-demotion.js +173 -0
- package/src/context/context-dictionary.js +106 -0
- package/src/context/context-drift-detection.js +225 -0
- package/src/context/context-evaluation.js +374 -0
- package/src/context/context-event-ingress.js +100 -0
- package/src/context/context-event-normalization.js +224 -0
- package/src/context/context-feedback-loop.js +216 -0
- package/src/context/context-freshness.js +21 -0
- package/src/context/context-graph-builder.js +71 -0
- package/src/context/context-graph.js +451 -0
- package/src/context/context-history-relevance.js +321 -0
- package/src/context/context-interception.js +145 -0
- package/src/context/context-invalidation-events.js +154 -0
- package/src/context/context-lifecycle.js +170 -0
- package/src/context/context-loop-prevention.js +347 -0
- package/src/context/context-manager.js +340 -0
- package/src/context/context-memory-layers.js +265 -0
- package/src/context/context-minimality.js +166 -0
- package/src/context/context-normalization.js +130 -0
- package/src/context/context-optimization-metrics.js +434 -0
- package/src/context/context-output-policy.js +135 -0
- package/src/context/context-pack-authority.js +157 -0
- package/src/context/context-promotion.js +172 -0
- package/src/context/context-query-contract.js +101 -0
- package/src/context/context-ranking.js +164 -0
- package/src/context/context-rate-distortion.js +261 -0
- package/src/context/context-recovery.js +209 -0
- package/src/context/context-retrieval-integration.js +60 -0
- package/src/context/context-retrieval.js +93 -0
- package/src/context/context-router.js +457 -0
- package/src/context/context-routing-evaluation.js +331 -0
- package/src/context/context-routing-observability.js +296 -0
- package/src/context/context-routing-shadow.js +237 -0
- package/src/context/context-scope.js +181 -0
- package/src/context/context-snapshot.js +226 -0
- package/src/context/context-source-registry.js +95 -0
- package/src/context/context-sufficiency-gate.js +120 -0
- package/src/context/context-sufficiency-oracle.js +167 -0
- package/src/context/context-telemetry.js +176 -0
- package/src/context/context.js +633 -0
- package/src/context/dependency-closure.js +246 -0
- package/src/context/page-fault-tracker.js +275 -0
- package/src/context/prompt-engine.js +74 -0
- package/src/context/runtime-context-graph.js +260 -0
- package/src/context/selection.js +2 -0
- package/src/context/session.js +2 -0
- package/src/context/sufficiency-contract.js +300 -0
- package/src/context/tokenizer.js +17 -0
- package/src/context-benchmark-router.mjs +125 -0
- package/src/evidence/evidence-engine.js +161 -0
- package/src/evidence/evidence-factory.js +3 -0
- package/src/evidence/evidence-freshness.js +463 -0
- package/src/evidence/evidence-gap.js +76 -0
- package/src/evidence/evidence-lineage.js +525 -0
- package/src/evidence/evidence.js +136 -0
- package/src/evidence/freshness-validation.js +187 -0
- package/src/evidence/lineage.js +4 -0
- package/src/execution/action-evaluation.js +179 -0
- package/src/execution/circuit-breaker.js +70 -0
- package/src/execution/claim-interception.js +63 -0
- package/src/execution/execution-engine.js +258 -0
- package/src/execution/execution-intent.js +69 -0
- package/src/execution/execution-state.js +89 -0
- package/src/execution/formatting.js +60 -0
- package/src/execution/l1-sanitize.js +16 -0
- package/src/execution/l2-resource-guards.js +19 -0
- package/src/execution/l3-invariant-checker.js +5 -0
- package/src/execution/l4-containment.js +6 -0
- package/src/execution/runtime-guards.js +106 -0
- package/src/execution/strategy-identity.js +162 -0
- package/src/execution/tool-interceptor.js +7 -0
- package/src/execution/tool-result-classifier.js +63 -0
- package/src/integration/canary-deploy.js +143 -0
- package/src/integration/collector.js +59 -0
- package/src/integration/error-recovery.js +6 -0
- package/src/integration/event-bus.js +66 -0
- package/src/integration/health-checker.js +57 -0
- package/src/integration/logger.js +39 -0
- package/src/integration/message-handler.js +611 -0
- package/src/integration/opencode-db.js +153 -0
- package/src/integration/orchestration.js +419 -0
- package/src/integration/part-provenance.js +65 -0
- package/src/integration/rate-limiter.js +55 -0
- package/src/integration/release-gate.js +336 -0
- package/src/integration/rollback-manager.js +164 -0
- package/src/integration/router-adapter.js +269 -0
- package/src/integration/telemetry.js +45 -0
- package/src/integration/update-checker.js +10 -0
- package/src/persistence/event-sourcing.js +75 -0
- package/src/persistence/memory.js +501 -0
- package/src/persistence/migration-runner.js +16 -0
- package/src/persistence/persistence-manager.js +39 -0
- package/src/persistence/transaction-log.js +157 -0
- package/src/policy/action-capabilities.js +116 -0
- package/src/policy/action-policy.js +4 -0
- package/src/policy/assessment-engine.js +104 -0
- package/src/policy/assumption-tracking.js +66 -0
- package/src/policy/budget-enforcer.js +7 -0
- package/src/policy/config-validator.js +102 -0
- package/src/policy/execution-assessment.js +142 -0
- package/src/policy/failure-classification.js +5 -0
- package/src/policy/feature-flags.js +65 -0
- package/src/policy/governance-enforcement.js +118 -0
- package/src/policy/locale.js +15 -0
- package/src/policy/multi-signer.js +151 -0
- package/src/policy/policy-state-machine.js +97 -0
- package/src/policy/ponytail-constraint.js +38 -0
- package/src/policy/project-inspector.js +93 -0
- package/src/policy/query-builder.js +14 -0
- package/src/policy/request-classifier.js +79 -0
- package/src/policy/risk-engine.js +266 -0
- package/src/policy/scope-enforcement.js +140 -0
- package/src/policy/secret-scanner.js +68 -0
- package/src/policy/skill-routing.js +104 -0
- package/src/policy/strategy-capabilities.js +211 -0
- package/src/policy/strategy.js +6 -0
- package/src/policy/uncertainty.js +117 -0
- package/src/shared/container.js +44 -0
- package/src/shared/decision-types.js +24 -0
- package/src/shared/simple-test.js +160 -0
- package/src/shared/wam-events.js +52 -0
- package/src/skills/engine.js +1705 -0
- package/src/skills/skill-registry.js +19 -0
- package/src/skills/skill-routing.js +340 -0
- package/src/state/lifecycle-manager.js +113 -0
- package/src/state/operational-state.js +198 -0
- package/src/state/projections.js +47 -0
- package/src/state/replay-engine.js +5 -0
- package/src/state/requirement-ownership.js +20 -0
- package/src/state/requirement-state.js +152 -0
- package/src/state/run-event-identity.js +172 -0
- package/src/state/state-engine.js +19 -0
- package/src/state/state-machine.js +119 -0
- package/src/state/state-schema.js +318 -0
- package/src/state/state-store.js +335 -0
- package/src/state/state-transition.js +84 -0
- package/src/state/task-dependencies.js +287 -0
- package/src/state/task-execution.js +217 -0
- package/src/state/task-lifecycle.js +59 -0
- package/src/state/task-runs.js +361 -0
- package/src/state/task-state-file.js +86 -0
- package/src/state/task-state.js +41 -0
- package/src/state/task-status.js +54 -0
- package/src/state/task-store.js +48 -0
- package/src/state/wam-state.js +148 -0
- package/src/verification/completion-gate-simple.js +8 -0
- package/src/verification/completion-gate.js +183 -0
- package/src/verification/contract.js +9 -0
- package/src/verification/contradiction-resolution.js +255 -0
- package/src/verification/diagnostic-engine.js +659 -0
- package/src/verification/false-completion-prevention.js +100 -0
- package/src/verification/hook-validator.js +6 -0
- package/src/verification/requirements.js +6 -0
- package/src/verification/verification-context.js +162 -0
- package/src/verification/verification-lifecycle.js +66 -0
- package/src/verification/verification-model.js +89 -0
- package/src/verification/verification-persistence.js +129 -0
- package/src/verification/verification-policy.js +127 -0
- package/src/verification/verification.js +415 -0
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime Context Graph — canonical assembler for all runtime state layers.
|
|
3
|
+
*
|
|
4
|
+
* Unifies taskState, runState, evidenceLineage, cognitionState, decisions,
|
|
5
|
+
* constraints, artifacts, observations, hypotheses, and experiments into a
|
|
6
|
+
* single ContextGraph. Replaces the shallow buildGraphFromTaskState() that
|
|
7
|
+
* only saw (task, requirements, evidence) with a layer-aware builder that
|
|
8
|
+
* creates nodes/edges for every state slice present in the runtime.
|
|
9
|
+
*
|
|
10
|
+
* Pattern follows context-graph-builder.js but expands coverage to:
|
|
11
|
+
* - task, requirements
|
|
12
|
+
* - evidence (lineage)
|
|
13
|
+
* - decisions, constraints
|
|
14
|
+
* - artifacts
|
|
15
|
+
* - observations
|
|
16
|
+
* - hypotheses, experiments (only when supplied)
|
|
17
|
+
*
|
|
18
|
+
* Edges are added only when both endpoints exist.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { ContextGraph } from "./context-graph.js";
|
|
22
|
+
import { buildContextGraph } from "./context-graph-builder.js";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {Object} BuildRuntimeContextGraphInput
|
|
26
|
+
* @property {Object} [taskState]
|
|
27
|
+
* @property {Object} [runState]
|
|
28
|
+
* @property {Array} [evidenceLineage]
|
|
29
|
+
* @property {Object} [cognitionState]
|
|
30
|
+
* @property {Array} [decisions]
|
|
31
|
+
* @property {Array} [constraints]
|
|
32
|
+
* @property {Array} [artifacts]
|
|
33
|
+
* @property {Array} [observations]
|
|
34
|
+
* @property {Array} [hypotheses]
|
|
35
|
+
* @property {Array} [experiments]
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Build a canonical ContextGraph from all runtime state layers.
|
|
40
|
+
*
|
|
41
|
+
* @param {BuildRuntimeContextGraphInput} input
|
|
42
|
+
* @returns {ContextGraph}
|
|
43
|
+
*/
|
|
44
|
+
export function buildRuntimeContextGraph(input = {}) {
|
|
45
|
+
const {
|
|
46
|
+
taskState = {},
|
|
47
|
+
runState = {},
|
|
48
|
+
evidenceLineage = [],
|
|
49
|
+
cognitionState = {},
|
|
50
|
+
decisions = [],
|
|
51
|
+
constraints = [],
|
|
52
|
+
artifacts = [],
|
|
53
|
+
observations = [],
|
|
54
|
+
hypotheses = [],
|
|
55
|
+
experiments = [],
|
|
56
|
+
} = input;
|
|
57
|
+
|
|
58
|
+
// Canonical primary source: delegate base graph (task + requirements +
|
|
59
|
+
// evidence) to context-graph-builder.js so node/edge schema and IDs
|
|
60
|
+
// stay canonical. The remaining state layers (cognition, decisions,
|
|
61
|
+
// constraints, artifacts, observations, hypotheses, experiments) are
|
|
62
|
+
// added below on top of the canonical base.
|
|
63
|
+
const g = buildContextGraph(taskState, runState, evidenceLineage);
|
|
64
|
+
const taskId = taskState?.taskId || null;
|
|
65
|
+
|
|
66
|
+
// -- Requirement shadow output nodes (router compatibility) --
|
|
67
|
+
// The canonical requirement node + the task→requirement edge are
|
|
68
|
+
// already produced by buildContextGraph() above. We only need the
|
|
69
|
+
// shadow "output" node per requirement so Context Router's Phase 3
|
|
70
|
+
// collection can resolve output-type ids.
|
|
71
|
+
const requirementIds = new Set();
|
|
72
|
+
for (const req of taskState?.requirements || []) {
|
|
73
|
+
if (!req?.id) continue;
|
|
74
|
+
requirementIds.add(req.id);
|
|
75
|
+
const outputId = `${req.id}::output`;
|
|
76
|
+
g.addNode({
|
|
77
|
+
id: outputId,
|
|
78
|
+
type: "output",
|
|
79
|
+
content: req.title || req.description || "",
|
|
80
|
+
metadata: {
|
|
81
|
+
provenance: "user_decided",
|
|
82
|
+
shadowOf: req.id,
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
if (taskId) {
|
|
86
|
+
g.addEdge({ from: taskId, to: outputId, type: "related_to" });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// -- Evidence lineage (evidence supports requirement when linked) --
|
|
91
|
+
for (const ev of evidenceLineage || []) {
|
|
92
|
+
if (!ev?.id) continue;
|
|
93
|
+
g.addNode({
|
|
94
|
+
id: ev.id,
|
|
95
|
+
type: "evidence",
|
|
96
|
+
content: ev.content || ev.summary || "",
|
|
97
|
+
verified: ev.status === "valid" || ev.verified === true,
|
|
98
|
+
metadata: {
|
|
99
|
+
provenance: "run_execution",
|
|
100
|
+
source: ev.source || null,
|
|
101
|
+
capturedAt: ev.capturedAt || null,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
if (ev.requirementId && requirementIds.has(ev.requirementId)) {
|
|
105
|
+
g.addEdge({ from: ev.id, to: ev.requirementId, type: "supports" });
|
|
106
|
+
} else if (taskId) {
|
|
107
|
+
g.addEdge({ from: ev.id, to: taskId, type: "supports" });
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// -- Decisions (decision influences requirement/task) --
|
|
112
|
+
for (const dec of decisions || []) {
|
|
113
|
+
if (!dec?.id) continue;
|
|
114
|
+
g.addNode({
|
|
115
|
+
id: dec.id,
|
|
116
|
+
type: "decision",
|
|
117
|
+
content: dec.summary || dec.description || dec.content || "",
|
|
118
|
+
metadata: {
|
|
119
|
+
provenance: dec.provenance || "user_decided",
|
|
120
|
+
madeAt: dec.madeAt || null,
|
|
121
|
+
status: dec.status || "accepted",
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
if (dec.requirementId && requirementIds.has(dec.requirementId)) {
|
|
125
|
+
g.addEdge({ from: dec.id, to: dec.requirementId, type: "supports" });
|
|
126
|
+
} else if (taskId) {
|
|
127
|
+
g.addEdge({ from: dec.id, to: taskId, type: "supports" });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// -- Constraints (constraint constrains task/requirement) --
|
|
132
|
+
for (const c of constraints || []) {
|
|
133
|
+
if (!c?.id) continue;
|
|
134
|
+
g.addNode({
|
|
135
|
+
id: c.id,
|
|
136
|
+
type: "constraint",
|
|
137
|
+
content: c.description || c.content || c.summary || "",
|
|
138
|
+
metadata: {
|
|
139
|
+
provenance: c.provenance || "user_decided",
|
|
140
|
+
severity: c.severity || "normal",
|
|
141
|
+
relation: "constraint",
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
const target = c.requirementId || taskId;
|
|
145
|
+
if (target) {
|
|
146
|
+
g.addEdge({ from: target, to: c.id, type: "related_to" });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// -- Artifacts (task produces artifact) --
|
|
151
|
+
for (const a of artifacts || []) {
|
|
152
|
+
if (!a?.id) continue;
|
|
153
|
+
g.addNode({
|
|
154
|
+
id: a.id,
|
|
155
|
+
type: "artifact",
|
|
156
|
+
content: a.content || a.path || a.summary || "",
|
|
157
|
+
metadata: {
|
|
158
|
+
provenance: a.provenance || "run_execution",
|
|
159
|
+
path: a.path || null,
|
|
160
|
+
kind: a.kind || "generic",
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
// taskId is the canonical producer; fall back to requirement only
|
|
164
|
+
// when no task is in scope.
|
|
165
|
+
const producer = taskId || a.taskId || a.requirementId;
|
|
166
|
+
if (producer) {
|
|
167
|
+
g.addEdge({ from: producer, to: a.id, type: "produces" });
|
|
168
|
+
}
|
|
169
|
+
if (a.requirementId && requirementIds.has(a.requirementId)) {
|
|
170
|
+
g.addEdge({ from: a.id, to: a.requirementId, type: "supports" });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// -- Observations (observation relates to task) --
|
|
175
|
+
for (const o of observations || []) {
|
|
176
|
+
if (!o?.id) continue;
|
|
177
|
+
g.addNode({
|
|
178
|
+
id: o.id,
|
|
179
|
+
type: "observation",
|
|
180
|
+
content: o.content || o.summary || "",
|
|
181
|
+
metadata: {
|
|
182
|
+
provenance: o.provenance || "run_execution",
|
|
183
|
+
observedAt: o.observedAt || null,
|
|
184
|
+
},
|
|
185
|
+
});
|
|
186
|
+
const target = o.requirementId || o.taskId || taskId;
|
|
187
|
+
if (target) {
|
|
188
|
+
g.addEdge({ from: o.id, to: target, type: "related_to" });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// -- Hypotheses (only when present) --
|
|
193
|
+
for (const h of hypotheses || []) {
|
|
194
|
+
if (!h?.id) continue;
|
|
195
|
+
g.addNode({
|
|
196
|
+
id: h.id,
|
|
197
|
+
type: "claim",
|
|
198
|
+
content: h.statement || h.content || "",
|
|
199
|
+
metadata: {
|
|
200
|
+
provenance: h.provenance || "user_decided",
|
|
201
|
+
confidence: h.confidence ?? null,
|
|
202
|
+
kind: "hypothesis",
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
const target = h.requirementId || h.taskId || taskId;
|
|
206
|
+
if (target) {
|
|
207
|
+
g.addEdge({ from: h.id, to: target, type: "related_to" });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// -- Experiments (only when present) --
|
|
212
|
+
for (const x of experiments || []) {
|
|
213
|
+
if (!x?.id) continue;
|
|
214
|
+
g.addNode({
|
|
215
|
+
id: x.id,
|
|
216
|
+
type: "action",
|
|
217
|
+
content: x.description || x.content || "",
|
|
218
|
+
metadata: {
|
|
219
|
+
provenance: x.provenance || "run_execution",
|
|
220
|
+
status: x.status || "planned",
|
|
221
|
+
kind: "experiment",
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
if (x.hypothesisId && g.hasNode(x.hypothesisId)) {
|
|
225
|
+
g.addEdge({ from: x.id, to: x.hypothesisId, type: "supports" });
|
|
226
|
+
}
|
|
227
|
+
const target = x.requirementId || taskId;
|
|
228
|
+
if (target) {
|
|
229
|
+
g.addEdge({ from: x.id, to: target, type: "produces" });
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// -- Cognition summary node (single node when cognitionState present) --
|
|
234
|
+
if (cognitionState && Object.keys(cognitionState).length > 0) {
|
|
235
|
+
const cogId = cognitionState.id || `cognition:${taskId || "global"}`;
|
|
236
|
+
if (!g.hasNode(cogId)) {
|
|
237
|
+
g.addNode({
|
|
238
|
+
id: cogId,
|
|
239
|
+
type: "observation",
|
|
240
|
+
content:
|
|
241
|
+
cognitionState.summary ||
|
|
242
|
+
cognitionState.objective ||
|
|
243
|
+
"Active cognition state",
|
|
244
|
+
metadata: {
|
|
245
|
+
provenance: "run_execution",
|
|
246
|
+
kind: "cognition",
|
|
247
|
+
load: cognitionState.load ?? null,
|
|
248
|
+
focus: cognitionState.focus || null,
|
|
249
|
+
},
|
|
250
|
+
});
|
|
251
|
+
if (taskId) {
|
|
252
|
+
g.addEdge({ from: cogId, to: taskId, type: "related_to" });
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return g;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export default { buildRuntimeContextGraph };
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Sufficiency Contract — task-derived conditions for safe execution.
|
|
3
|
+
*
|
|
4
|
+
* Replaces lexical keyword matching with structured conditions that
|
|
5
|
+
* must be satisfied before autonomous execution is permitted.
|
|
6
|
+
*
|
|
7
|
+
* States: SATISFIED | MISSING | BLOCKED | UNKNOWN
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {"SATISFIED" | "MISSING" | "BLOCKED" | "UNKNOWN"} ConditionStatus
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @typedef {Object} SufficiencyCondition
|
|
16
|
+
* @property {string} id
|
|
17
|
+
* @property {string} type - Type of required knowledge
|
|
18
|
+
* @property {string} description
|
|
19
|
+
* @property {ConditionStatus} status
|
|
20
|
+
* @property {string} source - What satisfied or blocked this condition
|
|
21
|
+
* @property {"MANDATORY" | "CONDITIONAL"} severity
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @typedef {Object} SufficiencyContract
|
|
26
|
+
* @property {string} taskId
|
|
27
|
+
* @property {SufficiencyCondition[]} conditions
|
|
28
|
+
* @property {boolean} sufficient - True only when all MANDATORY conditions are SATISFIED
|
|
29
|
+
* @property {string[]} missing - List of missing MANDATORY condition descriptions
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
/** Condition types derived from task analysis */
|
|
33
|
+
const CONDITION_TYPES = {
|
|
34
|
+
PROJECT_KNOWLEDGE: "project-knowledge",
|
|
35
|
+
DECISION: "decision",
|
|
36
|
+
CONSTRAINT: "constraint",
|
|
37
|
+
DEPENDENCY: "dependency",
|
|
38
|
+
VERIFICATION: "verification",
|
|
39
|
+
UNKNOWN_RESOLUTION: "unknown-resolution",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Patterns that indicate required context domains.
|
|
44
|
+
* Each pattern maps to one or more condition types.
|
|
45
|
+
*/
|
|
46
|
+
const DOMAIN_PATTERNS = [
|
|
47
|
+
{
|
|
48
|
+
domain: "auth",
|
|
49
|
+
patterns: /\b(auth|oauth|jwt|token|login|credential|password|session)\b/i,
|
|
50
|
+
conditions: [
|
|
51
|
+
{ type: CONDITION_TYPES.DECISION, description: "Auth mechanism decision (OAuth, JWT, etc.)" },
|
|
52
|
+
{ type: CONDITION_TYPES.PROJECT_KNOWLEDGE, description: "Existing auth implementation" },
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
domain: "migration",
|
|
57
|
+
patterns: /\b(migrat|schema.*change|database.*change|column.*add|table.*rename)\b/i,
|
|
58
|
+
conditions: [
|
|
59
|
+
{ type: CONDITION_TYPES.DECISION, description: "Migration strategy (forward, backward-compatible)" },
|
|
60
|
+
{ type: CONDITION_TYPES.CONSTRAINT, description: "Data integrity constraints" },
|
|
61
|
+
{ type: CONDITION_TYPES.DEPENDENCY, description: "Migration tool version" },
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
domain: "security",
|
|
66
|
+
patterns: /\b(security|vulnerability|cve|encrypt|hash|sanitiz|xss|csrf|injection)\b/i,
|
|
67
|
+
conditions: [
|
|
68
|
+
{ type: CONDITION_TYPES.DECISION, description: "Security approach decision" },
|
|
69
|
+
{ type: CONDITION_TYPES.CONSTRAINT, description: "Security constraints and compliance requirements" },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
domain: "testing",
|
|
74
|
+
patterns: /\b(test|spec|coverage|e2e|unit|integration)\b/i,
|
|
75
|
+
conditions: [
|
|
76
|
+
{ type: CONDITION_TYPES.PROJECT_KNOWLEDGE, description: "Test framework and patterns" },
|
|
77
|
+
{ type: CONDITION_TYPES.VERIFICATION, description: "Verification criteria" },
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
domain: "architecture",
|
|
82
|
+
patterns: /\b(architect|refactor|restructur|monolith|microservice|modul)\b/i,
|
|
83
|
+
conditions: [
|
|
84
|
+
{ type: CONDITION_TYPES.DECISION, description: "Architecture decision" },
|
|
85
|
+
{ type: CONDITION_TYPES.CONSTRAINT, description: "Architectural constraints" },
|
|
86
|
+
{ type: CONDITION_TYPES.PROJECT_KNOWLEDGE, description: "Current architecture state" },
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
domain: "performance",
|
|
91
|
+
patterns: /\b(performance|optim|cache|redis|latency|throughput|bottleneck)\b/i,
|
|
92
|
+
conditions: [
|
|
93
|
+
{ type: CONDITION_TYPES.DECISION, description: "Performance optimization strategy" },
|
|
94
|
+
{ type: CONDITION_TYPES.PROJECT_KNOWLEDGE, description: "Current performance baseline" },
|
|
95
|
+
],
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
domain: "scraping",
|
|
99
|
+
patterns: /\b(scrap|crawl|puppeteer|playwright|selenium|parser)\b/i,
|
|
100
|
+
conditions: [
|
|
101
|
+
{ type: CONDITION_TYPES.PROJECT_KNOWLEDGE, description: "Scraping framework and patterns" },
|
|
102
|
+
{ type: CONDITION_TYPES.DEPENDENCY, description: "Browser automation dependency" },
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
];
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Concrete terms per domain. When a domain's condition is unsatisfied, the
|
|
109
|
+
* matched terms are surfaced verbatim in `missing` so the caller can name the
|
|
110
|
+
* exact missing concept (e.g. "cache") instead of only a prose description.
|
|
111
|
+
*/
|
|
112
|
+
const DOMAIN_TERMS = {
|
|
113
|
+
auth: ["auth", "oauth", "jwt", "token", "login", "credential", "password", "session"],
|
|
114
|
+
migration: ["migration", "schema", "column", "table"],
|
|
115
|
+
security: ["security", "vulnerability", "encrypt", "hash", "sanitize", "xss", "csrf", "injection"],
|
|
116
|
+
testing: ["test", "coverage", "e2e", "unit", "integration"],
|
|
117
|
+
architecture: ["architecture", "refactor", "structure", "monolith", "microservice", "module"],
|
|
118
|
+
performance: ["performance", "optimization", "cache", "redis", "latency", "throughput", "bottleneck"],
|
|
119
|
+
scraping: ["scraping", "crawl", "puppeteer", "playwright", "selenium", "parser"],
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Collect the MANDATORY missing descriptions plus the matched domain terms.
|
|
124
|
+
* Descriptions stay first so existing consumers keep working; the terms are
|
|
125
|
+
* appended so a caller can test for a concrete missing concept.
|
|
126
|
+
*
|
|
127
|
+
* @param {SufficiencyCondition[]} conditions
|
|
128
|
+
* @returns {string[]}
|
|
129
|
+
*/
|
|
130
|
+
function collectMissing(conditions) {
|
|
131
|
+
const out = [];
|
|
132
|
+
const seen = new Set();
|
|
133
|
+
for (const c of conditions) {
|
|
134
|
+
if (c.status !== "MISSING" && c.status !== "BLOCKED") continue;
|
|
135
|
+
if (c.severity !== "MANDATORY") continue;
|
|
136
|
+
if (!seen.has(c.description)) {
|
|
137
|
+
out.push(c.description);
|
|
138
|
+
seen.add(c.description);
|
|
139
|
+
}
|
|
140
|
+
for (const term of c.terms || []) {
|
|
141
|
+
if (!seen.has(term)) {
|
|
142
|
+
out.push(term);
|
|
143
|
+
seen.add(term);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Generate a sufficiency contract from a task description.
|
|
152
|
+
*
|
|
153
|
+
* @param {string} taskDescription
|
|
154
|
+
* @param {string} taskId
|
|
155
|
+
* @returns {SufficiencyContract}
|
|
156
|
+
*/
|
|
157
|
+
export function generateContract(taskDescription, taskId) {
|
|
158
|
+
const conditions = [];
|
|
159
|
+
const seen = new Set();
|
|
160
|
+
|
|
161
|
+
for (const domain of DOMAIN_PATTERNS) {
|
|
162
|
+
if (domain.patterns.test(taskDescription)) {
|
|
163
|
+
const terms = (DOMAIN_TERMS[domain.domain] || []).filter((t) =>
|
|
164
|
+
new RegExp(`\\b${t}`, "i").test(taskDescription)
|
|
165
|
+
);
|
|
166
|
+
for (const cond of domain.conditions) {
|
|
167
|
+
const key = `${cond.type}:${cond.description}`;
|
|
168
|
+
if (!seen.has(key)) {
|
|
169
|
+
seen.add(key);
|
|
170
|
+
conditions.push({
|
|
171
|
+
id: `SC-${conditions.length + 1}`,
|
|
172
|
+
type: cond.type,
|
|
173
|
+
description: cond.description,
|
|
174
|
+
domain: domain.domain,
|
|
175
|
+
terms,
|
|
176
|
+
status: "MISSING",
|
|
177
|
+
source: "",
|
|
178
|
+
severity: "MANDATORY",
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Always require project knowledge as a baseline
|
|
186
|
+
const projectKnowledgeKey = `${CONDITION_TYPES.PROJECT_KNOWLEDGE}:Project structure and dependencies`;
|
|
187
|
+
if (!seen.has(projectKnowledgeKey)) {
|
|
188
|
+
seen.add(projectKnowledgeKey);
|
|
189
|
+
conditions.push({
|
|
190
|
+
id: `SC-${conditions.length + 1}`,
|
|
191
|
+
type: CONDITION_TYPES.PROJECT_KNOWLEDGE,
|
|
192
|
+
description: "Project structure and dependencies",
|
|
193
|
+
status: "MISSING",
|
|
194
|
+
source: "",
|
|
195
|
+
severity: "MANDATORY",
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const missing = collectMissing(conditions);
|
|
200
|
+
|
|
201
|
+
return {
|
|
202
|
+
taskId,
|
|
203
|
+
conditions,
|
|
204
|
+
sufficient: missing.length === 0,
|
|
205
|
+
missing,
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Evaluate a sufficiency contract against available context capsules.
|
|
211
|
+
*
|
|
212
|
+
* @param {SufficiencyContract} contract
|
|
213
|
+
* @param {Array} capsules - Selected context capsules
|
|
214
|
+
* @returns {SufficiencyContract} Updated contract with statuses
|
|
215
|
+
*/
|
|
216
|
+
export function evaluateContract(contract, capsules) {
|
|
217
|
+
const capsuleText = capsules
|
|
218
|
+
.map((c) => `${c.purpose || ""} ${c.scope || ""} ${c.content || ""}`)
|
|
219
|
+
.join(" ")
|
|
220
|
+
.toLowerCase();
|
|
221
|
+
|
|
222
|
+
for (const condition of contract.conditions) {
|
|
223
|
+
// Check if any capsule covers this condition
|
|
224
|
+
const covered = capsules.some((c) => {
|
|
225
|
+
const text = `${c.purpose || ""} ${c.scope || ""} ${c.content || ""}`.toLowerCase();
|
|
226
|
+
return conditionMatchesText(condition, text);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
if (covered) {
|
|
230
|
+
condition.status = "SATISFIED";
|
|
231
|
+
condition.source = "capsule";
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Recalculate sufficiency
|
|
236
|
+
contract.missing = collectMissing(contract.conditions);
|
|
237
|
+
contract.sufficient = contract.missing.length === 0;
|
|
238
|
+
|
|
239
|
+
return contract;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Check if a condition is covered by text content.
|
|
244
|
+
*/
|
|
245
|
+
function conditionMatchesText(condition, text) {
|
|
246
|
+
// Type-specific matching
|
|
247
|
+
switch (condition.type) {
|
|
248
|
+
case CONDITION_TYPES.PROJECT_KNOWLEDGE:
|
|
249
|
+
return /\b(project|package\.json|dependenc|structure|architect)\b/i.test(text);
|
|
250
|
+
case CONDITION_TYPES.DECISION:
|
|
251
|
+
return /\b(decision|decid|chose|selected|approach|strategy)\b/i.test(text);
|
|
252
|
+
case CONDITION_TYPES.CONSTRAINT:
|
|
253
|
+
return /\b(constraint|requirement|must|shall|mandatory|compliance)\b/i.test(text);
|
|
254
|
+
case CONDITION_TYPES.DEPENDENCY:
|
|
255
|
+
return /\b(dependency|version|package|library|framework)\b/i.test(text);
|
|
256
|
+
case CONDITION_TYPES.VERIFICATION:
|
|
257
|
+
return /\b(verification|verify|test|pass|evidence|criteria)\b/i.test(text);
|
|
258
|
+
case CONDITION_TYPES.UNKNOWN_RESOLUTION:
|
|
259
|
+
return /\b(answer|resolved|clarified|confirmed)\b/i.test(text);
|
|
260
|
+
default:
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Merge a sufficiency contract with assumptions from the analysis.
|
|
267
|
+
* Assumptions with DECISION_CRITICAL classification become MANDATORY conditions.
|
|
268
|
+
*
|
|
269
|
+
* @param {SufficiencyContract} contract
|
|
270
|
+
* @param {Array} assumptions - From analysis.assumptions
|
|
271
|
+
* @returns {SufficiencyContract}
|
|
272
|
+
*/
|
|
273
|
+
export function mergeAssumptions(contract, assumptions) {
|
|
274
|
+
for (const assumption of assumptions || []) {
|
|
275
|
+
if (assumption.classification === "DECISION_CRITICAL" && assumption.status === "active") {
|
|
276
|
+
const key = `${CONDITION_TYPES.UNKNOWN_RESOLUTION}:${assumption.statement}`;
|
|
277
|
+
const exists = contract.conditions.some(
|
|
278
|
+
(c) => c.type === CONDITION_TYPES.UNKNOWN_RESOLUTION && c.description === assumption.statement
|
|
279
|
+
);
|
|
280
|
+
if (!exists) {
|
|
281
|
+
contract.conditions.push({
|
|
282
|
+
id: `SC-${contract.conditions.length + 1}`,
|
|
283
|
+
type: CONDITION_TYPES.UNKNOWN_RESOLUTION,
|
|
284
|
+
description: assumption.statement,
|
|
285
|
+
status: "BLOCKED",
|
|
286
|
+
source: `assumption ${assumption.id}`,
|
|
287
|
+
severity: "MANDATORY",
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// Recalculate
|
|
294
|
+
contract.missing = collectMissing(contract.conditions);
|
|
295
|
+
contract.sufficient = contract.missing.length === 0;
|
|
296
|
+
|
|
297
|
+
return contract;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export { CONDITION_TYPES };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export function countTokens(text) {
|
|
2
|
+
if (text == null || text === '') return 0;
|
|
3
|
+
const str = String(text);
|
|
4
|
+
// Approximation: GPT-2 BPE rule of thumb.
|
|
5
|
+
// Common regex from OpenAI's gpt-3.5-turbo tokenizer approximations
|
|
6
|
+
// and tiktoken's "cl100k_base" approximated regex pattern.
|
|
7
|
+
const re = /'s|'t|'re|'ve|'m|'ll|'d| ?[A-Za-z]+| ?[0-9]+| ?[^\sA-Za-z0-9]+|\s+(?!\S)/g;
|
|
8
|
+
const matches = str.match(re);
|
|
9
|
+
if (!matches) return 0;
|
|
10
|
+
// Each matched piece is roughly 1 token for short ASCII; multi-byte chars add overhead.
|
|
11
|
+
let tokens = matches.length;
|
|
12
|
+
// Account for multi-byte characters (emojis, accented, CJK) — roughly 2 tokens each.
|
|
13
|
+
const multibyteCount = (str.match(/[^\x00-\x7F]/g) || []).length;
|
|
14
|
+
// Multi-byte chars are already counted once in matches; roughly double-count them.
|
|
15
|
+
tokens += multibyteCount;
|
|
16
|
+
return tokens;
|
|
17
|
+
}
|