specrails-desktop 2.59.2 → 2.60.0
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/client/dist/assets/{ActivityFeedPage-vAY9C71W.js → ActivityFeedPage-3J7fR8yB.js} +1 -1
- package/client/dist/assets/{AgentBrowserCapture-CpwjGXQm.js → AgentBrowserCapture-D4a3wYM1.js} +1 -1
- package/client/dist/assets/{AgentModeAnalyticsPane-BHeoJVxQ.js → AgentModeAnalyticsPane-Dps30tk9.js} +2 -2
- package/client/dist/assets/{AgentModeCodePane-B0Nf3YkN.js → AgentModeCodePane-CvLimey8.js} +2 -2
- package/client/dist/assets/{AgentModeJobsPane-CpbIItY_.js → AgentModeJobsPane-25tQlLpF.js} +1 -1
- package/client/dist/assets/{AgentsPage-BVJAFXn3.js → AgentsPage-CUDp_sfw.js} +2 -2
- package/client/dist/assets/{AnalyticsPage-DDWees-K.js → AnalyticsPage-DXWMGn8b.js} +1 -1
- package/client/dist/assets/{CodePage-CzV5tkvS.js → CodePage-D981zRHy.js} +1 -1
- package/client/dist/assets/{DesktopAnalyticsPage-DfRHNK7i.js → DesktopAnalyticsPage-BkFBq0E6.js} +1 -1
- package/client/dist/assets/{DocsDialog-BxduBYbh.js → DocsDialog-BL7uSbIJ.js} +1 -1
- package/client/dist/assets/{DocsPage-DOVeRJn_.js → DocsPage-CsDLbmZX.js} +1 -1
- package/client/dist/assets/{ExportDropdown-BnKVV8UK.js → ExportDropdown-B4Olg1Fk.js} +1 -1
- package/client/dist/assets/{InteractiveJobComposer-Da9dvM-0.js → InteractiveJobComposer-Z6fl4791.js} +2 -2
- package/client/dist/assets/JobDetailModal-DS_Owxs6.js +1 -0
- package/client/dist/assets/JobDetailPage-1TUQ9vlE.js +1 -0
- package/client/dist/assets/{JobsPage-0vdlbNik.js → JobsPage-BSrl8P7u.js} +1 -1
- package/client/dist/assets/LoopBuilderPage-Dh5uk2Qy.js +1 -0
- package/client/dist/assets/{LoopPreviewModal-Df-S8NGf.js → LoopPreviewModal-CH1r-KhU.js} +1 -1
- package/client/dist/assets/{LoopWindowSurface-sdb7QbSo.js → LoopWindowSurface-CiZdI6aw.js} +1 -1
- package/client/dist/assets/{LoopsPage-CDfCC9Px.js → LoopsPage-BwFujdGi.js} +1 -1
- package/client/dist/assets/{MinimizedChatsContext-DKlPf54Y.js → MinimizedChatsContext-BD2bsRBe.js} +1 -1
- package/client/dist/assets/PluginsPage-B8f49Mvn.js +2 -0
- package/client/dist/assets/{ProjectSettingsDialog-DOkjT7xv.js → ProjectSettingsDialog-D7q-O6h3.js} +1 -1
- package/client/dist/assets/{RepositoryDeliveries-CJVpOUpZ.js → RepositoryDeliveries-NNorcGzT.js} +1 -1
- package/client/dist/assets/{RepositoryScopeSelector-BeM-2gIZ.js → RepositoryScopeSelector-D-jb4bI_.js} +1 -1
- package/client/dist/assets/{ReviewPacketPage-EBCim2w_.js → ReviewPacketPage-DpZSzF-Q.js} +1 -1
- package/client/dist/assets/{TemplatePreviewModal-1-92UGwN.js → TemplatePreviewModal-5CZdAZ0G.js} +1 -1
- package/client/dist/assets/{TicketDetailModalContext-CkVXuHxU.js → TicketDetailModalContext-BHmtj1As.js} +1 -1
- package/client/dist/assets/{Trans-CzhPjnjB.js → Trans-wmTUDVyC.js} +1 -1
- package/client/dist/assets/{agentRuntime-TXPQowKJ.js → agentRuntime-7Ydcvr6P.js} +1 -1
- package/client/dist/assets/{agentRuntime-Bpx3yWHK.js → agentRuntime-BHVw9orA.js} +1 -1
- package/client/dist/assets/{agentRuntime-15Pkk6we.js → agentRuntime-DCPDaQcV.js} +1 -1
- package/client/dist/assets/{agentRuntime-C78n13To.js → agentRuntime-DKTw4Ajg.js} +1 -1
- package/client/dist/assets/{agentRuntime-CCI7XF4c.js → agentRuntime-DVhij_i_.js} +1 -1
- package/client/dist/assets/{agentRuntime-Ddqvp2bP.js → agentRuntime-Doss-T8o.js} +1 -1
- package/client/dist/assets/{agentRuntime-CKDHe2-a.js → agentRuntime-eZSMUlkM.js} +1 -1
- package/client/dist/assets/{agentRuntime-hqZRy08E.js → agentRuntime-qSSU7fQk.js} +1 -1
- package/client/dist/assets/agents-B6ZsnARo.js +1 -0
- package/client/dist/assets/agents-BORdhe0K.js +1 -0
- package/client/dist/assets/agents-C6aq9Oqs.js +1 -0
- package/client/dist/assets/agents-Cbsc4bcX.js +1 -0
- package/client/dist/assets/agents-D0uYR6hq.js +1 -0
- package/client/dist/assets/agents-Doe1sHY5.js +1 -0
- package/client/dist/assets/agents-DyNi_I9m.js +1 -0
- package/client/dist/assets/agents-StKxiTg0.js +1 -0
- package/client/dist/assets/agentstudio-7cYCXn-L.js +1 -0
- package/client/dist/assets/{agentstudio-QdAJIDef.js → agentstudio-BHWQh8G3.js} +1 -1
- package/client/dist/assets/agentstudio-BjnWHyRs.js +1 -0
- package/client/dist/assets/{agentstudio-fLXpRGIi.js → agentstudio-BkV8vcK4.js} +1 -1
- package/client/dist/assets/{agentstudio-BWAKeGgB.js → agentstudio-BzugqB_N.js} +1 -1
- package/client/dist/assets/{agentstudio-Cja8Sjcp.js → agentstudio-CWbp7KvH.js} +1 -1
- package/client/dist/assets/agentstudio-DG6plf5o.js +1 -0
- package/client/dist/assets/agentstudio-DkZVF-Cc.js +1 -0
- package/client/dist/assets/{formatDistanceToNow-DlQaXc7c.js → formatDistanceToNow-Dax4zqPF.js} +1 -1
- package/client/dist/assets/{getTimezoneOffsetInMilliseconds-DxUFGcVq.js → getTimezoneOffsetInMilliseconds-dpIo42JZ.js} +1 -1
- package/client/dist/assets/{index-Czov72g7.js → index-g8S62tpS.js} +7 -7
- package/client/dist/assets/jira-B6OYw4CJ.js +1 -0
- package/client/dist/assets/jira-BTF6RaOe.js +1 -0
- package/client/dist/assets/jira-CEetIB2q.js +1 -0
- package/client/dist/assets/jira-CIzsZLw5.js +1 -0
- package/client/dist/assets/{jira-BOoaUXbb.js → jira-Cq6yvN4q.js} +1 -1
- package/client/dist/assets/jira-Daw9tmpI.js +1 -0
- package/client/dist/assets/jira-FXr7u2lh.js +1 -0
- package/client/dist/assets/jira-LaNQn7yl.js +1 -0
- package/client/dist/assets/{jira-api-CbJvbRYx.js → jira-api-CLrIvXFm.js} +1 -1
- package/client/dist/assets/{jobs-DZAbh1m2.js → jobs-ARwD85B9.js} +1 -1
- package/client/dist/assets/{jobs-BD47Ov11.js → jobs-BMF1w4WT.js} +1 -1
- package/client/dist/assets/{jobs-tWjcDF_6.js → jobs-CBfzGLwm.js} +1 -1
- package/client/dist/assets/{jobs-CSrRx5lD.js → jobs-CPjiluBY.js} +1 -1
- package/client/dist/assets/{jobs-epP7gt8W.js → jobs-CQQd58pY.js} +1 -1
- package/client/dist/assets/{jobs-1G3wodhl.js → jobs-De3EqaO0.js} +1 -1
- package/client/dist/assets/{jobs-BLOoVRRl.js → jobs-Du9-Ei9a.js} +1 -1
- package/client/dist/assets/{jobs-B4pu8TdF.js → jobs-qMHbnxwC.js} +1 -1
- package/client/dist/assets/{project-repositories-BkBD3rxx.js → project-repositories-BkyT8AjU.js} +1 -1
- package/client/dist/assets/{spending-CYotH-9N.js → spending-Oov7p52A.js} +1 -1
- package/client/dist/assets/{useDesktop-DpxVGfUC.js → useDesktop-DpiS8Uov.js} +1 -1
- package/client/dist/assets/{useRuntimeRuns-CfGRbhr9.js → useRuntimeRuns-DBm1mul0.js} +1 -1
- package/client/dist/assets/{useSharedWebSocket-C17TGqT8.js → useSharedWebSocket-BZxKaVNT.js} +2 -2
- package/client/dist/index.html +19 -19
- package/docs/getting-started.md +2 -2
- package/docs/guide/de/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/de/agents/2-profiles-and-the-balanced-default.md +1 -1
- package/docs/guide/de/agents/3-customizing-models-per-agent.md +1 -1
- package/docs/guide/de/agents/4-custom-agents-catalog.md +3 -3
- package/docs/guide/en/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/en/agents/2-profiles-and-the-balanced-default.md +1 -1
- package/docs/guide/en/agents/3-customizing-models-per-agent.md +1 -1
- package/docs/guide/en/agents/4-custom-agents-catalog.md +3 -3
- package/docs/guide/es/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/es/agents/2-profiles-and-the-balanced-default.md +1 -1
- package/docs/guide/es/agents/3-customizing-models-per-agent.md +1 -1
- package/docs/guide/es/agents/4-custom-agents-catalog.md +3 -3
- package/docs/guide/fr/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/fr/agents/2-profiles-and-the-balanced-default.md +1 -1
- package/docs/guide/fr/agents/3-customizing-models-per-agent.md +1 -1
- package/docs/guide/fr/agents/4-custom-agents-catalog.md +3 -3
- package/docs/guide/it/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/it/agents/2-profiles-and-the-balanced-default.md +1 -1
- package/docs/guide/it/agents/3-customizing-models-per-agent.md +1 -1
- package/docs/guide/it/agents/4-custom-agents-catalog.md +3 -3
- package/docs/guide/ja/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/ja/agents/2-profiles-and-the-balanced-default.md +1 -1
- package/docs/guide/ja/agents/3-customizing-models-per-agent.md +1 -1
- package/docs/guide/ja/agents/4-custom-agents-catalog.md +3 -3
- package/docs/guide/pt/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/pt/agents/2-profiles-and-the-balanced-default.md +1 -1
- package/docs/guide/pt/agents/3-customizing-models-per-agent.md +1 -1
- package/docs/guide/pt/agents/4-custom-agents-catalog.md +3 -3
- package/docs/guide/zh/agents/1-meet-the-agents.md +1 -1
- package/docs/guide/zh/agents/2-profiles-and-the-balanced-default.md +1 -1
- package/docs/guide/zh/agents/3-customizing-models-per-agent.md +1 -1
- package/docs/guide/zh/agents/4-custom-agents-catalog.md +3 -3
- package/docs/internals/adding-a-provider.md +7 -6
- package/docs/internals/configuration.md +45 -0
- package/docs/internals/core-runtime-updates.md +19 -0
- package/docs/internals/loop-step-log-explorer.md +27 -0
- package/docs/internals/mission-rail-cards.md +7 -0
- package/docs/internals/profiles.md +17 -10
- package/docs/internals/review-packet.md +1 -1
- package/docs/internals/safe-pr-review-flow.md +9 -0
- package/docs/internals/source-map.md +6 -2
- package/docs/jira-integration-plan.md +7 -4
- package/docs/running-pipelines.md +2 -2
- package/package.json +1 -1
- package/server/dist/core-compat.js +7 -3
- package/server/dist/core-execution.js +5 -18
- package/server/dist/jira/jira-db.js +33 -6
- package/server/dist/jira/jira-materializer.js +11 -9
- package/server/dist/jira/jira-status-resolver.js +64 -22
- package/server/dist/jira/jira-sync-manager.js +40 -1
- package/server/dist/jira-router.js +8 -41
- package/server/dist/mcp/guide.js +4 -3
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-bridge.js +22 -70
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-controls.js +7 -4
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-settings.js +24 -1
- package/server/dist/modules/agent-runtime/runtime/agent-runtime-verification-log.js +252 -0
- package/server/dist/modules/agents/runtime/profiles-router.js +74 -36
- package/server/dist/modules/delivery/runtime/rail-relaunch.js +10 -2
- package/server/dist/modules/execution/runtime/queue-manager.js +7 -9
- package/server/dist/modules/loops/runtime/loop-agents.js +2 -5
- package/server/dist/modules/loops/runtime/loop-command-catalog.js +5 -5
- package/server/dist/modules/loops/runtime/loop-definition.js +1 -1
- package/server/dist/modules/loops/runtime/loop-executors.js +0 -2
- package/server/dist/modules/loops/runtime/loop-implement-recipe.js +5 -4
- package/server/dist/modules/loops/runtime/loop-run-manager.js +5 -3
- package/server/dist/modules/loops/runtime/loops-router.js +3 -1
- package/server/dist/path-resolver.js +41 -20
- package/server/dist/project-env.js +22 -6
- package/server/dist/providers/gemini-agent-ack.js +13 -10
- package/server/dist/setup-manager.js +28 -43
- package/server/dist/util/checkout-path.js +22 -0
- package/server/dist/workspace-manager.js +13 -71
- package/server/dist/worktree-node-modules.js +70 -34
- package/client/dist/assets/JobDetailModal-DhwKbZGe.js +0 -1
- package/client/dist/assets/JobDetailPage-MtPE-E_1.js +0 -1
- package/client/dist/assets/LoopBuilderPage-DCUHozXh.js +0 -1
- package/client/dist/assets/PluginsPage-iL0G3rQQ.js +0 -2
- package/client/dist/assets/agents-CA5eT1d0.js +0 -1
- package/client/dist/assets/agents-CAgy-5uS.js +0 -1
- package/client/dist/assets/agents-CNm6Qzlv.js +0 -1
- package/client/dist/assets/agents-CTwbx-fb.js +0 -1
- package/client/dist/assets/agents-DEGV1Vao.js +0 -1
- package/client/dist/assets/agents-HsDF1aQU.js +0 -1
- package/client/dist/assets/agents-IQjdA-z9.js +0 -1
- package/client/dist/assets/agents-RkGoteXh.js +0 -1
- package/client/dist/assets/agentstudio-B2CTtQgZ.js +0 -1
- package/client/dist/assets/agentstudio-DtfPcr99.js +0 -1
- package/client/dist/assets/agentstudio-X70BKf6u.js +0 -1
- package/client/dist/assets/agentstudio-qXKqVnWS.js +0 -1
- package/client/dist/assets/jira-BNZu8f9O.js +0 -1
- package/client/dist/assets/jira-BYVN4L2u.js +0 -1
- package/client/dist/assets/jira-CKJg3HZd.js +0 -1
- package/client/dist/assets/jira-DDDsZ4ub.js +0 -1
- package/client/dist/assets/jira-DXwYjVE4.js +0 -1
- package/client/dist/assets/jira-Dn6U2nRW.js +0 -1
- package/client/dist/assets/jira-j7hVolR5.js +0 -1
- package/server/dist/modules/loops/runtime/loop-agent-defaults.json +0 -6
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createVerificationLogProjection = createVerificationLogProjection;
|
|
4
|
+
const node_util_1 = require("node:util");
|
|
5
|
+
const object = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
6
|
+
const text = (value) => typeof value === 'string' ? value : '';
|
|
7
|
+
const display = (value, limit = 512) => (0, node_util_1.stripVTControlCharacters)(value).replace(/[\r\n]/g, ' ').slice(0, limit);
|
|
8
|
+
const attemptId = (event) => typeof event.attemptId === 'string' && event.attemptId.length <= 256 && event.attemptId.trim() ? event.attemptId : undefined;
|
|
9
|
+
const output = (value, id) => ({ text: value, ...(id ? { attemptId: id } : {}) });
|
|
10
|
+
const scope = (event) => JSON.stringify([event.runId, event.scopeId, event.nodePath, event.attemptId, event.attempt, event.visit]
|
|
11
|
+
.map(value => typeof value === 'string' && value.length <= 512 || typeof value === 'number' && Number.isSafeInteger(value) ? value : null));
|
|
12
|
+
const reference = 'Details → Verification evidence (stdout/stderr; retained evidence may be truncated)';
|
|
13
|
+
const shortPrefix = (value) => value.length > 96 ? value.slice(0, 92) + '…] ' : value;
|
|
14
|
+
/** This is presentation only. Neither its heuristics nor check progress can
|
|
15
|
+
* certify a candidate; original runtime events and command evidence are untouched. */
|
|
16
|
+
function createVerificationLogProjection() {
|
|
17
|
+
const streams = new Map();
|
|
18
|
+
const active = new Map();
|
|
19
|
+
let overflow = false;
|
|
20
|
+
const binding = (event, repository) => JSON.stringify([scope(event), repository]);
|
|
21
|
+
function get(key, event, prefix) {
|
|
22
|
+
let state = streams.get(key);
|
|
23
|
+
if (!state && streams.size < 64) {
|
|
24
|
+
state = { scope: scope(event), attemptId: attemptId(event), prefix: shortPrefix(prefix), tap: false, failed: false, yaml: false, inputLines: null, inputShortened: false,
|
|
25
|
+
headLines: 0, headChars: 0, shown: new Set(), diagnostics: [[], [], [], []], summaries: new Map(), tail: [], previous: [], context: 0, omitted: 0, announced: false };
|
|
26
|
+
streams.set(key, state);
|
|
27
|
+
}
|
|
28
|
+
return state;
|
|
29
|
+
}
|
|
30
|
+
function omitted(state) {
|
|
31
|
+
state.omitted++;
|
|
32
|
+
if (state.announced)
|
|
33
|
+
return '';
|
|
34
|
+
state.announced = true;
|
|
35
|
+
return state.prefix + '[Verbose output omitted; ' + reference + ']\n';
|
|
36
|
+
}
|
|
37
|
+
function diagnostic(state, line, priority) {
|
|
38
|
+
const bounded = line.slice(0, priority === 3 ? 256 : 512), bucket = state.diagnostics[priority];
|
|
39
|
+
if (state.shown.has(line) || bucket.includes(bounded))
|
|
40
|
+
return;
|
|
41
|
+
// First fact plus three recent facts in each class; warnings cannot consume
|
|
42
|
+
// the compiler/assertion budget, and later failures remain represented.
|
|
43
|
+
if (bucket.length === (priority === 3 ? 2 : 4))
|
|
44
|
+
bucket.splice(1, 1);
|
|
45
|
+
bucket.push(bounded);
|
|
46
|
+
}
|
|
47
|
+
function priority(body) {
|
|
48
|
+
if (/^(?!['"`]|(?:actual|expected|source):).+(?:\(\d+,\d+\)|:\d+(?::\d+)?)(?::|\s+-)?\s+(?:fatal\s+)?error\b/i.test(body)
|
|
49
|
+
|| /^(?:fatal\s+)?error\s+[A-Z]+\d+\s*:/.test(body)
|
|
50
|
+
|| /^(?:AssertionError|TypeError|ReferenceError|SyntaxError|RangeError)\b/.test(body))
|
|
51
|
+
return 0;
|
|
52
|
+
if (/^(?:FAIL\s|not ok \d+\b|[✖✗]\s|(?:fatal\s+)?error(?:\s*\[[^\]]+\])?\s*:)/i.test(body)
|
|
53
|
+
&& !/\b0 errors?\b/i.test(body))
|
|
54
|
+
return 1;
|
|
55
|
+
if (/^(?:expected|actual|operator|test at|location)\s*[: ]/i.test(body))
|
|
56
|
+
return 2;
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
function summary(body) {
|
|
60
|
+
if (/^Ran all test suites[.\s]*$/.test(body))
|
|
61
|
+
return 'ran';
|
|
62
|
+
const match = body.match(/^(Test Suites|Test Files|Tests|Snapshots|Time|Duration|Ran all test suites)\s*:?\s/i)
|
|
63
|
+
?? body.match(/^(?:#|ℹ)\s*(tests|suites|pass|fail|cancelled|skipped|todo|duration_ms|duration)\b/i);
|
|
64
|
+
return match?.[1].toLowerCase();
|
|
65
|
+
}
|
|
66
|
+
function line(state, original, body) {
|
|
67
|
+
let value = original;
|
|
68
|
+
if (/AssertionError\b.*\bInput:\s*$/.test(body))
|
|
69
|
+
state.inputLines = 0;
|
|
70
|
+
else if (state.inputLines !== null) {
|
|
71
|
+
if (/^["'`]/.test(body)) {
|
|
72
|
+
state.inputLines++;
|
|
73
|
+
if (state.inputLines > 2) {
|
|
74
|
+
if (state.inputShortened)
|
|
75
|
+
return '';
|
|
76
|
+
state.inputShortened = true;
|
|
77
|
+
return state.prefix + '[Assertion input shortened; inspect raw evidence]\n';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else if (!body)
|
|
81
|
+
return '';
|
|
82
|
+
else
|
|
83
|
+
state.inputLines = null;
|
|
84
|
+
}
|
|
85
|
+
if (/^[✔✓]\s/.test(body))
|
|
86
|
+
return '';
|
|
87
|
+
if (/^PASS\s/.test(body))
|
|
88
|
+
return omitted(state);
|
|
89
|
+
if (/^[✖✗]\s/.test(body))
|
|
90
|
+
state.failed = true;
|
|
91
|
+
if (/^TAP version |^# Subtest:/.test(body)) {
|
|
92
|
+
state.tap = true;
|
|
93
|
+
return '';
|
|
94
|
+
}
|
|
95
|
+
if (/^(?:not )?ok \d+\b/.test(body)) {
|
|
96
|
+
state.tap = true;
|
|
97
|
+
state.failed = body.startsWith('not ok');
|
|
98
|
+
state.yaml = false;
|
|
99
|
+
if (!state.failed)
|
|
100
|
+
return '';
|
|
101
|
+
}
|
|
102
|
+
if (state.tap) {
|
|
103
|
+
if (body === '---') {
|
|
104
|
+
state.yaml = true;
|
|
105
|
+
if (!state.failed)
|
|
106
|
+
return '';
|
|
107
|
+
}
|
|
108
|
+
if (body === '...') {
|
|
109
|
+
state.yaml = false;
|
|
110
|
+
if (!state.failed)
|
|
111
|
+
return '';
|
|
112
|
+
}
|
|
113
|
+
if (state.yaml && !state.failed)
|
|
114
|
+
return '';
|
|
115
|
+
if (/^1\.\.\d+$/.test(body))
|
|
116
|
+
return '';
|
|
117
|
+
}
|
|
118
|
+
if (!body)
|
|
119
|
+
return '';
|
|
120
|
+
if (value.length > 2_000)
|
|
121
|
+
value = value.slice(0, 1_900) + '\n[Long diagnostic line shortened; inspect raw evidence]';
|
|
122
|
+
const total = summary(body);
|
|
123
|
+
if (total) {
|
|
124
|
+
// Known totals have a fixed key set, so repeated progress updates do not
|
|
125
|
+
// become another unbounded stream or evict diagnostics.
|
|
126
|
+
state.summaries.set(total, state.prefix + body.slice(0, 128));
|
|
127
|
+
return '';
|
|
128
|
+
}
|
|
129
|
+
const rank = priority(body.slice(0, 2_000));
|
|
130
|
+
if (state.headLines < 24 && state.headChars + value.length <= 3_500) {
|
|
131
|
+
state.headLines++;
|
|
132
|
+
state.headChars += value.length;
|
|
133
|
+
state.shown.add(value);
|
|
134
|
+
state.previous.push(value);
|
|
135
|
+
if (state.previous.length > 2)
|
|
136
|
+
state.previous.shift();
|
|
137
|
+
return value + '\n';
|
|
138
|
+
}
|
|
139
|
+
if (rank !== undefined) {
|
|
140
|
+
if (rank < 2) {
|
|
141
|
+
for (const preceding of state.previous)
|
|
142
|
+
diagnostic(state, preceding, 3);
|
|
143
|
+
state.context = 3;
|
|
144
|
+
}
|
|
145
|
+
diagnostic(state, value, rank);
|
|
146
|
+
}
|
|
147
|
+
else if (state.context > 0) {
|
|
148
|
+
diagnostic(state, value, 3);
|
|
149
|
+
state.context--;
|
|
150
|
+
}
|
|
151
|
+
state.previous.push(value);
|
|
152
|
+
if (state.previous.length > 2)
|
|
153
|
+
state.previous.shift();
|
|
154
|
+
state.tail.push(value.slice(0, 256));
|
|
155
|
+
if (state.tail.length > 6)
|
|
156
|
+
state.tail.shift();
|
|
157
|
+
return omitted(state);
|
|
158
|
+
}
|
|
159
|
+
function flush(key) {
|
|
160
|
+
const result = [];
|
|
161
|
+
for (const [id, state] of streams) {
|
|
162
|
+
if (key !== undefined && id !== key)
|
|
163
|
+
continue;
|
|
164
|
+
let content = '';
|
|
165
|
+
const pending = [...state.diagnostics.flat(), ...state.tail, ...state.summaries.values()];
|
|
166
|
+
const seen = new Set(state.shown);
|
|
167
|
+
for (const value of pending)
|
|
168
|
+
if (!seen.has(value)) {
|
|
169
|
+
seen.add(value);
|
|
170
|
+
content += value + '\n';
|
|
171
|
+
}
|
|
172
|
+
if (state.omitted)
|
|
173
|
+
content += state.prefix + `[${state.omitted} output lines compacted; ${reference}]\n`;
|
|
174
|
+
if (content)
|
|
175
|
+
result.push(output(content, state.attemptId));
|
|
176
|
+
streams.delete(id);
|
|
177
|
+
for (const [name, activeId] of active)
|
|
178
|
+
if (activeId === id)
|
|
179
|
+
active.delete(name);
|
|
180
|
+
}
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
function project(event) {
|
|
184
|
+
if (event.type === 'verification-output' && typeof event.text === 'string') {
|
|
185
|
+
const result = [];
|
|
186
|
+
for (const value of (0, node_util_1.stripVTControlCharacters)(event.text).split('\n')) {
|
|
187
|
+
if (!value)
|
|
188
|
+
continue;
|
|
189
|
+
const match = value.match(/^(\[verification ([^/\]]+)\/[^\]]+\] )?(.*)$/);
|
|
190
|
+
const prefix = match?.[1] ?? '', repository = match?.[2] ?? '', body = (match?.[3] ?? value).trim();
|
|
191
|
+
const key = active.get(binding(event, repository)) ?? JSON.stringify([scope(event), prefix.slice(0, 1024)]);
|
|
192
|
+
const state = get(key, event, prefix);
|
|
193
|
+
if (state) {
|
|
194
|
+
const content = line(state, shortPrefix(prefix) + (match?.[3] ?? value), body);
|
|
195
|
+
if (content)
|
|
196
|
+
result.push(output(content, state.attemptId));
|
|
197
|
+
}
|
|
198
|
+
else if (!overflow) {
|
|
199
|
+
overflow = true;
|
|
200
|
+
result.push(output(`[Additional verification output omitted; ${reference}]\n`, attemptId(event)));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|
|
205
|
+
if (event.type === 'runtime-efficiency-event') {
|
|
206
|
+
const data = object(event.payload) ? { ...event, ...event.payload } : event;
|
|
207
|
+
const kind = text(data.kind), id = text(data.executionId), repository = text(data.repositoryId), label = text(data.label);
|
|
208
|
+
if (!['check-started', 'check-finished', 'check-reused', 'check-invalidated'].includes(kind) || !id || id.length > 256 || !repository || repository.length > 256 || !label || label.length > 4096)
|
|
209
|
+
return [];
|
|
210
|
+
const prefix = `[verification ${display(repository)}/${display(label)}] `;
|
|
211
|
+
const key = JSON.stringify([scope(data), id]), name = binding(data, repository);
|
|
212
|
+
if (kind === 'check-started') {
|
|
213
|
+
if (active.get(name) === key)
|
|
214
|
+
return [];
|
|
215
|
+
const result = active.has(name) ? flush(active.get(name)) : [];
|
|
216
|
+
if (get(key, data, prefix))
|
|
217
|
+
active.set(name, key);
|
|
218
|
+
result.push(output(prefix + 'started\n', attemptId(data)));
|
|
219
|
+
return result;
|
|
220
|
+
}
|
|
221
|
+
if (kind === 'check-invalidated')
|
|
222
|
+
return [output(prefix + 'evidence invalidated' + (typeof data.reason === 'string' ? ': ' + display(data.reason) : '') + '\n', attemptId(data))];
|
|
223
|
+
if (!Number.isSafeInteger(data.exitCode) || typeof data.durationMs !== 'number' || !Number.isFinite(data.durationMs) || data.durationMs < 0)
|
|
224
|
+
return [];
|
|
225
|
+
const result = flush(key);
|
|
226
|
+
return [...result, output(prefix + `${kind === 'check-reused' ? 'reused' : data.exitCode === 0 ? 'command passed' : 'command failed'} (exit ${data.exitCode}, ${(data.durationMs / 1000).toFixed(1)} s)\n`, attemptId(data))];
|
|
227
|
+
}
|
|
228
|
+
if (event.type === 'runtime-result')
|
|
229
|
+
return flush();
|
|
230
|
+
if (event.type === 'workflow-event' && object(event.event)) {
|
|
231
|
+
const data = event.event, kind = text(data.type);
|
|
232
|
+
if (/^workflow_(?:succeeded|failed|cancelled|paused)$/.test(kind))
|
|
233
|
+
return flush();
|
|
234
|
+
if (!/^step_(?:started|succeeded|failed|cancelled|interrupted)$/.test(kind))
|
|
235
|
+
return [];
|
|
236
|
+
const result = [];
|
|
237
|
+
for (const [key, state] of streams) {
|
|
238
|
+
const identity = JSON.parse(state.scope);
|
|
239
|
+
// Older transports lack attempt identity. Flush them before a phase
|
|
240
|
+
// boundary; v2 flushes only the ending attempt, leaving siblings intact.
|
|
241
|
+
const legacy = identity[2] === null && identity[3] === null;
|
|
242
|
+
const sameAttempt = typeof data.attemptId === 'string' && identity[3] === data.attemptId;
|
|
243
|
+
const sameNode = !data.attemptId && (data.nodePath ?? data.stepId) === identity[2] && (!data.scopeId || data.scopeId === identity[1]);
|
|
244
|
+
if (legacy || (kind !== 'step_started' && (sameAttempt || sameNode)))
|
|
245
|
+
result.push(...flush(key));
|
|
246
|
+
}
|
|
247
|
+
return result;
|
|
248
|
+
}
|
|
249
|
+
return [];
|
|
250
|
+
}
|
|
251
|
+
return { project, flush };
|
|
252
|
+
}
|
|
@@ -18,6 +18,8 @@ const providers_1 = require("../../../providers");
|
|
|
18
18
|
const kimi_skill_prompt_1 = require("../../../providers/kimi-skill-prompt");
|
|
19
19
|
const profile_manager_1 = require("./profile-manager");
|
|
20
20
|
const workspace_resolution_1 = require("../../../workspace-resolution");
|
|
21
|
+
const agent_runtime_loader_1 = require("../../agent-runtime/runtime/agent-runtime-loader");
|
|
22
|
+
const agent_runtime_settings_1 = require("../../agent-runtime/runtime/agent-runtime-settings");
|
|
21
23
|
const project_router_helpers_1 = require("../../../project-router-helpers");
|
|
22
24
|
/**
|
|
23
25
|
* Relocate-artifacts gate: the dir whose `.specrails/{profiles,specrails-version}`
|
|
@@ -70,6 +72,30 @@ function agentsCatalogDir(project, provider) {
|
|
|
70
72
|
function listAgentFiles(project, provider) {
|
|
71
73
|
return (0, agent_catalog_1.listNativeAgentFiles)(specRoot(project), provider ?? project.provider ?? 'claude');
|
|
72
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* The baseline roles are identifiers of runtime-defined roles: specrails-core
|
|
77
|
+
* never reads an `sr-*` file for them. Their read-only catalog body is the Core
|
|
78
|
+
* runtime definition (defaults merged with the global Settings overrides).
|
|
79
|
+
*/
|
|
80
|
+
const BASELINE_RUNTIME_ROLES = {
|
|
81
|
+
'sr-architect': 'architect',
|
|
82
|
+
'sr-developer': 'developer',
|
|
83
|
+
'sr-reviewer': 'reviewer',
|
|
84
|
+
};
|
|
85
|
+
const RUNTIME_DEFINED_DESCRIPTION = 'Runtime-defined by specrails-core: the implement pipeline runs this role from the Core runtime definition below, not from an installed file.';
|
|
86
|
+
async function loadRuntimeRoleDefinitions() {
|
|
87
|
+
try {
|
|
88
|
+
const runtime = await (0, agent_runtime_loader_1.loadCoreAgentRuntime)();
|
|
89
|
+
return { prompts: { ...runtime.rolePromptDefaults(), ...(0, agent_runtime_settings_1.loadRuntimeRolePrompts)() } };
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
return { prompts: {}, error: error instanceof Error ? error.message : 'Core role prompt catalog is unavailable' };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function runtimeRoleBody(definitions, agentId) {
|
|
96
|
+
const role = BASELINE_RUNTIME_ROLES[agentId];
|
|
97
|
+
return role ? definitions.prompts[role] : undefined;
|
|
98
|
+
}
|
|
73
99
|
const AGENTS_SECTION_ENABLED = process.env.SPECRAILS_AGENTS_SECTION !== 'false';
|
|
74
100
|
function handleError(res, err) {
|
|
75
101
|
if (err instanceof profile_manager_1.ProfileValidationError) {
|
|
@@ -175,12 +201,11 @@ function createProfilesRouter() {
|
|
|
175
201
|
? new Map((0, project_router_helpers_1.readAgentModels)({ ...project, provider })
|
|
176
202
|
.map((entry) => [entry.name, entry.model]))
|
|
177
203
|
: null;
|
|
178
|
-
const
|
|
179
|
-
if (!fs_1.default.existsSync(agentsDir)) {
|
|
180
|
-
res.status(400).json({ error: `no ${adapter.projectDirName} roles catalog found` });
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
204
|
+
const baseline = [...adapter.baselineAgents()];
|
|
183
205
|
const agents = [];
|
|
206
|
+
// Role files are optional: Core >= 6.3 defines the baseline roles in its
|
|
207
|
+
// runtime. Read `model:` only from `sr-*` files that still exist (older
|
|
208
|
+
// installs); every other baseline id is seeded with the adapter default.
|
|
184
209
|
for (const entry of listAgentFiles(project, provider)) {
|
|
185
210
|
if (!entry.id.startsWith('sr-'))
|
|
186
211
|
continue;
|
|
@@ -202,13 +227,10 @@ function createProfilesRouter() {
|
|
|
202
227
|
}
|
|
203
228
|
agents.push({ id, model });
|
|
204
229
|
}
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
error: `missing baseline agents in this project: ${missing.join(', ')}. Run 'npx specrails-core@latest update' first.`,
|
|
210
|
-
});
|
|
211
|
-
return;
|
|
230
|
+
for (const id of baseline) {
|
|
231
|
+
if (agents.some((a) => a.id === id))
|
|
232
|
+
continue;
|
|
233
|
+
agents.push({ id, model: projectedKimiModels?.get(id) ?? adapter.defaultModel() });
|
|
212
234
|
}
|
|
213
235
|
// Order: baseline trio first (architect, developer, reviewer), optional
|
|
214
236
|
// agents in the middle. sr-merge-resolver is no longer a baseline agent;
|
|
@@ -379,39 +401,44 @@ function createProfilesRouter() {
|
|
|
379
401
|
}
|
|
380
402
|
});
|
|
381
403
|
// GET /api/projects/:projectId/profiles/catalog
|
|
382
|
-
// List
|
|
383
|
-
|
|
404
|
+
// List the selected provider's roles: the runtime-defined baseline (upstream,
|
|
405
|
+
// synthesized from the adapter) plus the native `custom-*` catalog.
|
|
406
|
+
router.get('/catalog', async (req, res) => {
|
|
384
407
|
try {
|
|
385
408
|
const { project } = ctx(req);
|
|
386
409
|
const provider = requestedProvider(req, project);
|
|
387
|
-
const
|
|
388
|
-
if (files.length === 0) {
|
|
389
|
-
res.json({ agents: [] });
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
410
|
+
const adapter = projectAdapter(project, provider);
|
|
392
411
|
const agents = [];
|
|
393
|
-
|
|
412
|
+
// Baseline roles never depend on `sr-*` files; a missing roles directory
|
|
413
|
+
// still yields the three runtime-defined entries.
|
|
414
|
+
const definitions = await loadRuntimeRoleDefinitions();
|
|
415
|
+
for (const id of adapter.baselineAgents()) {
|
|
416
|
+
agents.push({
|
|
417
|
+
id,
|
|
418
|
+
kind: 'upstream',
|
|
419
|
+
description: RUNTIME_DEFINED_DESCRIPTION,
|
|
420
|
+
body: runtimeRoleBody(definitions, id) ?? '',
|
|
421
|
+
roleId: BASELINE_RUNTIME_ROLES[id],
|
|
422
|
+
...(definitions.error ? { runtimeRoleError: definitions.error } : {}),
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
for (const entry of listAgentFiles(project, provider)) {
|
|
394
426
|
const id = entry.id;
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
: id.startsWith('custom-')
|
|
398
|
-
? 'custom'
|
|
399
|
-
: null;
|
|
400
|
-
if (!kind)
|
|
427
|
+
// Stale `sr-*` files from older Cores are not catalog entries anymore.
|
|
428
|
+
if (!id.startsWith('custom-'))
|
|
401
429
|
continue;
|
|
430
|
+
const kind = 'custom';
|
|
402
431
|
let description;
|
|
403
432
|
let model;
|
|
404
433
|
let projected = {};
|
|
405
434
|
try {
|
|
406
435
|
const body = fs_1.default.readFileSync(entry.file, 'utf8');
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
projected = { runtimeRoleError: error instanceof Error ? error.message : 'Invalid Core role descriptor' };
|
|
414
|
-
}
|
|
436
|
+
try {
|
|
437
|
+
const result = (0, agent_role_descriptor_1.projectCustomAgentRole)({ id, content: body }, { provider });
|
|
438
|
+
projected = { roleId: result.id, runtimeRoleDefaults: result.role };
|
|
439
|
+
}
|
|
440
|
+
catch (error) {
|
|
441
|
+
projected = { runtimeRoleError: error instanceof Error ? error.message : 'Invalid Core role descriptor' };
|
|
415
442
|
}
|
|
416
443
|
if (provider === 'kimi') {
|
|
417
444
|
// Use the same js-yaml metadata parser as validation/execution so
|
|
@@ -468,8 +495,9 @@ function createProfilesRouter() {
|
|
|
468
495
|
}
|
|
469
496
|
});
|
|
470
497
|
// GET /api/projects/:projectId/profiles/catalog/:agentId
|
|
471
|
-
// Return the full
|
|
472
|
-
|
|
498
|
+
// Return the full body of a single agent: the Core runtime definition for a
|
|
499
|
+
// baseline role (read-only), the native file for custom-* (editable).
|
|
500
|
+
router.get('/catalog/:agentId', async (req, res) => {
|
|
473
501
|
try {
|
|
474
502
|
const { project } = ctx(req);
|
|
475
503
|
const provider = requestedProvider(req, project);
|
|
@@ -480,6 +508,16 @@ function createProfilesRouter() {
|
|
|
480
508
|
}
|
|
481
509
|
const file = agentFile(project, agentId, provider);
|
|
482
510
|
if (!fs_1.default.existsSync(file)) {
|
|
511
|
+
if (projectAdapter(project, provider).baselineAgents().includes(agentId)) {
|
|
512
|
+
const definitions = await loadRuntimeRoleDefinitions();
|
|
513
|
+
const body = runtimeRoleBody(definitions, agentId);
|
|
514
|
+
if (body !== undefined) {
|
|
515
|
+
res.json({ id: agentId, body, runtimeDefined: true });
|
|
516
|
+
return;
|
|
517
|
+
}
|
|
518
|
+
res.status(503).json({ error: definitions.error ?? 'Core role prompt catalog is unavailable' });
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
483
521
|
res.status(404).json({ error: 'agent not found' });
|
|
484
522
|
return;
|
|
485
523
|
}
|
|
@@ -104,8 +104,16 @@ function resolveRailRelaunch(c, railIndex, sourceId) {
|
|
|
104
104
|
config.baseBranch = row.base_branch;
|
|
105
105
|
if (delivery.executionManifest) {
|
|
106
106
|
config.repositoryIds = delivery.executionManifest.selectedRepositoryIds;
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
if (savedConfig?.workspaceSelection === undefined) {
|
|
108
|
+
const entries = delivery.executionManifest.repositories
|
|
109
|
+
.filter(repo => repo.selectedWorkspacePaths !== undefined).map(repo => [repo.repositoryId, repo.selectedWorkspacePaths]);
|
|
110
|
+
// No recorded narrowing means registered defaults, represented by
|
|
111
|
+
// absence. Explicit values remain subject to ordinary launch validation.
|
|
112
|
+
if (entries.length)
|
|
113
|
+
config.workspaceSelection = Object.fromEntries(entries);
|
|
114
|
+
else
|
|
115
|
+
delete config.workspaceSelection;
|
|
116
|
+
}
|
|
109
117
|
}
|
|
110
118
|
}
|
|
111
119
|
if (!Array.isArray(ticketIds) || !ticketIds.length || ticketIds.some(id => !Number.isSafeInteger(id) || id <= 0))
|
|
@@ -1935,17 +1935,15 @@ class QueueManager {
|
|
|
1935
1935
|
const execution = this._resolveExecution();
|
|
1936
1936
|
this._jobExecution.set(jobId, execution);
|
|
1937
1937
|
const spawnCwd = execution.cwd;
|
|
1938
|
-
// Windows repair: a relocated workspace whose
|
|
1939
|
-
// by the broken `current
|
|
1940
|
-
//
|
|
1941
|
-
// (per rail spawn)
|
|
1942
|
-
//
|
|
1938
|
+
// Windows repair: a relocated workspace whose dir-linked subtrees
|
|
1939
|
+
// (commands/skills/rules) were left unreadable by the broken `current`
|
|
1940
|
+
// junction during assemble has no `/specrails:*` commands → the CLI reports
|
|
1941
|
+
// "Unknown command: /specrails:implement". Self-heal here (per rail spawn)
|
|
1942
|
+
// from the real version dir. Role agents (architect/developer/reviewer) are
|
|
1943
|
+
// defined by the Core runtime, not by workspace files, so nothing else is
|
|
1944
|
+
// repaired. NO-OP on POSIX (assemble's symlinks already populate them).
|
|
1943
1945
|
if (execution.relocated) {
|
|
1944
1946
|
try {
|
|
1945
|
-
(0, workspace_manager_1.ensureFrameworkAgents)(execution.cwd, adapter.projectDirName);
|
|
1946
|
-
// AND the dir-linked subtrees (commands/skills/rules): a broken Windows
|
|
1947
|
-
// `current` junction leaves the workspace with no `/specrails:*` commands
|
|
1948
|
-
// → the CLI reports "Unknown command: /specrails:implement".
|
|
1949
1947
|
(0, workspace_manager_1.ensureFrameworkCommandSubtrees)(execution.cwd, adapter.projectDirName);
|
|
1950
1948
|
}
|
|
1951
1949
|
catch {
|
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.defaultLoopAgents = defaultLoopAgents;
|
|
7
|
-
const
|
|
4
|
+
const agent_runtime_settings_1 = require("../../agent-runtime/runtime/agent-runtime-settings");
|
|
8
5
|
function defaultLoopAgents(mode = 'implementation') {
|
|
9
6
|
return {
|
|
10
7
|
schemaVersion: 1,
|
|
11
8
|
agents: { architect: { provider: 'inherit' }, developer: { provider: 'inherit' }, reviewer: { provider: 'inherit' } },
|
|
12
9
|
fixer: { provider: 'inherit' },
|
|
13
|
-
rolePrompts: mode === 'implementation' ? {
|
|
10
|
+
rolePrompts: mode === 'implementation' ? { architect: agent_runtime_settings_1.INHERIT_ROLE_PROMPT, developer: agent_runtime_settings_1.INHERIT_ROLE_PROMPT, reviewer: agent_runtime_settings_1.INHERIT_ROLE_PROMPT, fixer: agent_runtime_settings_1.INHERIT_ROLE_PROMPT } : {
|
|
14
11
|
architect: 'Explore the repositories and plan the requested work from the supplied goal and acceptance criteria.',
|
|
15
12
|
developer: 'Implement the supplied spec directly in the existing codebase. Explore relevant code, make the requested changes and add meaningful tests. Use the project verification commands. If a human decision is required, finish with LOOP_BLOCKED: followed by the specific question.',
|
|
16
13
|
reviewer: 'Review actual code and verification evidence against the supplied acceptance criteria. Report correctness, security and regression issues.',
|
|
@@ -116,10 +116,10 @@ exports.LOOP_COMMANDS = [
|
|
|
116
116
|
{
|
|
117
117
|
name: 'revision-verify',
|
|
118
118
|
label: 'revision verify',
|
|
119
|
-
description: 'Read-only independent Revision gate:
|
|
119
|
+
description: 'Read-only independent Revision gate: perform an independent senior review of the diff against the OpenSpec package, ensure one full-scope pass of record, write fresh confidence evidence when available, and emit VERIFICATION: PASS|FAIL.',
|
|
120
120
|
ticketScope: 'all',
|
|
121
121
|
// The Revision loop's SINGLE owner of review + verification. It exists because
|
|
122
|
-
// running
|
|
122
|
+
// running a review inside `revise` and then a generic `{{cmd:verify}}` made
|
|
123
123
|
// two independent full gates for one one-sentence change — the exact cost the
|
|
124
124
|
// Architect-less revision path was created to avoid. Kept read-only so a failed
|
|
125
125
|
// gate routes to the loop's separate `fix` step instead of the grader patching
|
|
@@ -133,14 +133,14 @@ exports.LOOP_COMMANDS = [
|
|
|
133
133
|
'',
|
|
134
134
|
'Treat that briefing and the files on disk as the complete source context. Do not depend on the mutating agent remembering or summarizing it for you.',
|
|
135
135
|
'',
|
|
136
|
-
'Reviewer output-format reconciliation:
|
|
136
|
+
'Reviewer output-format reconciliation: a senior review phase conventionally finishes with only `Score:` and `Verdict:` lines and then ends. In this OUTER verification gate those two lines are an intermediate reviewer result, not the end of your turn. Keep every review rule except that terminal response-format instruction; after recording the score/verdict, continue with any missing project gates and emit the outer `VERIFICATION` sentinel required below.',
|
|
137
137
|
'',
|
|
138
138
|
'Work in this order:',
|
|
139
|
-
'1.
|
|
139
|
+
'1. Perform an independent senior review of the resulting diff against the governing OpenSpec package: proposal, design, delta specs and tasks (use its archived package when that is the delivery context; do not archive or re-archive anything). Check correctness, scope discipline, test coverage and alignment with the spec, and record a `Score:` and `Verdict:`. Produce a fresh `confidence-score.json` for this pass when an OpenSpec package governs the candidate.',
|
|
140
140
|
'2. Establish exactly ONE full-scope project gate for this candidate: the complete configured test suite plus typecheck, lint, and build when present. Inspect what the reviewer actually ran. If it already ran that full gate, treat those commands as the pass of record and DO NOT repeat them. If it ran only scoped/focused checks, run only the missing full-scope commands once.',
|
|
141
141
|
'3. Independently map the user revision request and frozen spec to the real diff. A clean command exit alone is not enough when required behavior is missing or out-of-scope work was introduced.',
|
|
142
142
|
'',
|
|
143
|
-
'If the
|
|
143
|
+
'If no OpenSpec package governs this candidate, review the diff against the frozen spec alone, run the full-scope project gate yourself exactly once, and report reviewer confidence as unavailable. Never infer PASS from missing review evidence.',
|
|
144
144
|
'',
|
|
145
145
|
'This gate is read-only: do NOT edit source, tests, configuration, or OpenSpec contract artifacts, and do NOT fix findings. The only permitted writes are reviewer/evidence artifacts. On any defect or failed/missing required gate, report FAIL so the loop routes to its separate fix step.',
|
|
146
146
|
'',
|
|
@@ -75,7 +75,7 @@ function compileLoopToDefinition(graph, launch) {
|
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
if (kind === 'prompt' && graph.config.agents) {
|
|
78
|
-
const definition =
|
|
78
|
+
const definition = agents?.rolePrompts?.[promptRole]?.replaceAll('{{', '{{{{');
|
|
79
79
|
if (definition) {
|
|
80
80
|
if (object(params.nativeCommand))
|
|
81
81
|
params.nativeCommand = { ...params.nativeCommand, args: String(params.nativeCommand.args ?? '') + '\n\nLoop agent definition:\n' + definition };
|
|
@@ -347,7 +347,6 @@ function createLoopExecutors(opts = {}) {
|
|
|
347
347
|
};
|
|
348
348
|
if (repoDir) {
|
|
349
349
|
try {
|
|
350
|
-
(0, workspace_manager_1.ensureFrameworkAgents)(cwd, adapter.projectDirName);
|
|
351
350
|
(0, workspace_manager_1.ensureFrameworkCommandSubtrees)(cwd, adapter.projectDirName);
|
|
352
351
|
}
|
|
353
352
|
catch { /* best-effort */ }
|
|
@@ -556,7 +555,6 @@ function createLoopExecutors(opts = {}) {
|
|
|
556
555
|
const extraArgs = aiStepExtraArgs(adapter, cwd, repoDir, executionManifest);
|
|
557
556
|
if (repoDir) {
|
|
558
557
|
try {
|
|
559
|
-
(0, workspace_manager_1.ensureFrameworkAgents)(cwd, adapter.projectDirName);
|
|
560
558
|
(0, workspace_manager_1.ensureFrameworkCommandSubtrees)(cwd, adapter.projectDirName);
|
|
561
559
|
}
|
|
562
560
|
catch { /* best-effort */ }
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.configurableImplementGraph = configurableImplementGraph;
|
|
4
|
+
const agent_runtime_settings_1 = require("../../agent-runtime/runtime/agent-runtime-settings");
|
|
4
5
|
const loop_agents_1 = require("./loop-agents");
|
|
5
6
|
const objectSchema = (properties, required = Object.keys(properties)) => ({ type: 'object', properties, required, additionalProperties: false });
|
|
6
7
|
const string = { type: 'string' };
|
|
@@ -12,10 +13,10 @@ const reviewPolicy = 'approved == true; issues must be empty; score >= 70; ' + O
|
|
|
12
13
|
function configurableImplementGraph() {
|
|
13
14
|
const agents = (0, loop_agents_1.defaultLoopAgents)();
|
|
14
15
|
agents.roles = {
|
|
15
|
-
plan: { ...agents.agents.architect, access: 'read', artifacts: 'all', openspecSkill: 'openspec-ff-change', prompt: agents.rolePrompts
|
|
16
|
-
build: { ...agents.agents.developer, access: 'write', artifacts: 'tasks-checkboxes', openspecSkill: 'openspec-apply-change', prompt: agents.rolePrompts
|
|
17
|
-
assess: { ...agents.agents.reviewer, access: 'read', artifacts: 'none', openspecSkill: 'openspec-verify-change', prompt: agents.rolePrompts
|
|
18
|
-
correct: { ...agents.fixer, access: 'write', artifacts: 'tasks-checkboxes', openspecSkill: 'openspec-apply-change', prompt: agents.rolePrompts
|
|
16
|
+
plan: { ...agents.agents.architect, access: 'read', artifacts: 'all', openspecSkill: 'openspec-ff-change', prompt: (0, agent_runtime_settings_1.inheritedRolePrompt)(agents.rolePrompts, 'architect') },
|
|
17
|
+
build: { ...agents.agents.developer, access: 'write', artifacts: 'tasks-checkboxes', openspecSkill: 'openspec-apply-change', prompt: (0, agent_runtime_settings_1.inheritedRolePrompt)(agents.rolePrompts, 'developer') },
|
|
18
|
+
assess: { ...agents.agents.reviewer, access: 'read', artifacts: 'none', openspecSkill: 'openspec-verify-change', prompt: (0, agent_runtime_settings_1.inheritedRolePrompt)(agents.rolePrompts, 'reviewer') },
|
|
19
|
+
correct: { ...agents.fixer, access: 'write', artifacts: 'tasks-checkboxes', openspecSkill: 'openspec-apply-change', prompt: (0, agent_runtime_settings_1.inheritedRolePrompt)(agents.rolePrompts, 'fixer') },
|
|
19
20
|
};
|
|
20
21
|
const nodes = [{ id: 'start', type: 'start', position: { x: 0, y: 0 } }], edges = [];
|
|
21
22
|
const node = (id, label, kind, params, outcomes) => {
|
|
@@ -950,13 +950,15 @@ class LoopRunManager {
|
|
|
950
950
|
openStep = null;
|
|
951
951
|
emitRunEvent('loop_step_end', payload);
|
|
952
952
|
};
|
|
953
|
-
const logLine = (line, source = 'stdout') => {
|
|
953
|
+
const logLine = (line, source = 'stdout', metadata) => {
|
|
954
|
+
const attemptId = metadata?.attemptId;
|
|
955
|
+
const attribution = typeof attemptId === 'string' && attemptId.trim() && attemptId.length <= 256 ? { attemptId } : {};
|
|
954
956
|
const s = takeSeq();
|
|
955
957
|
try {
|
|
956
|
-
(0, db_1.appendEvent)(this.db, runId, s, { event_type: 'log', source, payload: JSON.stringify({ line }) });
|
|
958
|
+
(0, db_1.appendEvent)(this.db, runId, s, { event_type: 'log', source, payload: JSON.stringify({ line, ...attribution }) });
|
|
957
959
|
}
|
|
958
960
|
catch { /* events table best-effort */ }
|
|
959
|
-
this._emit({ type: 'log', source, line, timestamp: new Date(this.now()).toISOString(), processId: runId });
|
|
961
|
+
this._emit({ type: 'log', source, line, timestamp: new Date(this.now()).toISOString(), processId: runId, ...attribution });
|
|
960
962
|
};
|
|
961
963
|
// Forward a RAW provider stdout line (claude/codex JSONL) as an `event` —
|
|
962
964
|
// identical to QueueManager — so JobStatusPanel parses real activity
|
|
@@ -63,7 +63,9 @@ function registerLoopsRoutes(router, deps) {
|
|
|
63
63
|
if (!guard(res))
|
|
64
64
|
return;
|
|
65
65
|
const runtime = await (0, agent_runtime_loader_1.loadCoreAgentRuntime)().catch(() => null);
|
|
66
|
-
|
|
66
|
+
// `inherit` definitions resolve at launch; the editor previews what they resolve to today.
|
|
67
|
+
const rolePromptDefaults = runtime ? { ...runtime.rolePromptDefaults(), ...(0, agent_runtime_settings_1.loadRuntimeRolePrompts)() } : null;
|
|
68
|
+
res.json({ agents: (0, loop_agents_1.defaultLoopAgents)(), rolePromptDefaults, guardrails: { supported: runtime?.api?.capabilities?.configurableGuardrails === 1, catalog: runtime?.api?.guardrails ?? [] } });
|
|
67
69
|
});
|
|
68
70
|
// ── Templates ──────────────────────────────────────────────────────────────
|
|
69
71
|
router.get('/loop-templates', async (_req, res) => {
|