@tea-agent/loop-agent 0.44.0-next.6 → 0.44.0-next.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/CHANGELOG.md +288 -454
- package/dist/build-stamp.json +3 -3
- package/dist/executors/dag-pi/guards.js +4 -0
- package/dist/executors/dag-pi/model-config.js +30 -0
- package/dist/{workflows/dag/frontend-plan-completeness.js → executors/dag-pi/plan/facts.js} +25 -41
- package/dist/executors/dag-pi/plan/ledger-contract.js +55 -0
- package/dist/executors/dag-pi/tools/contract-tools.js +515 -0
- package/dist/executors/dag-pi/tools/design-terminal-tools.js +156 -0
- package/dist/executors/dag-pi/tools/plan-decision-tools.js +519 -0
- package/dist/executors/dag-pi/tools/review-terminal-tools.js +156 -0
- package/dist/executors/dag-pi/tools/scout-evidence-tools.js +270 -0
- package/dist/executors/dag-pi-executor.js +64 -1907
- package/dist/shared/git-workspace-status.js +2 -0
- package/dist/task/frontend-preflight.js +1 -1
- package/dist/task/source-prepare/semantic-intake.js +1 -1
- package/dist/task/source-prepare/source-fidelity-pi.js +1 -1
- package/dist/worker/console/chat/assistant-content.js +5 -34
- package/dist/worker/console/chat/chat-event-store.js +27 -10
- package/dist/worker/console/chat/db-connections.js +72 -8
- package/dist/worker/console/chat/pi-runtime/custom-tools/sql-tools.js +52 -24
- package/dist/worker/console/chat/pi-runtime.js +34 -0
- package/dist/worker/console/chat/routes.js +138 -9
- package/dist/worker/console/chat/session-store.js +147 -19
- package/dist/worker/console/chat/turn-process.js +69 -23
- package/dist/worker/console/chat/user-turn-outline.js +19 -0
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-Brn2sPzL.js → abnfDiagram-N423BO3Z-r1NAPU_5.js} +1 -1
- package/dist/worker/console/static/assets/{arc-BIMNTG0W.js → arc-dT5T4sVL.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G--WtcgR_A.js → architectureDiagram-T3A2C74G-CP_cOq46.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-BT_Ztog1.js → blockDiagram-VBNYF7ZC-sToEZxEf.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-C5hbVr-l.js → c4Diagram-5PPSVZJV-DSxwwi2m.js} +1 -1
- package/dist/worker/console/static/assets/channel-CyBY_yGk.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-BKKnyR9Z.js → chunk-2GRJ4B5K-B9fh0IkF.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-BHs6biqA.js → chunk-2Q5K7J3B-CAUNl-A6.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-BdSFy_vP.js → chunk-5RXB4S5H-BomeqbNX.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-BpJIdTKV.js → chunk-5VM5RSS4-BNAuTOLE.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-C_iWJhkT.js → chunk-6Q2QTUOP-DfzjRD5y.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-BTbmx3-k.js → chunk-GF5L2VYU-C3uE-yc2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-D4Ee6DmP.js → chunk-JWPE2WC7-C3sQMMYr.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-B487SORR.js → chunk-KBJHAD2P-D_AtEYQL.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-BKYHjNrr.js → chunk-RYQCIY6F-DW4TwhKv.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-DrTdoYZG.js → chunk-XXDRQBXY-CTQDmJcp.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-D5lN4E_E.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-D5lN4E_E.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-CttUY_Jo.js → cose-bilkent-JH36ORCC-iMqPuBsL.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-B4Rm5gnR.js → cynefin-VYW2F7L2-DktIuDWs.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-ByxHBq_S.js → cynefinDiagram-MW4NZA55-BgVnjyEs.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-DGrfNFA0.js → dagre-VZM6K2ZE-CR25E4bu.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-KjrUPquv.js → diagram-7IWD3JNH-CPM2h5HY.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-VS4mlm75.js → diagram-B4RE2ZJO-DqF0x2g1.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-BLXYmFTM.js → diagram-LBJQPF4R-G8BYp2eb.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-C6xoFAqH.js → diagram-Q27KOJAE-BbC4kT_D.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-C478dCe7.js → diagram-UB23O5K3-CKZwZ-G5.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-DHEpW5zN.js → ebnfDiagram-BXEA7PRR-kJDmheia.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-CA5GKfo9.js → erDiagram-JOGREHBK-DFTVHyxB.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-zysi0Fl-.js → flowDiagram-UKHOOZJN-BqdN5_os.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-DGzcKA8Y.js → ganttDiagram-PKOTCBZU-SYDjVakh.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-CHsuIG1w.js → gitGraphDiagram-DS77QQ5N-Bf8bNpGA.js} +1 -1
- package/dist/worker/console/static/assets/index-B28Onmfy.css +1 -0
- package/dist/worker/console/static/assets/index-CTMZsDmh.js +486 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-BexZHPCp.js → infoDiagram-6WML65LV-DIeAmJ45.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-Gkx8q-DB.js → ishikawaDiagram-WSZJBQD7-oikqUAlo.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-XDW3qrJ7.js → journeyDiagram-NVQOT4AX-mKEF_xYT.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-DJ07eEaN.js → kanban-definition-27J2QSJJ-BdWJHPnN.js} +1 -1
- package/dist/worker/console/static/assets/{linear-DL-zeqOn.js → linear-DGRlieMH.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-C0HdXtOf.js → mermaid.core-4P9yPC9c.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-CqRX0lrt.js → mindmap-definition-FAOFIHXS-5PTSkos6.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-BVM9JZ2H.js → pegDiagram-VL7TDLO6-DONIFpG5.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-BA3ozdKk.js → pieDiagram-7S7Q4E2Y-D_Z4S70M.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-B-0_p9_4.js → quadrantDiagram-CIZ2JOQS-CAsjh8iY.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-DHRzPWFc.js → railroadDiagram-AXF67PYL-Cx4Dd6ac.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-9BEC_PcW.js → requirementDiagram-LRYGKXZP-cQb7mwyH.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-DMxeW4rN.js → sankeyDiagram-W5VNT64P-Cd-DhUdf.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DixP6LIU.js → sequenceDiagram-SI44F4Z6-AlKYRgIk.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-B_EifJBo.js → sizeCapture-X5ZJPWSS-CUy_ET4e.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-BwikwWbX.js → stateDiagram-OKZ733FA-CTuVe6Sa.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BsWhs8O7.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-C162l9o1.js → swimlanes-SLNWSIFB-ChFLJb-v.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-CJcioYGH.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-mpe_u1i4.js → timeline-definition-Z64GVDOM-DZZeiAPr.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-DyUk54HX.js → vennDiagram-T6HMQDX7-t4O91cZU.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-HYyMkzfm.js → wardleyDiagram-T6FBY63Y-CV5qGHZu.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-DRoh7skR.js → xychartDiagram-ELKLHX3M-DyXbytUI.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/operator-chat/chat-link.js +20 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +58 -3
- package/dist/worker/console/static-src/operator-chat/process-label.js +19 -6
- package/dist/worker/console/static-src/operator-chat/transcript-mode.js +21 -0
- package/dist/worker/console/static-src/operator-chat/turn-group-equality.js +2 -0
- package/dist/worker/console/static-src/operator-chat/turn-process-disclosure.js +13 -5
- package/dist/worker/console/static-src/operator-chat/turn-state-projection.js +166 -0
- package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +56 -2
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +202 -43
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +78 -23
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +55 -18
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +5 -2
- package/dist/worker/scheduler/scheduled-goal-dispatch.js +3 -2
- package/dist/worker/scheduler/scheduled-goal-evidence.js +6 -1
- package/package.json +1 -1
- package/dist/worker/console/static/assets/channel-DNWB4hpR.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-COhFgJji.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-COhFgJji.js +0 -1
- package/dist/worker/console/static/assets/index-CJh6pVLm.js +0 -482
- package/dist/worker/console/static/assets/index-C_kvKmFM.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-S2ZHMo1c.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-BZm4ByfV.js +0 -8
package/dist/build-stamp.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.44.0-next.
|
|
4
|
-
"gitSha": "
|
|
5
|
-
"builtAt": "2026-09-
|
|
3
|
+
"version": "0.44.0-next.8",
|
|
4
|
+
"gitSha": "e100bbbeba403ae8cbe6c9a93ccce76cbadf434e",
|
|
5
|
+
"builtAt": "2026-09-16T23:48:41.706Z"
|
|
6
6
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** DAG Pi 模型引用解析:纯配置叶子模块,零依赖,禁止反向依赖执行器入口。 */
|
|
2
|
+
export const DEFAULT_DAG_PI_PROVIDER = "wizard-local";
|
|
3
|
+
export const DAG_PI_MODEL_PROVIDERS = {
|
|
4
|
+
"gpt-5.3-codex-spark": "wizard-local",
|
|
5
|
+
"gpt-5.5": "wizard-local",
|
|
6
|
+
"glm-5.2": "wizard-local",
|
|
7
|
+
"deepseek-v4-flash": "deepseek",
|
|
8
|
+
"deepseek-v4-pro": "deepseek",
|
|
9
|
+
};
|
|
10
|
+
export function resolveDagPiModelConfig(modelReference, options) {
|
|
11
|
+
const separatorIndex = modelReference.indexOf("/");
|
|
12
|
+
const qualified = separatorIndex >= 0;
|
|
13
|
+
const provider = qualified
|
|
14
|
+
? modelReference.slice(0, separatorIndex)
|
|
15
|
+
: (DAG_PI_MODEL_PROVIDERS[modelReference] ?? DEFAULT_DAG_PI_PROVIDER);
|
|
16
|
+
const model = qualified
|
|
17
|
+
? modelReference.slice(separatorIndex + 1)
|
|
18
|
+
: modelReference;
|
|
19
|
+
if (!provider || !model) {
|
|
20
|
+
throw new Error(`invalid DAG Pi model reference "${modelReference}": expected non-empty provider/model`);
|
|
21
|
+
}
|
|
22
|
+
const explicitThinking = options?.thinking?.trim();
|
|
23
|
+
const thinking = explicitThinking ??
|
|
24
|
+
(provider === "wizard-local" && model === "gpt-5.5" ? "low" : undefined);
|
|
25
|
+
return {
|
|
26
|
+
provider,
|
|
27
|
+
model,
|
|
28
|
+
...(thinking ? { thinking } : {}),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return missing.map((item) => ({
|
|
4
|
-
...item,
|
|
5
|
-
owner: "Plan",
|
|
6
|
-
repairScope: item.kind === "state-registry" || item.kind === "mock-api"
|
|
7
|
-
? "global-phase"
|
|
8
|
-
: item.requirementIds.length > 1 ? "requirement-slice" : "fact",
|
|
9
|
-
nextAction: "replace-fact-and-finalize",
|
|
10
|
-
}));
|
|
11
|
-
}
|
|
1
|
+
/** DAG Pi plan ledger 完整性事实计算:纯类型与纯函数,禁止反向依赖执行器入口。 */
|
|
2
|
+
import { collectCanonicalStateFlowNames } from "../../../workflows/dag/frontend-contract-facts.js";
|
|
12
3
|
export function committedFactFromPlanRecord(value) {
|
|
13
4
|
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
14
5
|
return undefined;
|
|
@@ -76,9 +67,16 @@ export function collectFrontendPlanMissingFacts(input) {
|
|
|
76
67
|
});
|
|
77
68
|
continue;
|
|
78
69
|
}
|
|
79
|
-
|
|
70
|
+
// Verification targets are the single authoritative direction. The
|
|
71
|
+
// legacy requirement-side list is accepted only as a fallback while
|
|
72
|
+
// resuming older ledgers; new plans derive it from target.requirementIds.
|
|
73
|
+
const derivedTargetIds = [...verificationTargetRequirements.entries()]
|
|
74
|
+
.filter(([, requirementIds]) => requirementIds.has(id))
|
|
75
|
+
.map(([targetId]) => targetId);
|
|
76
|
+
const legacyTargetIds = Array.isArray(entry.verificationTargetIds)
|
|
80
77
|
? entry.verificationTargetIds.filter((value) => typeof value === "string" && value.trim().length > 0)
|
|
81
78
|
: [];
|
|
79
|
+
const targetIds = derivedTargetIds.length > 0 ? derivedTargetIds : legacyTargetIds;
|
|
82
80
|
const gap = entry.evidenceGap && typeof entry.evidenceGap === "object"
|
|
83
81
|
? entry.evidenceGap
|
|
84
82
|
: undefined;
|
|
@@ -104,7 +102,7 @@ export function collectFrontendPlanMissingFacts(input) {
|
|
|
104
102
|
}
|
|
105
103
|
}
|
|
106
104
|
}
|
|
107
|
-
return
|
|
105
|
+
return missing;
|
|
108
106
|
}
|
|
109
107
|
/** Completeness checks for phases whose facts are committed incrementally. */
|
|
110
108
|
export function collectFrontendPlanPhaseMissingFacts(input) {
|
|
@@ -123,54 +121,40 @@ export function collectFrontendPlanPhaseMissingFacts(input) {
|
|
|
123
121
|
];
|
|
124
122
|
}
|
|
125
123
|
if (input.phase === "ux-local") {
|
|
126
|
-
// One snapshot per check: no cross-revision cache to invalidate.
|
|
127
|
-
const required = new Set(input.behaviorRequiredRequirementIds ?? []);
|
|
128
|
-
const requested = new Set(input.requirementIds.filter(id => required.has(id)));
|
|
129
|
-
if (!requested.size)
|
|
130
|
-
return [];
|
|
131
|
-
const byRequirement = new Map();
|
|
132
|
-
for (const fact of facts) {
|
|
133
|
-
for (const id of new Set(planFactStringList(fact.scopeRequirementIds))) {
|
|
134
|
-
if (!requested.has(id))
|
|
135
|
-
continue;
|
|
136
|
-
const entries = byRequirement.get(id) ?? [];
|
|
137
|
-
entries.push(fact);
|
|
138
|
-
byRequirement.set(id, entries);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
const liveStateFlow = collectCanonicalStateFlowNames(facts);
|
|
142
124
|
const missing = [];
|
|
143
|
-
|
|
144
|
-
|
|
125
|
+
// Evaluate each behaviour requirement independently. A fact scoped to AC-1
|
|
126
|
+
// must not accidentally satisfy AC-2 merely because both ids share one
|
|
127
|
+
// UX session; shared facts remain valid when they explicitly list both ids.
|
|
128
|
+
for (const requirementId of input.requirementIds) {
|
|
129
|
+
if (!input.behaviorRequiredRequirementIds?.includes(requirementId))
|
|
145
130
|
continue;
|
|
146
|
-
const scopedFacts =
|
|
131
|
+
const scopedFacts = facts.filter((fact) => planFactScopeIntersects(fact, new Set([requirementId])));
|
|
147
132
|
const hasChoice = scopedFacts.some((fact) => fact.kind === "component-choice" &&
|
|
148
133
|
Array.isArray(fact.uiComponentChoices) &&
|
|
149
134
|
fact.uiComponentChoices.length > 0);
|
|
150
135
|
const canonicalStateFlow = collectCanonicalStateFlowNames(scopedFacts);
|
|
151
|
-
const hasStateFlow =
|
|
152
|
-
|
|
136
|
+
const hasStateFlow = canonicalStateFlow.uiStateNames.size > 0 ||
|
|
137
|
+
canonicalStateFlow.interactionNames.size > 0;
|
|
153
138
|
if (!hasChoice) {
|
|
154
139
|
missing.push({
|
|
155
140
|
kind: "component-choice",
|
|
156
|
-
requirementIds: [
|
|
141
|
+
requirementIds: [requirementId],
|
|
157
142
|
reason: "behaviour-required UX slice has no committed component-choice fact",
|
|
158
143
|
});
|
|
159
144
|
}
|
|
160
145
|
if (!hasStateFlow) {
|
|
161
146
|
missing.push({
|
|
162
147
|
kind: "state-flow",
|
|
163
|
-
requirementIds: [
|
|
148
|
+
requirementIds: [requirementId],
|
|
164
149
|
reason: "behaviour-required UX slice has no committed state-flow fact",
|
|
165
150
|
});
|
|
166
151
|
}
|
|
167
152
|
}
|
|
168
|
-
return
|
|
153
|
+
return missing;
|
|
169
154
|
}
|
|
170
155
|
const hasMockApi = facts.some((fact) => fact.kind === "mock-api");
|
|
171
|
-
const allInteractions = collectCanonicalStateFlowNames(
|
|
172
|
-
const
|
|
173
|
-
const liveInteractions = new Set([...collectCanonicalStateFlowNames(facts.filter(f => !planFactStringList(f.scopeRequirementIds).length || planFactScopeIntersects(f, requested))).interactionNames].filter(name => allInteractions.has(name)));
|
|
156
|
+
const allInteractions = collectCanonicalStateFlowNames(input.committedFacts).interactionNames;
|
|
157
|
+
const liveInteractions = new Set([...collectCanonicalStateFlowNames(facts.filter(f => !planFactStringList(f.scopeRequirementIds).length || planFactScopeIntersects(f, new Set(input.requirementIds)))).interactionNames].filter(name => allInteractions.has(name)));
|
|
174
158
|
const coveredInteractions = new Set(facts
|
|
175
159
|
.filter((fact) => fact.kind === "data-flow")
|
|
176
160
|
.flatMap((fact) => planFactStringList(fact.interactions)));
|
|
@@ -192,5 +176,5 @@ export function collectFrontendPlanPhaseMissingFacts(input) {
|
|
|
192
176
|
reason: `interaction ${interaction} has no committed data-flow fact`,
|
|
193
177
|
});
|
|
194
178
|
}
|
|
195
|
-
return
|
|
179
|
+
return missing;
|
|
196
180
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** DAG Pi plan ledger 契约与来源继承装载:纯类型与纯函数,禁止反向依赖执行器入口。 */
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { frontendExecutionSchema } from "../../../workflows/dag/frontend-execution-groups.js";
|
|
4
|
+
/**
|
|
5
|
+
* Source fidelity ledger (AC-005/AC-006): load the contract node's committed
|
|
6
|
+
* requirement facts and build a requirement-id → provenance map. The contract
|
|
7
|
+
* node declared sourceFragmentIds/sourceRefs from the ledger's
|
|
8
|
+
* requirement→fragment mapping; the plan inherits them by id so the compiled
|
|
9
|
+
* canonical contract carries authoritative provenance without the plan
|
|
10
|
+
* re-deriving (or fabricating) it. Best-effort: missing/unreadable contract
|
|
11
|
+
* ledger yields an empty map and the plan compiles as before (the design
|
|
12
|
+
* policy shell will then fail closed on missing provenance).
|
|
13
|
+
*/
|
|
14
|
+
export async function loadContractRequirementInheritance(runDir) {
|
|
15
|
+
const { readTypedEventStoreFromJsonl } = await import("../../../workflows/dag/frontend-typed-event-store.js");
|
|
16
|
+
let records;
|
|
17
|
+
try {
|
|
18
|
+
records = await readTypedEventStoreFromJsonl(path.join(runDir, "frontend-contract-pi", "contract-typed-facts.jsonl"));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return new Map();
|
|
22
|
+
}
|
|
23
|
+
const byId = new Map();
|
|
24
|
+
for (const record of records) {
|
|
25
|
+
const fact = record.fact;
|
|
26
|
+
if (!fact || typeof fact !== "object")
|
|
27
|
+
continue;
|
|
28
|
+
const recordFact = fact;
|
|
29
|
+
if (recordFact.origin !== "contract" ||
|
|
30
|
+
recordFact.kind !== "requirement") {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
// Contract requirement facts carry id/sourceFragmentIds/sourceRefs on
|
|
34
|
+
// the fact itself (origin=contract, kind=requirement, id, text, ...),
|
|
35
|
+
// not inside an `entry` wrapper.
|
|
36
|
+
const id = typeof recordFact.id === "string" ? recordFact.id : "";
|
|
37
|
+
if (!id)
|
|
38
|
+
continue;
|
|
39
|
+
const sourceFragmentIds = Array.isArray(recordFact.sourceFragmentIds)
|
|
40
|
+
? recordFact.sourceFragmentIds.filter((value) => typeof value === "string")
|
|
41
|
+
: undefined;
|
|
42
|
+
const sourceRefs = Array.isArray(recordFact.sourceRefs)
|
|
43
|
+
? recordFact.sourceRefs.filter((value) => typeof value === "string")
|
|
44
|
+
: undefined;
|
|
45
|
+
if (sourceFragmentIds || sourceRefs) {
|
|
46
|
+
byId.set(id, {
|
|
47
|
+
...(typeof recordFact.text === "string" ? { text: recordFact.text } : {}),
|
|
48
|
+
...(recordFact.execution !== undefined ? { execution: frontendExecutionSchema.parse(recordFact.execution) } : {}),
|
|
49
|
+
...(sourceFragmentIds ? { sourceFragmentIds } : {}),
|
|
50
|
+
...(sourceRefs ? { sourceRefs } : {}),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return byId;
|
|
55
|
+
}
|