@tea-agent/loop-agent 0.39.1 → 0.40.0-next.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/CHANGELOG.md +106 -116
- package/dist/build-stamp.json +3 -3
- package/dist/executors/dag-pi-executor.js +69 -7
- package/dist/executors/pi-executor.js +4 -2
- package/dist/executors/pi-sdk-executor.js +46 -1
- package/dist/executors/pi-writer-tool-policy.js +57 -1
- package/dist/executors/shell-executor.js +42 -2
- package/dist/executors/workspace-write-snapshot.js +68 -0
- package/dist/infrastructure/harness/atomic-write.js +23 -0
- package/dist/task/config-types.js +10 -0
- package/dist/worker/console/chat/chat-event-store.js +75 -5
- package/dist/worker/console/chat/context-panel.js +7 -0
- package/dist/worker/console/chat/deferred-turn.js +12 -0
- package/dist/worker/console/chat/pi-runtime.js +331 -18
- package/dist/worker/console/chat/provider-error.js +98 -0
- package/dist/worker/console/chat/routes.js +389 -56
- package/dist/worker/console/chat/session-stats.js +179 -0
- package/dist/worker/console/chat/session-store.js +93 -63
- package/dist/worker/console/chat/todos.js +115 -0
- package/dist/worker/console/chat/tool-preview.js +42 -0
- package/dist/worker/console/chat/turn-process.js +20 -55
- package/dist/worker/console/chat/user-questions.js +266 -0
- package/dist/worker/console/chat/workspace-landing.js +79 -0
- package/dist/worker/console/native-directory-picker.js +13 -0
- package/dist/worker/console/routes.js +309 -1
- package/dist/worker/console/security.js +4 -4
- package/dist/worker/console/server.js +529 -186
- package/dist/worker/console/static/assets/{abnfDiagram-N423BO3Z-CTx1TrNa.js → abnfDiagram-N423BO3Z-Bs-CDAXM.js} +1 -1
- package/dist/worker/console/static/assets/{arc-B4i9cVxX.js → arc-CAkA3We3.js} +1 -1
- package/dist/worker/console/static/assets/{architectureDiagram-T3A2C74G-BAXE8_Rl.js → architectureDiagram-T3A2C74G-DEmI_zqr.js} +1 -1
- package/dist/worker/console/static/assets/{blockDiagram-VBNYF7ZC-C5Xh59at.js → blockDiagram-VBNYF7ZC-uDHANebE.js} +1 -1
- package/dist/worker/console/static/assets/{c4Diagram-5PPSVZJV-B_asOzAu.js → c4Diagram-5PPSVZJV-Bv97b4_B.js} +1 -1
- package/dist/worker/console/static/assets/channel-amxUpk7o.js +1 -0
- package/dist/worker/console/static/assets/{chunk-2GRJ4B5K-wRO_iRNc.js → chunk-2GRJ4B5K-shmQKsFz.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-2Q5K7J3B-ByOaSh_G.js → chunk-2Q5K7J3B-BAraNvcN.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5RXB4S5H-DjLzudan.js → chunk-5RXB4S5H-BirhxUop.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-5VM5RSS4-JCNGkXYT.js → chunk-5VM5RSS4-C9LgUJpR.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-6Q2QTUOP-BhrPXXMZ.js → chunk-6Q2QTUOP-DrU-s-t7.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-GF5L2VYU-TJ5JuEBT.js → chunk-GF5L2VYU-Tx-H_FA2.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-JWPE2WC7-VVthn_mD.js → chunk-JWPE2WC7-BjLtNFrR.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-KBJHAD2P-D60-Mny4.js → chunk-KBJHAD2P-UNLVwSsy.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-RYQCIY6F-zXv7aVye.js → chunk-RYQCIY6F-CBEUX8XD.js} +1 -1
- package/dist/worker/console/static/assets/{chunk-XXDRQBXY-By9VQoi1.js → chunk-XXDRQBXY-WTL7IZOq.js} +1 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-bejwBVIz.js +1 -0
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-bejwBVIz.js +1 -0
- package/dist/worker/console/static/assets/{cose-bilkent-JH36ORCC-C4zQLe-M.js → cose-bilkent-JH36ORCC-CkHG6W3s.js} +1 -1
- package/dist/worker/console/static/assets/{cynefin-VYW2F7L2-wh5N2ReN.js → cynefin-VYW2F7L2-BRzFqTaL.js} +1 -1
- package/dist/worker/console/static/assets/{cynefinDiagram-MW4NZA55-Dlu5wIqs.js → cynefinDiagram-MW4NZA55-2_CFp_i7.js} +1 -1
- package/dist/worker/console/static/assets/{dagre-VZM6K2ZE-CrDgthc6.js → dagre-VZM6K2ZE-BJtsmdkE.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-7IWD3JNH-zN1clg27.js → diagram-7IWD3JNH-DNEFFo6w.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-B4RE2ZJO-BN-o7J7-.js → diagram-B4RE2ZJO-B_IWV7eo.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-LBJQPF4R-C8SuPt0d.js → diagram-LBJQPF4R-DvvRx2dz.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-Q27KOJAE-BoizuHbZ.js → diagram-Q27KOJAE-CsibsWLg.js} +1 -1
- package/dist/worker/console/static/assets/{diagram-UB23O5K3-BzUzXixG.js → diagram-UB23O5K3-les_djBQ.js} +1 -1
- package/dist/worker/console/static/assets/{ebnfDiagram-BXEA7PRR-Ev3lA4Cf.js → ebnfDiagram-BXEA7PRR-BEm2n7qJ.js} +1 -1
- package/dist/worker/console/static/assets/{erDiagram-JOGREHBK-GALUzRbs.js → erDiagram-JOGREHBK-BI7vHHVm.js} +1 -1
- package/dist/worker/console/static/assets/{flowDiagram-UKHOOZJN-CZJN65Sb.js → flowDiagram-UKHOOZJN-CUFCERrB.js} +1 -1
- package/dist/worker/console/static/assets/{ganttDiagram-PKOTCBZU-JLB9OESl.js → ganttDiagram-PKOTCBZU-wxyLiGWt.js} +1 -1
- package/dist/worker/console/static/assets/{gitGraphDiagram-DS77QQ5N-CcvCr4GD.js → gitGraphDiagram-DS77QQ5N-Bt897K8Z.js} +1 -1
- package/dist/worker/console/static/assets/index-BHhUOTri.css +1 -0
- package/dist/worker/console/static/assets/index-DqJbO3-p.js +407 -0
- package/dist/worker/console/static/assets/{infoDiagram-6WML65LV-HG5z7aVg.js → infoDiagram-6WML65LV-DYNx_IPv.js} +1 -1
- package/dist/worker/console/static/assets/{ishikawaDiagram-WSZJBQD7-BHEu9chR.js → ishikawaDiagram-WSZJBQD7-CzpLNEu6.js} +1 -1
- package/dist/worker/console/static/assets/{journeyDiagram-NVQOT4AX-Cp_Up8-a.js → journeyDiagram-NVQOT4AX-97f9owNU.js} +1 -1
- package/dist/worker/console/static/assets/{kanban-definition-27J2QSJJ-DvVeY-em.js → kanban-definition-27J2QSJJ-BxM9hyBn.js} +1 -1
- package/dist/worker/console/static/assets/{linear-aGmcjgTn.js → linear-ByuxcHvp.js} +1 -1
- package/dist/worker/console/static/assets/{mermaid.core-Biyo-tqA.js → mermaid.core-DwPGvpCv.js} +5 -5
- package/dist/worker/console/static/assets/{mindmap-definition-FAOFIHXS-DyxY2pIb.js → mindmap-definition-FAOFIHXS-DCoqG9RT.js} +1 -1
- package/dist/worker/console/static/assets/{pegDiagram-VL7TDLO6-CkdGuc50.js → pegDiagram-VL7TDLO6-BLSBmBMx.js} +1 -1
- package/dist/worker/console/static/assets/{pieDiagram-7S7Q4E2Y-NNQI9xVR.js → pieDiagram-7S7Q4E2Y-B0t_0oJW.js} +1 -1
- package/dist/worker/console/static/assets/{quadrantDiagram-CIZ2JOQS-PAJkuz_G.js → quadrantDiagram-CIZ2JOQS-sTzDk7Nt.js} +1 -1
- package/dist/worker/console/static/assets/{railroadDiagram-AXF67PYL-ZwrQod0O.js → railroadDiagram-AXF67PYL-B3jRdATC.js} +1 -1
- package/dist/worker/console/static/assets/{requirementDiagram-LRYGKXZP-D3ZfrzM2.js → requirementDiagram-LRYGKXZP-D-cTtXEN.js} +1 -1
- package/dist/worker/console/static/assets/{sankeyDiagram-W5VNT64P-DDGFmWk5.js → sankeyDiagram-W5VNT64P-B25igJRE.js} +1 -1
- package/dist/worker/console/static/assets/{sequenceDiagram-SI44F4Z6-DO6mmXTA.js → sequenceDiagram-SI44F4Z6-jW_lM1_D.js} +1 -1
- package/dist/worker/console/static/assets/{sizeCapture-X5ZJPWSS-DMbCQiJt.js → sizeCapture-X5ZJPWSS-CrzTgsHE.js} +1 -1
- package/dist/worker/console/static/assets/{stateDiagram-OKZ733FA-Di_YUEfC.js → stateDiagram-OKZ733FA-B01MvlqE.js} +1 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-BvFKEtm2.js +1 -0
- package/dist/worker/console/static/assets/{swimlanes-SLNWSIFB-Bn2PphNJ.js → swimlanes-SLNWSIFB-YcF12FiU.js} +2 -2
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DIB2eVg-.js +8 -0
- package/dist/worker/console/static/assets/{timeline-definition-Z64GVDOM-DPh8pRsp.js → timeline-definition-Z64GVDOM-ClnRcg2s.js} +1 -1
- package/dist/worker/console/static/assets/{vennDiagram-T6HMQDX7-GMfl26pW.js → vennDiagram-T6HMQDX7-B6gr_z-q.js} +1 -1
- package/dist/worker/console/static/assets/{wardleyDiagram-T6FBY63Y-DTlmVrmF.js → wardleyDiagram-T6FBY63Y-CvSgguGH.js} +1 -1
- package/dist/worker/console/static/assets/{xychartDiagram-ELKLHX3M-YGBjKAS5.js → xychartDiagram-ELKLHX3M-23OtSZCb.js} +1 -1
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/console-types.js +29 -4
- package/dist/worker/console/static-src/app/useConsoleShell.js +30 -12
- package/dist/worker/console/static-src/app/useOperatorActions.js +36 -6
- package/dist/worker/console/static-src/app/useRecoveryConsole.js +10 -11
- package/dist/worker/console/static-src/app/useRunProgress.js +2 -1
- package/dist/worker/console/static-src/app/useTaskWizard.js +2 -2
- package/dist/worker/console/static-src/night/useNightBoard.js +8 -5
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +141 -8
- package/dist/worker/console/static-src/operator-chat/compaction-message.js +79 -0
- package/dist/worker/console/static-src/operator-chat/details-dag-actions.js +122 -0
- package/dist/worker/console/static-src/operator-chat/refs.js +3 -0
- package/dist/worker/console/static-src/operator-chat/runtime-selection-labels.js +27 -0
- package/dist/worker/console/static-src/operator-chat/spatial-overlay.js +1 -2
- package/dist/worker/console/static-src/operator-chat/turn-stream-controller.js +25 -0
- package/dist/worker/console/static-src/operator-chat/turn-submission.js +3 -2
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +181 -87
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +159 -44
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +177 -8
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +63 -9
- package/dist/worker/console/static-src/operator-chat/useWorkspaceBrowserGate.js +4 -0
- package/dist/worker/console/static-src/operator-chat/workspace-layout-mode.js +3 -3
- package/dist/worker/console/static-src/shell/useWorkspaces.js +299 -0
- package/dist/worker/console/static-src/shell/workspace-route.js +339 -0
- package/dist/worker/console/workspace-context.js +234 -0
- package/dist/worker/console/workspace-registry.js +214 -0
- package/dist/worker/observe/server.js +4 -0
- package/dist/worker/observe/static/api.js +26 -6
- package/dist/worker/observe/static/app.js +18 -70
- package/dist/worker/observe/static/dag-node-purpose.d.ts +6 -0
- package/dist/worker/observe/static/dag-node-purpose.js +203 -0
- package/dist/worker/observe/static/index.html +1 -1
- package/dist/worker/observe/static/inspect-workspace.js +307 -0
- package/dist/worker/observe/static/operator-chrome.css +145 -20
- package/dist/worker/observe/static/operator-chrome.d.ts +20 -3
- package/dist/worker/observe/static/operator-chrome.js +330 -100
- package/dist/worker/observe/static/router.d.ts +46 -0
- package/dist/worker/observe/static/router.js +25 -1
- package/dist/worker/observe/static/state.d.ts +50 -0
- package/dist/worker/observe/static/state.js +174 -2
- package/dist/worker/observe/static/styles.css +348 -38
- package/dist/worker/observe/static/views/dag-graph.js +4 -2
- package/dist/worker/observe/static/views/dag-inspector.js +310 -156
- package/dist/worker/observe/static/views/dag.d.ts +13 -0
- package/dist/worker/observe/static/views/dag.js +6 -4
- package/dist/worker/observe/static/views/dashboard.js +6 -4
- package/dist/worker/observe/static/views/night.js +2 -2
- package/dist/worker/observe/static/views/pool.js +1 -0
- package/dist/worker/observe/static/views/run.js +3 -1
- package/dist/worker/observe/static/views/task.js +1 -1
- package/dist/workflows/dag/backend-test-pytest-collection.js +11 -10
- package/dist/workflows/dag/backend-test-writer-completeness.js +7 -12
- package/dist/workflows/dag/dynamic-runtime/map.js +1 -0
- package/dist/workflows/dag/init-hybrid.js +113 -47
- package/dist/workflows/dag/interrupt-request.js +3 -3
- package/dist/workflows/dag/lifecycle.js +3 -3
- package/dist/workflows/dag/types.js +20 -1
- package/docs/README.md +1 -0
- package/docs/operations/local-development-environment.md +21 -0
- package/docs/templates/agent-dag.schema.json +18 -0
- package/docs/templates/backend-test-dag.json +265 -237
- package/harness.json +3 -3
- package/package.json +3 -1
- package/dist/worker/console/static/assets/channel-Dj_4Moei.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-JCYQIIEL-C0YYAyCa.js +0 -1
- package/dist/worker/console/static/assets/classDiagram-v2-OCEON4UE-C0YYAyCa.js +0 -1
- package/dist/worker/console/static/assets/index-CW88Fjbw.js +0 -406
- package/dist/worker/console/static/assets/index-DP0ZJl39.css +0 -1
- package/dist/worker/console/static/assets/stateDiagram-v2-UEYNNEHI-DrdDvela.js +0 -1
- package/dist/worker/console/static/assets/swimlanesDiagram-ULZ7WXOC-DPkEAULl.js +0 -8
- package/dist/worker/console/static-src/operator-chat/activity-rail-presentation.js +0 -73
- package/dist/worker/console/static-src/operator-chat/useActivityRailTransition.js +0 -59
|
@@ -84,7 +84,7 @@ let dashboardLoadingNode = null;
|
|
|
84
84
|
|
|
85
85
|
/**
|
|
86
86
|
* 「昨夜班次」条带:夜间结果在观测侧的唯一一级呈现(替代旧「夜间任务」tab)。
|
|
87
|
-
* 管理动作(晨审处置)始终落在操作侧 /#/night,保持 Inspect 只读不变式。
|
|
87
|
+
* 管理动作(晨审处置)始终落在操作侧 /#/operate/night,保持 Inspect 只读不变式。
|
|
88
88
|
*/
|
|
89
89
|
async function renderNightStrip() {
|
|
90
90
|
const strip = document.getElementById("dashboard-night");
|
|
@@ -118,14 +118,14 @@ async function renderNightStrip() {
|
|
|
118
118
|
|
|
119
119
|
const actions = el("div", "night-strip-actions");
|
|
120
120
|
const detail = el("a", "page-action-btn", "夜间详情");
|
|
121
|
-
detail.href = "
|
|
121
|
+
detail.href = "/#/inspect/night";
|
|
122
122
|
detail.addEventListener("click", (e) => {
|
|
123
123
|
e.preventDefault();
|
|
124
124
|
navigate("/night");
|
|
125
125
|
});
|
|
126
126
|
actions.appendChild(detail);
|
|
127
127
|
const manage = el("a", "page-action-btn night-strip-manage", "晨审处置 →");
|
|
128
|
-
manage.href = "/#/night";
|
|
128
|
+
manage.href = "/#/operate/night";
|
|
129
129
|
manage.title = "夜间计划的管理与晨审处置在操作台完成(Inspect 保持只读)";
|
|
130
130
|
actions.appendChild(manage);
|
|
131
131
|
strip.appendChild(actions);
|
|
@@ -738,10 +738,12 @@ export function startDashboardPolling(scrollTo) {
|
|
|
738
738
|
const poll = async (initialScrollTo) => {
|
|
739
739
|
await renderDashboard(initialScrollTo);
|
|
740
740
|
if (generation !== uiState.pollingGeneration) return;
|
|
741
|
+
const delay = dashboardPollDelay();
|
|
742
|
+
if (delay == null) return;
|
|
741
743
|
uiState.dashboardTimer = setTimeout(() => {
|
|
742
744
|
uiState.dashboardTimer = null;
|
|
743
745
|
void poll();
|
|
744
|
-
},
|
|
746
|
+
}, delay);
|
|
745
747
|
};
|
|
746
748
|
void poll(scrollTo);
|
|
747
749
|
}
|
|
@@ -46,8 +46,8 @@ export async function renderNightJobs(scheduleId) {
|
|
|
46
46
|
showView("night");
|
|
47
47
|
bindNightToolbar();
|
|
48
48
|
const crumbs = [
|
|
49
|
-
{ label: UI_TEXT.dashboard, href: "
|
|
50
|
-
{ label: UI_TEXT.nightJobs, href: "
|
|
49
|
+
{ label: UI_TEXT.dashboard, href: "/#/inspect" },
|
|
50
|
+
{ label: UI_TEXT.nightJobs, href: "/#/inspect/night" },
|
|
51
51
|
];
|
|
52
52
|
if (scheduleId) crumbs.push({ label: scheduleId });
|
|
53
53
|
setBreadcrumb(crumbs);
|
|
@@ -93,6 +93,7 @@ function startPoolAutoPolling() {
|
|
|
93
93
|
if (generation !== uiState.pollingGeneration) return;
|
|
94
94
|
if (!poolAutoRefreshEnabled()) return;
|
|
95
95
|
const delay = isPageVisible() ? POOL_POLL_MS : dashboardPollDelay();
|
|
96
|
+
if (delay == null) return;
|
|
96
97
|
uiState.poolTimer = setTimeout(() => {
|
|
97
98
|
uiState.poolTimer = null;
|
|
98
99
|
void poll();
|
|
@@ -50,6 +50,7 @@ import {
|
|
|
50
50
|
} from "../relations.js";
|
|
51
51
|
import { copyText, renderRecommendedCommand } from "../copy.js";
|
|
52
52
|
import {
|
|
53
|
+
fetchWithWorkspaceScope,
|
|
53
54
|
isPageVisible,
|
|
54
55
|
detailPollDelay,
|
|
55
56
|
dashboardPollDelay,
|
|
@@ -126,7 +127,7 @@ export function renderInlineArtifactList(container, artifacts) {
|
|
|
126
127
|
list.appendChild(li);
|
|
127
128
|
void (async () => {
|
|
128
129
|
try {
|
|
129
|
-
const res = await
|
|
130
|
+
const res = await fetchWithWorkspaceScope(artifactUrl(artifactPath));
|
|
130
131
|
const text = await res.text();
|
|
131
132
|
if (!res.ok) {
|
|
132
133
|
let message = text;
|
|
@@ -444,6 +445,7 @@ export function startRunPolling(workerRunId, initial = true) {
|
|
|
444
445
|
const active = await renderRun(workerRunId, isInitial);
|
|
445
446
|
if (generation !== uiState.pollingGeneration || !active) return;
|
|
446
447
|
const delay = detailPollDelay("running", isPageVisible());
|
|
448
|
+
if (delay == null) return;
|
|
447
449
|
uiState.runPollTimer = setTimeout(() => {
|
|
448
450
|
uiState.runPollTimer = null;
|
|
449
451
|
void poll(false);
|
|
@@ -86,7 +86,7 @@ export async function renderTaskDetail(featureId, taskId) {
|
|
|
86
86
|
showView("task");
|
|
87
87
|
setBreadcrumb([
|
|
88
88
|
{ label: UI_TEXT.dashboard, href: "#/" },
|
|
89
|
-
{ label: "资源池", href: "
|
|
89
|
+
{ label: "资源池", href: "/#/inspect/pool" },
|
|
90
90
|
{ label: displayLabel },
|
|
91
91
|
]);
|
|
92
92
|
|
|
@@ -258,13 +258,14 @@ function bounded(value) {
|
|
|
258
258
|
? normalized
|
|
259
259
|
: `${normalized.slice(0, MAX_DIAGNOSTIC_CHARS)}\n...[truncated]`;
|
|
260
260
|
}
|
|
261
|
-
function collectionItems(stdout) {
|
|
261
|
+
function collectionItems(stdout, layout) {
|
|
262
|
+
const rootPrefix = `${(layout ?? resolveBackendTestLayout(undefined)).testRoot}/`;
|
|
262
263
|
return [...new Set(stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => {
|
|
263
264
|
if (!line.includes("::"))
|
|
264
265
|
return false;
|
|
265
266
|
if (/^(ERROR|FAILED|E\s+)/.test(line))
|
|
266
267
|
return false;
|
|
267
|
-
return
|
|
268
|
+
return line.replaceAll("\\", "/").startsWith(rootPrefix);
|
|
268
269
|
}).map((line) => line.replaceAll("\\", "/")))];
|
|
269
270
|
}
|
|
270
271
|
function escapeRegExp(value) {
|
|
@@ -416,7 +417,7 @@ function classifyCollectionFailure(output, evidence) {
|
|
|
416
417
|
return { status: "BLOCKED", kind: "unclassified-collection-error", detail: "collection failure cannot be safely attributed to generated testcase assets" };
|
|
417
418
|
}
|
|
418
419
|
export function assessBackendPytestCollection(input) {
|
|
419
|
-
const items = collectionItems(input.stdout);
|
|
420
|
+
const items = collectionItems(input.stdout, input.layout);
|
|
420
421
|
const fixtureResolution = input.fixtureResolution ?? { exitCode: 0, stdout: "fixture resolution assumed by direct assessor", stderr: "" };
|
|
421
422
|
if (input.exitCode === 0 && fixtureResolution.exitCode === 0) {
|
|
422
423
|
return backendPytestCollectionFactsSchema.parse({
|
|
@@ -740,7 +741,7 @@ export async function materializeBackendTestExecutionReadiness(input) {
|
|
|
740
741
|
if (input.effective.phase !== "effective" || input.effective.status !== "PASS" || input.effective.fixtureResolutionStatus !== "PASS") {
|
|
741
742
|
throw new Error("backend-test execution readiness requires effective collection and fixture-resolution PASS");
|
|
742
743
|
}
|
|
743
|
-
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.effective.mappedScripts);
|
|
744
|
+
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.effective.mappedScripts, { layout: input.layout });
|
|
744
745
|
assertSameInventory(input.effective, current);
|
|
745
746
|
const eligibility = input.eligibility ?? { eligibleItemIds: input.effective.collectedItemIds, excludedItems: [] };
|
|
746
747
|
const status = eligibility.eligibleItemIds.length === 0
|
|
@@ -839,7 +840,7 @@ async function firstUnreadableAssetPath(workspaceRoot, readiness) {
|
|
|
839
840
|
}
|
|
840
841
|
return undefined;
|
|
841
842
|
}
|
|
842
|
-
export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, readiness) {
|
|
843
|
+
export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, readiness, layout) {
|
|
843
844
|
if (!["PASS", "PARTIAL"].includes(readiness.status)) {
|
|
844
845
|
const counts = formatReadinessCounts(readiness);
|
|
845
846
|
const reasonTally = readiness.eligibleItemIds.length === 0 && readiness.excludedItems.length > 0
|
|
@@ -862,7 +863,7 @@ export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, re
|
|
|
862
863
|
}
|
|
863
864
|
let current;
|
|
864
865
|
try {
|
|
865
|
-
current = await buildBackendPytestAssetInventory(workspaceRoot, readiness.mappedScripts);
|
|
866
|
+
current = await buildBackendPytestAssetInventory(workspaceRoot, readiness.mappedScripts, { layout });
|
|
866
867
|
}
|
|
867
868
|
catch {
|
|
868
869
|
const fallbackPath = [...readiness.mappedScripts].sort()[0] ?? Object.keys(readiness.assetHashes).sort()[0] ?? "unknown";
|
|
@@ -897,11 +898,11 @@ export async function assertBackendTestExecutionReadinessFresh(workspaceRoot, re
|
|
|
897
898
|
}
|
|
898
899
|
}
|
|
899
900
|
}
|
|
900
|
-
export async function assertBackendPytestCollectionFresh(workspaceRoot, effective) {
|
|
901
|
+
export async function assertBackendPytestCollectionFresh(workspaceRoot, effective, layout) {
|
|
901
902
|
if (effective.phase !== "effective" || effective.status !== "PASS") {
|
|
902
903
|
throw new Error("backend pytest execution requires effective collection PASS facts");
|
|
903
904
|
}
|
|
904
|
-
const current = await buildBackendPytestAssetInventory(workspaceRoot, effective.mappedScripts);
|
|
905
|
+
const current = await buildBackendPytestAssetInventory(workspaceRoot, effective.mappedScripts, { layout });
|
|
905
906
|
const priorityOnly = priorityOnlyBackendPytestScripts(current.assetFiles);
|
|
906
907
|
if (priorityOnly.length > 0)
|
|
907
908
|
throw new Error(`priority-only-pytest-module: ${priorityOnly.join(", ")}`);
|
|
@@ -909,7 +910,7 @@ export async function assertBackendPytestCollectionFresh(workspaceRoot, effectiv
|
|
|
909
910
|
}
|
|
910
911
|
export async function materializeEffectiveBackendPytestCollection(input) {
|
|
911
912
|
if (input.initial.status === "PASS") {
|
|
912
|
-
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.initial.mappedScripts);
|
|
913
|
+
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.initial.mappedScripts, { layout: input.layout });
|
|
913
914
|
const priorityOnly = priorityOnlyBackendPytestScripts(current.assetFiles);
|
|
914
915
|
if (priorityOnly.length > 0)
|
|
915
916
|
throw new Error(`priority-only-pytest-module: ${priorityOnly.join(", ")}`);
|
|
@@ -927,7 +928,7 @@ export async function materializeEffectiveBackendPytestCollection(input) {
|
|
|
927
928
|
if (input.final.status !== "PASS")
|
|
928
929
|
throw new Error("backend pytest collection still fails after bounded repair");
|
|
929
930
|
await assertBackendPytestRepairSafety(input.workspaceRoot, input.initial, input.final);
|
|
930
|
-
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.final.mappedScripts);
|
|
931
|
+
const current = await buildBackendPytestAssetInventory(input.workspaceRoot, input.final.mappedScripts, { layout: input.layout });
|
|
931
932
|
const priorityOnly = priorityOnlyBackendPytestScripts(current.assetFiles);
|
|
932
933
|
if (priorityOnly.length > 0)
|
|
933
934
|
throw new Error(`priority-only-pytest-module: ${priorityOnly.join(", ")}`);
|
|
@@ -884,28 +884,23 @@ export function isBackendTestShardChildTask(task) {
|
|
|
884
884
|
task.id?.startsWith("generate-backend-pytest-case-"));
|
|
885
885
|
}
|
|
886
886
|
/**
|
|
887
|
-
*
|
|
888
|
-
*
|
|
889
|
-
*
|
|
890
|
-
* must NOT require module files to exist at plan time.
|
|
887
|
+
* Historical classifier for the Markdown plan node. Current backend-test N2
|
|
888
|
+
* is read-only and persists a run-owned plan.md, so writer completeness never
|
|
889
|
+
* invokes the workspace README assessment below for newly generated DAGs.
|
|
891
890
|
*/
|
|
892
891
|
export function isBackendTestMdPlanTask(task) {
|
|
893
892
|
return task.id === "generate-backend-md-plan-pi";
|
|
894
893
|
}
|
|
895
894
|
/**
|
|
896
|
-
*
|
|
897
|
-
*
|
|
898
|
-
* scripts are produced by the downstream map_agent children, so the Gate
|
|
899
|
-
* must NOT require mapped pytest scripts to exist at plan time.
|
|
895
|
+
* Historical classifier for the former shared-resources pytest writer. Current
|
|
896
|
+
* N7 is static and every map child writes one self-contained pytest module.
|
|
900
897
|
*/
|
|
901
898
|
export function isBackendTestPytestPlanTask(task) {
|
|
902
899
|
return task.id === "generate-backend-pytest-plan-pi";
|
|
903
900
|
}
|
|
904
901
|
/**
|
|
905
|
-
*
|
|
906
|
-
*
|
|
907
|
-
* index), WITHOUT requiring the indexed module files to exist yet — those are
|
|
908
|
-
* written by the downstream map_agent shard children.
|
|
902
|
+
* Legacy workspace-plan completeness helper retained for isolated historical
|
|
903
|
+
* fixtures. New DAGs validate the run-owned plan artifact in N3 instead.
|
|
909
904
|
*/
|
|
910
905
|
export async function assessBackendTestMdPlanCompleteness(workspaceRoot, layout) {
|
|
911
906
|
const resolvedPlan = layout ?? resolveBackendTestLayout(undefined);
|
|
@@ -26,6 +26,7 @@ export function buildExpandedChildTask(input) {
|
|
|
26
26
|
allowedPaths: renderDynamicPatternList(child.allowedPaths, item, index, expansion.itemName) ?? [],
|
|
27
27
|
forbiddenPaths: renderDynamicPatternList(child.forbiddenPaths, item, index, expansion.itemName) ?? [],
|
|
28
28
|
writeSet: renderDynamicPatternList(child.writeSet, item, index, expansion.itemName),
|
|
29
|
+
readSet: renderDynamicPatternList(child.readSet, item, index, expansion.itemName),
|
|
29
30
|
outputContract: child.outputContract,
|
|
30
31
|
writerOutcomePolicy: child.writerOutcomePolicy,
|
|
31
32
|
writeGuardPolicy: child.writeGuardPolicy,
|