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.
- 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,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Minimality Test (C07 — context-minimality).
|
|
3
|
+
*
|
|
4
|
+
* Given a selected context set P, determines whether P is minimal w.r.t.
|
|
5
|
+
* the Oracle's required-closure graph. A selected set P is *minimal* iff
|
|
6
|
+
* removing any single node from P∩required makes the oracle verdict
|
|
7
|
+
* insufficient (i.e. every node in P∩required is load-bearing).
|
|
8
|
+
*
|
|
9
|
+
* Two outputs:
|
|
10
|
+
* - minimalityRatio: |load-bearing ∩ required| / |P ∩ required|
|
|
11
|
+
* (1.0 = every required node is load-bearing)
|
|
12
|
+
* - overInjected: P \\ requiredClosure (context that contributes
|
|
13
|
+
* nothing to oracle sufficiency)
|
|
14
|
+
*
|
|
15
|
+
* Independence: this module only consults the oracle's required-closure
|
|
16
|
+
* computation. It does NOT examine scoring weights or admission classes.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @typedef {Object} MinimalityInput
|
|
21
|
+
* @property {string} taskId
|
|
22
|
+
* @property {string[]} selected - selected node IDs (selected set P)
|
|
23
|
+
* @property {Object} oracleGraph - same shape accepted by
|
|
24
|
+
* `verifySufficiency` (buildOracleGraph-compatible).
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @typedef {Object} MinimalityNodeVerdict
|
|
29
|
+
* @property {string} id
|
|
30
|
+
* @property {"load-bearing" | "redundant" | "over-injected"} status
|
|
31
|
+
* @property {boolean} sufficientIfRemoved - whether oracle still sufficient
|
|
32
|
+
* after removing this single node. Undefined for over-injected nodes.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @typedef {Object} MinimalityReport
|
|
37
|
+
* @property {string} taskId
|
|
38
|
+
* @property {string[]} requiredClosure - sorted required IDs from oracle
|
|
39
|
+
* @property {string[]} selected - sorted input selected IDs
|
|
40
|
+
* @property {string[]} overInjected - selected \\ requiredClosure
|
|
41
|
+
* @property {string[]} loadBearing - P ∩ required that, removed alone,
|
|
42
|
+
* breaks oracle sufficiency
|
|
43
|
+
* @property {string[]} redundant - P ∩ required that are NOT load-bearing
|
|
44
|
+
* @property {MinimalityNodeVerdict[]} verdicts - per-node verdicts (selected ∩ required)
|
|
45
|
+
* @property {number} minimalityRatio - |loadBearing| / |P ∩ required| (0 if no required intersection)
|
|
46
|
+
* @property {boolean} minimal - true iff redundant.length === 0 AND overInjected.length === 0
|
|
47
|
+
* @property {Object} stats
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
import {
|
|
51
|
+
computeRequiredClosure,
|
|
52
|
+
verifySufficiency,
|
|
53
|
+
} from "./context-sufficiency-oracle.js";
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Test minimality of a selected set P against the oracle's required closure.
|
|
57
|
+
*
|
|
58
|
+
* Algorithm:
|
|
59
|
+
* 1. Compute requiredClosure = oracle(taskId).
|
|
60
|
+
* 2. Partition selected into over-injected (selected \ required)
|
|
61
|
+
* and candidate-minimal (selected ∩ required).
|
|
62
|
+
* 3. For each candidate-minimal node n, remove n from selected and
|
|
63
|
+
* re-run oracle sufficiency. If still sufficient → n is redundant.
|
|
64
|
+
* 4. minimalityRatio = loadBearing.length / candidate-minimal.length.
|
|
65
|
+
*
|
|
66
|
+
* @param {MinimalityInput} input
|
|
67
|
+
* @returns {MinimalityReport}
|
|
68
|
+
*/
|
|
69
|
+
export function testMinimality(input) {
|
|
70
|
+
if (!input || typeof input !== "object") {
|
|
71
|
+
throw new TypeError("testMinimality: input must be an object");
|
|
72
|
+
}
|
|
73
|
+
const { taskId, selected, oracleGraph } = input;
|
|
74
|
+
if (typeof taskId !== "string" || taskId.length === 0) {
|
|
75
|
+
throw new TypeError("testMinimality: taskId must be a non-empty string");
|
|
76
|
+
}
|
|
77
|
+
if (!Array.isArray(selected)) {
|
|
78
|
+
throw new TypeError("testMinimality: selected must be an array");
|
|
79
|
+
}
|
|
80
|
+
if (!oracleGraph || typeof oracleGraph.getNode !== "function") {
|
|
81
|
+
throw new TypeError("testMinimality: oracleGraph must be a graph object");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const requiredClosure = computeRequiredClosure(taskId, oracleGraph);
|
|
85
|
+
const requiredSet = new Set(requiredClosure);
|
|
86
|
+
|
|
87
|
+
// Dedup + sort selected
|
|
88
|
+
const selectedSorted = [...new Set(selected)].sort();
|
|
89
|
+
|
|
90
|
+
// Partition
|
|
91
|
+
const overInjected = [];
|
|
92
|
+
const candidateMinimal = [];
|
|
93
|
+
for (const id of selectedSorted) {
|
|
94
|
+
if (requiredSet.has(id)) candidateMinimal.push(id);
|
|
95
|
+
else overInjected.push(id);
|
|
96
|
+
}
|
|
97
|
+
overInjected.sort();
|
|
98
|
+
|
|
99
|
+
// For each candidate-minimal node, remove and re-test sufficiency
|
|
100
|
+
const loadBearing = [];
|
|
101
|
+
const redundant = [];
|
|
102
|
+
const verdicts = [];
|
|
103
|
+
|
|
104
|
+
for (const id of candidateMinimal) {
|
|
105
|
+
const reduced = selectedSorted.filter((x) => x !== id);
|
|
106
|
+
const verdict = verifySufficiency(taskId, oracleGraph, reduced);
|
|
107
|
+
const sufficientIfRemoved = verdict.sufficient;
|
|
108
|
+
if (sufficientIfRemoved) {
|
|
109
|
+
redundant.push(id);
|
|
110
|
+
verdicts.push({ id, status: "redundant", sufficientIfRemoved: true });
|
|
111
|
+
} else {
|
|
112
|
+
loadBearing.push(id);
|
|
113
|
+
verdicts.push({ id, status: "load-bearing", sufficientIfRemoved: false });
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const candidateCount = candidateMinimal.length;
|
|
118
|
+
const minimalityRatio = candidateCount === 0 ? 1 : loadBearing.length / candidateCount;
|
|
119
|
+
const minimal = redundant.length === 0 && overInjected.length === 0;
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
taskId,
|
|
123
|
+
requiredClosure,
|
|
124
|
+
selected: selectedSorted,
|
|
125
|
+
overInjected,
|
|
126
|
+
loadBearing,
|
|
127
|
+
redundant,
|
|
128
|
+
verdicts,
|
|
129
|
+
minimalityRatio,
|
|
130
|
+
minimal,
|
|
131
|
+
stats: {
|
|
132
|
+
selectedCount: selectedSorted.length,
|
|
133
|
+
requiredCount: requiredClosure.length,
|
|
134
|
+
candidateMinimalCount: candidateCount,
|
|
135
|
+
loadBearingCount: loadBearing.length,
|
|
136
|
+
redundantCount: redundant.length,
|
|
137
|
+
overInjectedCount: overInjected.length,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Convenience: list IDs flagged as over-injected context.
|
|
144
|
+
* Equivalent to `report.overInjected`.
|
|
145
|
+
*
|
|
146
|
+
* @param {MinimalityReport} report
|
|
147
|
+
* @returns {string[]}
|
|
148
|
+
*/
|
|
149
|
+
export function overInjectedIds(report) {
|
|
150
|
+
if (!report || !Array.isArray(report.overInjected)) return [];
|
|
151
|
+
return [...report.overInjected];
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Convenience: minimality ratio accessor with explicit zero-guard.
|
|
156
|
+
*
|
|
157
|
+
* @param {MinimalityReport} report
|
|
158
|
+
* @returns {number} ratio in [0, 1]
|
|
159
|
+
*/
|
|
160
|
+
export function minimalityRatio(report) {
|
|
161
|
+
if (!report) return 0;
|
|
162
|
+
if (typeof report.minimalityRatio !== "number") return 0;
|
|
163
|
+
if (report.minimalityRatio < 0) return 0;
|
|
164
|
+
if (report.minimalityRatio > 1) return 1;
|
|
165
|
+
return report.minimalityRatio;
|
|
166
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context Normalization — unify all captured context into ContextItem.
|
|
3
|
+
*
|
|
4
|
+
* Every raw capture record (tool_call, agent_message, file_modification,
|
|
5
|
+
* git_change, requirement_change, verification_result) is normalized
|
|
6
|
+
* into a canonical ContextItem:
|
|
7
|
+
* { id, content, source, type, timestamp, scope, relatedRequirements[], metadata }
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @typedef {Object} ContextItem
|
|
12
|
+
* @property {string} id - Unique identifier
|
|
13
|
+
* @property {string} content - Human-readable content / summary
|
|
14
|
+
* @property {string} source - Where the context originated
|
|
15
|
+
* @property {string} type - Category (tool_call, agent_message, etc.)
|
|
16
|
+
* @property {number} timestamp - Unix ms
|
|
17
|
+
* @property {string} scope - Scope boundary (session, requirement, task, project)
|
|
18
|
+
* @property {string[]} relatedRequirements - Related requirement IDs
|
|
19
|
+
* @property {Object} metadata - Extra metadata
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Normalize a single raw capture record into a ContextItem.
|
|
24
|
+
* @param {Object} record - Raw capture record
|
|
25
|
+
* @returns {ContextItem}
|
|
26
|
+
*/
|
|
27
|
+
export function normalizeContextItem(record) {
|
|
28
|
+
if (!record || typeof record !== "object") {
|
|
29
|
+
throw new TypeError("Record must be a non-null object");
|
|
30
|
+
}
|
|
31
|
+
if (!record.id || !record.type) {
|
|
32
|
+
throw new TypeError("Record must have id and type");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const content = extractContent(record);
|
|
36
|
+
const relatedRequirements = extractRelatedRequirements(record);
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
id: record.id,
|
|
40
|
+
content,
|
|
41
|
+
source: record.source || "unknown",
|
|
42
|
+
type: record.type,
|
|
43
|
+
timestamp: record.timestamp || Date.now(),
|
|
44
|
+
scope: record.scope || "session",
|
|
45
|
+
relatedRequirements,
|
|
46
|
+
metadata: record.metadata || {},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Normalize an array of raw records into ContextItems.
|
|
52
|
+
* @param {Object[]} records
|
|
53
|
+
* @returns {ContextItem[]}
|
|
54
|
+
*/
|
|
55
|
+
export function normalizeContextItems(records) {
|
|
56
|
+
if (!Array.isArray(records)) {
|
|
57
|
+
throw new TypeError("Records must be an array");
|
|
58
|
+
}
|
|
59
|
+
return records.map(normalizeContextItem);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function extractContent(record) {
|
|
63
|
+
const { type, content } = record;
|
|
64
|
+
|
|
65
|
+
// Agent messages: content is { role, content }
|
|
66
|
+
if (type === "agent_message" && content && typeof content === "object") {
|
|
67
|
+
return `[${content.role}] ${content.content || ""}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Tool calls / results: content is { toolName, params } or { toolName, result }
|
|
71
|
+
if ((type === "tool_call" || type === "tool_result") && content && typeof content === "object") {
|
|
72
|
+
const name = content.toolName || "unknown";
|
|
73
|
+
if (type === "tool_call") {
|
|
74
|
+
const paramsStr = content.params ? JSON.stringify(content.params).slice(0, 200) : "";
|
|
75
|
+
return `Tool call: ${name}(${paramsStr})`;
|
|
76
|
+
}
|
|
77
|
+
const resultStr = typeof content.result === "string" ? content.result.slice(0, 200) : "[non-string result]";
|
|
78
|
+
return `Tool result: ${name} → ${resultStr}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// File modifications: { filePath, action, details }
|
|
82
|
+
if (type === "file_modification" && content && typeof content === "object") {
|
|
83
|
+
return `File ${content.action}: ${content.filePath}${content.details ? ` — ${JSON.stringify(content.details).slice(0, 150)}` : ""}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Git changes: { action, details }
|
|
87
|
+
if (type === "git_change" && content && typeof content === "object") {
|
|
88
|
+
const hash = content.details?.hash ? ` (${content.details.hash.slice(0, 8)})` : "";
|
|
89
|
+
const msg = content.details?.message || "";
|
|
90
|
+
return `Git ${content.action}${hash}: ${msg}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Requirement changes: { action, requirement }
|
|
94
|
+
if (type === "requirement_change" && content && typeof content === "object") {
|
|
95
|
+
const req = content.requirement || {};
|
|
96
|
+
return `Requirement ${content.action}: ${req.id || "?"} — ${req.title || req.description || ""}`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Verification results: { status, details }
|
|
100
|
+
if (type === "verification_result" && content && typeof content === "object") {
|
|
101
|
+
const test = content.details?.testName || content.details?.assertion || "";
|
|
102
|
+
return `Verification ${content.status}: ${test}`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Fallback
|
|
106
|
+
if (typeof content === "string") return content;
|
|
107
|
+
if (content && typeof content === "object") return JSON.stringify(content).slice(0, 500);
|
|
108
|
+
return String(record.content ?? "");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function extractRelatedRequirements(record) {
|
|
112
|
+
const reqs = [];
|
|
113
|
+
|
|
114
|
+
// Check metadata
|
|
115
|
+
if (record.metadata?.requirementId) {
|
|
116
|
+
reqs.push(record.metadata.requirementId);
|
|
117
|
+
}
|
|
118
|
+
if (record.metadata?.requirementIds) {
|
|
119
|
+
reqs.push(...record.metadata.requirementIds);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Check content fields
|
|
123
|
+
if (record.content && typeof record.content === "object") {
|
|
124
|
+
const req = record.content.requirement;
|
|
125
|
+
if (req?.id) reqs.push(req.id);
|
|
126
|
+
if (record.content.requirementId) reqs.push(record.content.requirementId);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return [...new Set(reqs)];
|
|
130
|
+
}
|