@useorgx/openclaw-plugin 0.4.9 → 0.7.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/README.md +35 -0
- package/dashboard/dist/assets/BJgZIVUQ.js +53 -0
- package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
- package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
- package/dashboard/dist/assets/BXWDRGm-.js +1 -0
- package/dashboard/dist/assets/BXWDRGm-.js.br +0 -0
- package/dashboard/dist/assets/BXWDRGm-.js.gz +0 -0
- package/dashboard/dist/assets/BgOYB78t.js +4 -0
- package/dashboard/dist/assets/BgOYB78t.js.br +0 -0
- package/dashboard/dist/assets/BgOYB78t.js.gz +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
- package/dashboard/dist/assets/CE38zU4U.js +1 -0
- package/dashboard/dist/assets/CE38zU4U.js.br +0 -0
- package/dashboard/dist/assets/CE38zU4U.js.gz +0 -0
- package/dashboard/dist/assets/CFGKRAzG.js +1 -0
- package/dashboard/dist/assets/CFGKRAzG.js.br +0 -0
- package/dashboard/dist/assets/CFGKRAzG.js.gz +0 -0
- package/dashboard/dist/assets/CGGR2GZh.js +1 -0
- package/dashboard/dist/assets/CGGR2GZh.js.br +0 -0
- package/dashboard/dist/assets/CGGR2GZh.js.gz +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js +1 -0
- package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
- package/dashboard/dist/assets/CPFiTmlw.js +8 -0
- package/dashboard/dist/assets/CPFiTmlw.js.br +0 -0
- package/dashboard/dist/assets/CPFiTmlw.js.gz +0 -0
- package/dashboard/dist/assets/CZZTvkQZ.js +1 -0
- package/dashboard/dist/assets/CZZTvkQZ.js.br +0 -0
- package/dashboard/dist/assets/CZZTvkQZ.js.gz +0 -0
- package/dashboard/dist/assets/{CpJsfbXo.js → CxQ08qFN.js} +2 -2
- package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
- package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
- package/dashboard/dist/assets/D-bf6hEI.js +213 -0
- package/dashboard/dist/assets/D-bf6hEI.js.br +0 -0
- package/dashboard/dist/assets/D-bf6hEI.js.gz +0 -0
- package/dashboard/dist/assets/DG6y9wJI.js +2 -0
- package/dashboard/dist/assets/DG6y9wJI.js.br +0 -0
- package/dashboard/dist/assets/DG6y9wJI.js.gz +0 -0
- package/dashboard/dist/assets/DNxKz-GV.js +1 -0
- package/dashboard/dist/assets/DNxKz-GV.js.br +0 -0
- package/dashboard/dist/assets/DNxKz-GV.js.gz +0 -0
- package/dashboard/dist/assets/DW_rKUic.js +11 -0
- package/dashboard/dist/assets/DW_rKUic.js.br +0 -0
- package/dashboard/dist/assets/DW_rKUic.js.gz +0 -0
- package/dashboard/dist/assets/DbNoijHm.js +1 -0
- package/dashboard/dist/assets/DbNoijHm.js.br +0 -0
- package/dashboard/dist/assets/DbNoijHm.js.gz +0 -0
- package/dashboard/dist/assets/DjcdE6jC.js +2 -0
- package/dashboard/dist/assets/DjcdE6jC.js.br +0 -0
- package/dashboard/dist/assets/DjcdE6jC.js.gz +0 -0
- package/dashboard/dist/assets/FZYuCDnt.js +1 -0
- package/dashboard/dist/assets/FZYuCDnt.js.br +0 -0
- package/dashboard/dist/assets/FZYuCDnt.js.gz +0 -0
- package/dashboard/dist/assets/PAUiij_z.js +1 -0
- package/dashboard/dist/assets/PAUiij_z.js.br +0 -0
- package/dashboard/dist/assets/PAUiij_z.js.gz +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js +8 -0
- package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
- package/dashboard/dist/assets/h5biQs2I.css +1 -0
- package/dashboard/dist/assets/h5biQs2I.css.br +0 -0
- package/dashboard/dist/assets/h5biQs2I.css.gz +0 -0
- package/dashboard/dist/assets/ic2FaMnh.js +1 -0
- package/dashboard/dist/assets/ic2FaMnh.js.br +0 -0
- package/dashboard/dist/assets/ic2FaMnh.js.gz +0 -0
- package/dashboard/dist/assets/nByHNHoW.js +1 -0
- package/dashboard/dist/assets/nByHNHoW.js.br +0 -0
- package/dashboard/dist/assets/nByHNHoW.js.gz +0 -0
- package/dashboard/dist/assets/qm8xLgv-.css +1 -0
- package/dashboard/dist/assets/qm8xLgv-.css.br +0 -0
- package/dashboard/dist/assets/qm8xLgv-.css.gz +0 -0
- package/dashboard/dist/assets/tS9mbYZi.js +1 -0
- package/dashboard/dist/assets/tS9mbYZi.js.br +0 -0
- package/dashboard/dist/assets/tS9mbYZi.js.gz +0 -0
- package/dashboard/dist/brand/anthropic-mark.svg.br +0 -0
- package/dashboard/dist/brand/anthropic-mark.svg.gz +0 -0
- package/dashboard/dist/brand/openai-mark.svg.br +0 -0
- package/dashboard/dist/brand/openai-mark.svg.gz +0 -0
- package/dashboard/dist/brand/openclaw-mark.svg.br +0 -0
- package/dashboard/dist/brand/openclaw-mark.svg.gz +0 -0
- package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
- package/dashboard/dist/index.html +7 -5
- package/dashboard/dist/index.html.br +0 -0
- package/dashboard/dist/index.html.gz +0 -0
- package/dist/activity-actor-fields.js +26 -4
- package/dist/activity-store.js +34 -8
- package/dist/agent-context-store.js +79 -17
- package/dist/agent-run-store.js +44 -3
- package/dist/agent-suite.d.ts +9 -0
- package/dist/agent-suite.js +149 -9
- package/dist/artifacts/artifact-domain-schemas.d.ts +66 -0
- package/dist/artifacts/artifact-domain-schemas.js +357 -0
- package/dist/artifacts/register-artifact.d.ts +4 -3
- package/dist/artifacts/register-artifact.js +170 -57
- package/dist/chat-store.d.ts +157 -0
- package/dist/chat-store.js +586 -0
- package/dist/cli/orgx.js +11 -0
- package/dist/contracts/client.d.ts +43 -3
- package/dist/contracts/client.js +159 -30
- package/dist/contracts/retro-schema.d.ts +81 -0
- package/dist/contracts/retro-schema.js +80 -0
- package/dist/contracts/shared-types.d.ts +159 -0
- package/dist/contracts/shared-types.js +177 -1
- package/dist/contracts/skill-pack-schema.d.ts +192 -0
- package/dist/contracts/skill-pack-schema.js +180 -0
- package/dist/contracts/types.d.ts +227 -2
- package/dist/entities/auto-assignment.js +43 -17
- package/dist/event-sanitization.d.ts +11 -0
- package/dist/event-sanitization.js +113 -0
- package/dist/fs-utils.js +13 -1
- package/dist/gateway-watchdog.d.ts +5 -0
- package/dist/gateway-watchdog.js +50 -0
- package/dist/hooks/post-reporting-event.mjs +1 -5
- package/dist/http/helpers/activity-headline.js +13 -132
- package/dist/http/helpers/auto-continue-engine.d.ts +198 -10
- package/dist/http/helpers/auto-continue-engine.js +2531 -186
- package/dist/http/helpers/autopilot-operations.d.ts +19 -0
- package/dist/http/helpers/autopilot-operations.js +182 -31
- package/dist/http/helpers/autopilot-runtime.d.ts +1 -0
- package/dist/http/helpers/autopilot-runtime.js +308 -20
- package/dist/http/helpers/autopilot-slice-utils.d.ts +18 -0
- package/dist/http/helpers/autopilot-slice-utils.js +516 -93
- package/dist/http/helpers/decision-mapper.d.ts +40 -0
- package/dist/http/helpers/decision-mapper.js +223 -7
- package/dist/http/helpers/dispatch-lifecycle.d.ts +19 -2
- package/dist/http/helpers/dispatch-lifecycle.js +242 -37
- package/dist/http/helpers/kickoff-context.js +74 -0
- package/dist/http/helpers/llm-client.d.ts +47 -0
- package/dist/http/helpers/llm-client.js +256 -0
- package/dist/http/helpers/mission-control.d.ts +102 -3
- package/dist/http/helpers/mission-control.js +498 -9
- package/dist/http/helpers/sentinel-catalog.d.ts +23 -0
- package/dist/http/helpers/sentinel-catalog.js +193 -0
- package/dist/http/helpers/session-classification.d.ts +9 -0
- package/dist/http/helpers/session-classification.js +564 -0
- package/dist/http/helpers/slice-experience-v2.d.ts +137 -0
- package/dist/http/helpers/slice-experience-v2.js +677 -0
- package/dist/http/helpers/slice-run-projections.d.ts +72 -0
- package/dist/http/helpers/slice-run-projections.js +860 -0
- package/dist/http/helpers/triage-mapper.d.ts +43 -0
- package/dist/http/helpers/triage-mapper.js +549 -0
- package/dist/http/helpers/value-utils.js +7 -2
- package/dist/http/helpers/workspace-scope.d.ts +15 -0
- package/dist/http/helpers/workspace-scope.js +170 -0
- package/dist/http/index.js +1354 -97
- package/dist/http/routes/agent-suite.d.ts +9 -0
- package/dist/http/routes/agent-suite.js +207 -8
- package/dist/http/routes/agents-catalog.js +64 -19
- package/dist/http/routes/chat.d.ts +19 -0
- package/dist/http/routes/chat.js +522 -0
- package/dist/http/routes/decision-actions.d.ts +8 -1
- package/dist/http/routes/decision-actions.js +42 -5
- package/dist/http/routes/dispatch-gateway-envelope.d.ts +25 -0
- package/dist/http/routes/dispatch-gateway-envelope.js +26 -0
- package/dist/http/routes/entities.d.ts +16 -0
- package/dist/http/routes/entities.js +294 -6
- package/dist/http/routes/live-legacy.d.ts +5 -0
- package/dist/http/routes/live-legacy.js +23 -509
- package/dist/http/routes/live-misc.d.ts +12 -0
- package/dist/http/routes/live-misc.js +251 -31
- package/dist/http/routes/live-snapshot.d.ts +48 -2
- package/dist/http/routes/live-snapshot.js +638 -19
- package/dist/http/routes/live-terminal.d.ts +11 -0
- package/dist/http/routes/live-terminal.js +261 -0
- package/dist/http/routes/live-triage.d.ts +61 -0
- package/dist/http/routes/live-triage.js +248 -0
- package/dist/http/routes/mission-control-actions.d.ts +49 -1
- package/dist/http/routes/mission-control-actions.js +1334 -84
- package/dist/http/routes/mission-control-read.d.ts +48 -3
- package/dist/http/routes/mission-control-read.js +1593 -20
- package/dist/http/routes/realtime-orchestrator.d.ts +10 -0
- package/dist/http/routes/realtime-orchestrator.js +74 -0
- package/dist/http/routes/run-control.d.ts +5 -2
- package/dist/http/routes/run-control.js +10 -0
- package/dist/http/routes/sentinels-catalog.d.ts +7 -0
- package/dist/http/routes/sentinels-catalog.js +24 -0
- package/dist/http/routes/summary.js +10 -3
- package/dist/http/routes/usage.d.ts +24 -0
- package/dist/http/routes/usage.js +362 -0
- package/dist/http/routes/work-artifacts.js +28 -9
- package/dist/index.js +165 -27
- package/dist/local-openclaw.js +29 -6
- package/dist/mcp-client-setup.js +3 -3
- package/dist/mcp-http-handler.js +33 -59
- package/dist/next-up-queue-store.d.ts +16 -1
- package/dist/next-up-queue-store.js +89 -7
- package/dist/outbox.d.ts +5 -0
- package/dist/outbox.js +113 -9
- package/dist/paths.js +24 -5
- package/dist/reporting/rollups.d.ts +53 -0
- package/dist/reporting/rollups.js +148 -0
- package/dist/retro/domain-templates.d.ts +45 -0
- package/dist/retro/domain-templates.js +297 -0
- package/dist/retro/quality-rubric.d.ts +33 -0
- package/dist/retro/quality-rubric.js +213 -0
- package/dist/runtime-cleanup.d.ts +18 -0
- package/dist/runtime-cleanup.js +87 -0
- package/dist/services/background.d.ts +11 -0
- package/dist/services/background.js +22 -0
- package/dist/services/experiment-randomization.d.ts +21 -0
- package/dist/services/experiment-randomization.js +63 -0
- package/dist/skill-pack-state.d.ts +36 -5
- package/dist/skill-pack-state.js +273 -29
- package/dist/sync/local-agent-telemetry.d.ts +13 -0
- package/dist/sync/local-agent-telemetry.js +128 -0
- package/dist/sync/outbox-replay.js +131 -24
- package/dist/team-context-store.d.ts +23 -0
- package/dist/team-context-store.js +116 -0
- package/dist/telemetry/posthog.js +4 -2
- package/dist/tools/core-tools.d.ts +10 -14
- package/dist/tools/core-tools.js +1289 -24
- package/dist/types.d.ts +2 -0
- package/dist/types.js +2 -0
- package/dist/worker-supervisor.js +23 -0
- package/package.json +14 -4
- package/dashboard/dist/assets/B3ziCA02.js +0 -8
- package/dashboard/dist/assets/B5NEElEI.css +0 -1
- package/dashboard/dist/assets/BhapSNAs.js +0 -215
- package/dashboard/dist/assets/iFdvE7lx.js +0 -1
- package/dashboard/dist/assets/jRJsmpYM.js +0 -1
- package/dashboard/dist/assets/sAhvFnpk.js +0 -4
|
@@ -17,101 +17,136 @@ function ensurePrivateDirForFile(pathname) {
|
|
|
17
17
|
}
|
|
18
18
|
function autopilotSliceSchema() {
|
|
19
19
|
// Strict enough to keep outputs predictable, but tolerant of older agents.
|
|
20
|
-
|
|
21
|
-
type: "
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
const artifactProperties = {
|
|
21
|
+
name: { type: "string", minLength: 1 },
|
|
22
|
+
artifact_type: {
|
|
23
|
+
type: "string",
|
|
24
|
+
enum: ["pr", "commit", "document", "config", "report", "design", "retro", "other"],
|
|
25
|
+
},
|
|
26
|
+
confidence_score: { type: ["number", "null"], minimum: 0, maximum: 1 },
|
|
27
|
+
description: { type: ["string", "null"] },
|
|
28
|
+
url: { type: ["string", "null"] },
|
|
29
|
+
verification_steps: { type: ["array", "null"], items: { type: "string" } },
|
|
30
|
+
milestone_id: { type: ["string", "null"] },
|
|
31
|
+
task_ids: { type: ["array", "null"], items: { type: "string" } },
|
|
32
|
+
};
|
|
33
|
+
const decisionProperties = {
|
|
34
|
+
question: { type: "string", minLength: 1 },
|
|
35
|
+
summary: { type: ["string", "null"] },
|
|
36
|
+
options: { type: ["array", "null"], items: { type: "string" } },
|
|
37
|
+
urgency: {
|
|
38
|
+
type: ["string", "null"],
|
|
39
|
+
enum: ["low", "medium", "high", "urgent", null],
|
|
40
|
+
},
|
|
41
|
+
blocking: { type: "boolean" },
|
|
42
|
+
};
|
|
43
|
+
const skillEvidenceProperties = {
|
|
44
|
+
skill: { type: "string", minLength: 1 },
|
|
45
|
+
skill_file: { type: ["string", "null"] },
|
|
46
|
+
skill_sha256: { type: ["string", "null"] },
|
|
47
|
+
skill_heading: { type: ["string", "null"] },
|
|
48
|
+
};
|
|
49
|
+
const taskUpdateProperties = {
|
|
50
|
+
task_id: { type: "string", minLength: 1 },
|
|
51
|
+
status: { type: "string", enum: ["todo", "in_progress", "done", "blocked"] },
|
|
52
|
+
reason: { type: ["string", "null"] },
|
|
53
|
+
};
|
|
54
|
+
const milestoneUpdateProperties = {
|
|
55
|
+
milestone_id: { type: "string", minLength: 1 },
|
|
56
|
+
status: {
|
|
57
|
+
type: "string",
|
|
58
|
+
enum: ["planned", "in_progress", "completed", "at_risk", "cancelled"],
|
|
59
|
+
},
|
|
60
|
+
reason: { type: ["string", "null"] },
|
|
61
|
+
};
|
|
62
|
+
const topLevelProperties = {
|
|
63
|
+
status: {
|
|
64
|
+
type: "string",
|
|
65
|
+
enum: ["completed", "blocked", "needs_decision", "error"],
|
|
66
|
+
},
|
|
67
|
+
summary: { type: "string", minLength: 1 },
|
|
68
|
+
workstream_id: { type: "string", minLength: 1 },
|
|
69
|
+
workstream_title: { type: ["string", "null"] },
|
|
70
|
+
slice_id: { type: ["string", "null"] },
|
|
71
|
+
artifacts: {
|
|
72
|
+
type: ["array", "null"],
|
|
73
|
+
items: {
|
|
74
|
+
type: "object",
|
|
75
|
+
additionalProperties: false,
|
|
76
|
+
required: Object.keys(artifactProperties),
|
|
77
|
+
properties: artifactProperties,
|
|
28
78
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
additionalProperties: false,
|
|
38
|
-
required: ["name", "artifact_type"],
|
|
39
|
-
properties: {
|
|
40
|
-
name: { type: "string", minLength: 1 },
|
|
41
|
-
artifact_type: {
|
|
42
|
-
type: "string",
|
|
43
|
-
enum: ["pr", "commit", "document", "config", "report", "design", "other"],
|
|
44
|
-
},
|
|
45
|
-
description: { type: ["string", "null"] },
|
|
46
|
-
url: { type: ["string", "null"] },
|
|
47
|
-
verification_steps: { type: ["array", "null"], items: { type: "string" } },
|
|
48
|
-
milestone_id: { type: ["string", "null"] },
|
|
49
|
-
task_ids: { type: ["array", "null"], items: { type: "string" } },
|
|
50
|
-
},
|
|
51
|
-
},
|
|
79
|
+
},
|
|
80
|
+
decisions_needed: {
|
|
81
|
+
type: ["array", "null"],
|
|
82
|
+
items: {
|
|
83
|
+
type: "object",
|
|
84
|
+
additionalProperties: false,
|
|
85
|
+
required: Object.keys(decisionProperties),
|
|
86
|
+
properties: decisionProperties,
|
|
52
87
|
},
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
summary: { type: ["string", "null"] },
|
|
62
|
-
options: { type: ["array", "null"], items: { type: "string" } },
|
|
63
|
-
urgency: {
|
|
64
|
-
type: ["string", "null"],
|
|
65
|
-
enum: ["low", "medium", "high", "urgent", null],
|
|
66
|
-
},
|
|
67
|
-
blocking: { type: ["boolean", "null"] },
|
|
68
|
-
},
|
|
69
|
-
},
|
|
88
|
+
},
|
|
89
|
+
skill_evidence: {
|
|
90
|
+
type: ["array", "null"],
|
|
91
|
+
items: {
|
|
92
|
+
type: "object",
|
|
93
|
+
additionalProperties: false,
|
|
94
|
+
required: Object.keys(skillEvidenceProperties),
|
|
95
|
+
properties: skillEvidenceProperties,
|
|
70
96
|
},
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
status: { type: "string", minLength: 1 },
|
|
80
|
-
reason: { type: ["string", "null"] },
|
|
81
|
-
},
|
|
82
|
-
},
|
|
97
|
+
},
|
|
98
|
+
task_updates: {
|
|
99
|
+
type: ["array", "null"],
|
|
100
|
+
items: {
|
|
101
|
+
type: "object",
|
|
102
|
+
additionalProperties: false,
|
|
103
|
+
required: Object.keys(taskUpdateProperties),
|
|
104
|
+
properties: taskUpdateProperties,
|
|
83
105
|
},
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
status: { type: "string", minLength: 1 },
|
|
93
|
-
reason: { type: ["string", "null"] },
|
|
94
|
-
},
|
|
95
|
-
},
|
|
106
|
+
},
|
|
107
|
+
milestone_updates: {
|
|
108
|
+
type: ["array", "null"],
|
|
109
|
+
items: {
|
|
110
|
+
type: "object",
|
|
111
|
+
additionalProperties: false,
|
|
112
|
+
required: Object.keys(milestoneUpdateProperties),
|
|
113
|
+
properties: milestoneUpdateProperties,
|
|
96
114
|
},
|
|
97
|
-
next_actions: { type: ["array", "null"], items: { type: "string" } },
|
|
98
115
|
},
|
|
116
|
+
next_actions: { type: ["array", "null"], items: { type: "string" } },
|
|
117
|
+
};
|
|
118
|
+
return {
|
|
119
|
+
type: "object",
|
|
120
|
+
additionalProperties: false,
|
|
121
|
+
required: Object.keys(topLevelProperties),
|
|
122
|
+
properties: topLevelProperties,
|
|
123
|
+
// Keep schema within Codex structured-output subset (no combinators like allOf/if/then).
|
|
124
|
+
// Status/decision consistency is enforced by coordinator post-parse.
|
|
99
125
|
};
|
|
100
126
|
}
|
|
101
127
|
export function ensureAutopilotSliceSchemaPath(schemaFilename) {
|
|
102
128
|
const file = join(getOrgxPluginConfigDir(), schemaFilename);
|
|
129
|
+
const nextSchemaRaw = JSON.stringify(autopilotSliceSchema(), null, 2);
|
|
103
130
|
try {
|
|
104
|
-
if (existsSync(file))
|
|
105
|
-
|
|
131
|
+
if (existsSync(file)) {
|
|
132
|
+
try {
|
|
133
|
+
const existingRaw = readFileSync(file, "utf8").trim();
|
|
134
|
+
if (existingRaw === nextSchemaRaw)
|
|
135
|
+
return file;
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
// continue and rewrite
|
|
139
|
+
}
|
|
140
|
+
}
|
|
106
141
|
ensurePrivateDirForFile(file);
|
|
107
|
-
writeFileAtomicSync(file,
|
|
142
|
+
writeFileAtomicSync(file, nextSchemaRaw, { mode: 0o600 });
|
|
108
143
|
return file;
|
|
109
144
|
}
|
|
110
145
|
catch {
|
|
111
146
|
// Fall back to best-effort write.
|
|
112
147
|
try {
|
|
113
148
|
ensurePrivateDirForFile(file);
|
|
114
|
-
writeFileSync(file, `${
|
|
149
|
+
writeFileSync(file, `${nextSchemaRaw}\n`, {
|
|
115
150
|
encoding: "utf8",
|
|
116
151
|
mode: 0o600,
|
|
117
152
|
});
|
|
@@ -123,19 +158,251 @@ export function ensureAutopilotSliceSchemaPath(schemaFilename) {
|
|
|
123
158
|
}
|
|
124
159
|
}
|
|
125
160
|
export function parseSliceResult(raw) {
|
|
126
|
-
const
|
|
161
|
+
const allowedStatuses = new Set(["completed", "blocked", "needs_decision", "error"]);
|
|
162
|
+
const stripUtf8Bom = (text) => text.replace(/^\uFEFF/, "");
|
|
163
|
+
const extractMarkdownJsonFences = (text) => {
|
|
164
|
+
const matches = text.matchAll(/```(?:json)?\s*([\s\S]*?)\s*```/gi);
|
|
165
|
+
const fences = [];
|
|
166
|
+
for (const match of matches) {
|
|
167
|
+
const inner = typeof match[1] === "string" ? match[1].trim() : "";
|
|
168
|
+
if (inner.length > 0)
|
|
169
|
+
fences.push(inner);
|
|
170
|
+
}
|
|
171
|
+
return fences;
|
|
172
|
+
};
|
|
173
|
+
const stripMarkdownJsonFence = (text) => {
|
|
174
|
+
const fenceCount = text.match(/```/g)?.length ?? 0;
|
|
175
|
+
if (fenceCount !== 2)
|
|
176
|
+
return text;
|
|
177
|
+
const fenced = text.match(/^```(?:json)?\s*([\s\S]*?)\s*```$/i);
|
|
178
|
+
if (!fenced || typeof fenced[1] !== "string")
|
|
179
|
+
return text;
|
|
180
|
+
return fenced[1].trim();
|
|
181
|
+
};
|
|
182
|
+
const parseSliceJsonText = (text) => {
|
|
183
|
+
const normalized = stripUtf8Bom(stripMarkdownJsonFence(text.trim()));
|
|
184
|
+
const parsed = parseJsonSafe(normalized);
|
|
185
|
+
if (parsed && typeof parsed === "object" && isLikelySliceResult(parsed)) {
|
|
186
|
+
return normalizeSliceResult(parsed);
|
|
187
|
+
}
|
|
188
|
+
const fencedCandidates = extractMarkdownJsonFences(normalized);
|
|
189
|
+
for (let i = fencedCandidates.length - 1; i >= 0; i -= 1) {
|
|
190
|
+
const parsedInner = parseJsonSafe(stripUtf8Bom(fencedCandidates[i]));
|
|
191
|
+
if (parsedInner && typeof parsedInner === "object" && isLikelySliceResult(parsedInner)) {
|
|
192
|
+
return normalizeSliceResult(parsedInner);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return null;
|
|
196
|
+
};
|
|
197
|
+
const isLikelySliceResult = (value) => {
|
|
198
|
+
if (!value || typeof value !== "object")
|
|
199
|
+
return false;
|
|
200
|
+
const record = value;
|
|
201
|
+
const status = typeof record.status === "string" ? record.status : "";
|
|
202
|
+
const workstreamId = typeof record.workstream_id === "string" ? record.workstream_id : "";
|
|
203
|
+
const summary = typeof record.summary === "string" ? record.summary : "";
|
|
204
|
+
return (allowedStatuses.has(status) &&
|
|
205
|
+
summary.trim().length > 0 &&
|
|
206
|
+
workstreamId.trim().length > 0);
|
|
207
|
+
};
|
|
208
|
+
const normalizeSliceResult = (value) => {
|
|
209
|
+
const record = value;
|
|
210
|
+
const status = typeof record.status === "string" ? record.status : "";
|
|
211
|
+
const decisions = record.decisions_needed;
|
|
212
|
+
let changed = false;
|
|
213
|
+
let nextRecord = record;
|
|
214
|
+
if (Array.isArray(decisions)) {
|
|
215
|
+
const normalized = decisions.map((decision) => {
|
|
216
|
+
if (!decision || typeof decision !== "object")
|
|
217
|
+
return decision;
|
|
218
|
+
const decisionRecord = decision;
|
|
219
|
+
if (typeof decisionRecord.blocking === "boolean")
|
|
220
|
+
return decision;
|
|
221
|
+
changed = true;
|
|
222
|
+
return { ...decisionRecord, blocking: false };
|
|
223
|
+
});
|
|
224
|
+
if (changed)
|
|
225
|
+
nextRecord = { ...nextRecord, decisions_needed: normalized };
|
|
226
|
+
}
|
|
227
|
+
const hasBlockingDecision = (input) => Array.isArray(input.decisions_needed) &&
|
|
228
|
+
input.decisions_needed.some((decision) => {
|
|
229
|
+
if (!decision || typeof decision !== "object")
|
|
230
|
+
return false;
|
|
231
|
+
return decision.blocking === true;
|
|
232
|
+
});
|
|
233
|
+
if (hasBlockingDecision(nextRecord) && status === "completed") {
|
|
234
|
+
changed = true;
|
|
235
|
+
nextRecord = { ...nextRecord, status: "needs_decision" };
|
|
236
|
+
}
|
|
237
|
+
const normalizedStatus = typeof nextRecord.status === "string" ? nextRecord.status : status;
|
|
238
|
+
if (normalizedStatus === "completed") {
|
|
239
|
+
const hasExplicitOutcomeArrays = Array.isArray(record.artifacts) ||
|
|
240
|
+
Array.isArray(record.task_updates) ||
|
|
241
|
+
Array.isArray(record.milestone_updates) ||
|
|
242
|
+
Array.isArray(record.decisions_needed);
|
|
243
|
+
const artifactsCount = Array.isArray(nextRecord.artifacts) ? nextRecord.artifacts.length : 0;
|
|
244
|
+
const taskUpdatesCount = Array.isArray(nextRecord.task_updates)
|
|
245
|
+
? nextRecord.task_updates.length
|
|
246
|
+
: 0;
|
|
247
|
+
const milestoneUpdatesCount = Array.isArray(nextRecord.milestone_updates)
|
|
248
|
+
? nextRecord.milestone_updates.length
|
|
249
|
+
: 0;
|
|
250
|
+
const hasOutcomes = artifactsCount > 0 ||
|
|
251
|
+
taskUpdatesCount > 0 ||
|
|
252
|
+
milestoneUpdatesCount > 0;
|
|
253
|
+
if (hasExplicitOutcomeArrays && !hasOutcomes) {
|
|
254
|
+
changed = true;
|
|
255
|
+
nextRecord = { ...nextRecord, status: "error" };
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
const finalStatus = typeof nextRecord.status === "string" ? nextRecord.status : "";
|
|
259
|
+
const requiresBlockingDecision = finalStatus === "blocked" || finalStatus === "needs_decision" || finalStatus === "error";
|
|
260
|
+
if (requiresBlockingDecision && !hasBlockingDecision(nextRecord)) {
|
|
261
|
+
const nextDecisions = Array.isArray(nextRecord.decisions_needed)
|
|
262
|
+
? [...nextRecord.decisions_needed]
|
|
263
|
+
: [];
|
|
264
|
+
nextDecisions.push({
|
|
265
|
+
question: "Missing required blocking decision for non-completed status",
|
|
266
|
+
summary: "Parser inserted a blocking decision because blocked/needs_decision/error statuses require blocking=true.",
|
|
267
|
+
options: null,
|
|
268
|
+
urgency: "medium",
|
|
269
|
+
blocking: true,
|
|
270
|
+
});
|
|
271
|
+
changed = true;
|
|
272
|
+
nextRecord = { ...nextRecord, decisions_needed: nextDecisions };
|
|
273
|
+
}
|
|
274
|
+
return changed ? nextRecord : value;
|
|
275
|
+
};
|
|
276
|
+
const unwrapStructuredOutput = (value) => {
|
|
277
|
+
if (!value || typeof value !== "object")
|
|
278
|
+
return null;
|
|
279
|
+
const record = value;
|
|
280
|
+
const parseEmbeddedText = (candidate) => {
|
|
281
|
+
if (typeof candidate === "string") {
|
|
282
|
+
return parseSliceJsonText(candidate);
|
|
283
|
+
}
|
|
284
|
+
if (Array.isArray(candidate)) {
|
|
285
|
+
for (let i = candidate.length - 1; i >= 0; i -= 1) {
|
|
286
|
+
const parsed = parseEmbeddedText(candidate[i]);
|
|
287
|
+
if (parsed)
|
|
288
|
+
return parsed;
|
|
289
|
+
}
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
if (!candidate || typeof candidate !== "object")
|
|
293
|
+
return null;
|
|
294
|
+
const candidateRecord = candidate;
|
|
295
|
+
if (typeof candidateRecord.value === "string") {
|
|
296
|
+
return parseSliceJsonText(candidateRecord.value);
|
|
297
|
+
}
|
|
298
|
+
if (typeof candidateRecord.text === "string") {
|
|
299
|
+
return parseSliceJsonText(candidateRecord.text);
|
|
300
|
+
}
|
|
301
|
+
const fromValue = parseEmbeddedText(candidateRecord.value);
|
|
302
|
+
if (fromValue)
|
|
303
|
+
return fromValue;
|
|
304
|
+
const fromText = parseEmbeddedText(candidateRecord.text);
|
|
305
|
+
if (fromText)
|
|
306
|
+
return fromText;
|
|
307
|
+
const fromOutputText = parseEmbeddedText(candidateRecord.output_text);
|
|
308
|
+
if (fromOutputText)
|
|
309
|
+
return fromOutputText;
|
|
310
|
+
return null;
|
|
311
|
+
};
|
|
312
|
+
const finalOutput = record.final_output;
|
|
313
|
+
if (finalOutput && typeof finalOutput === "object") {
|
|
314
|
+
if (isLikelySliceResult(finalOutput))
|
|
315
|
+
return normalizeSliceResult(finalOutput);
|
|
316
|
+
const parsedFinalOutput = parseEmbeddedText(finalOutput);
|
|
317
|
+
if (parsedFinalOutput)
|
|
318
|
+
return parsedFinalOutput;
|
|
319
|
+
return null;
|
|
320
|
+
}
|
|
321
|
+
if (typeof finalOutput === "string") {
|
|
322
|
+
const parsedFinalOutput = parseSliceJsonText(finalOutput);
|
|
323
|
+
if (parsedFinalOutput)
|
|
324
|
+
return parsedFinalOutput;
|
|
325
|
+
}
|
|
326
|
+
const structured = record.structured_output;
|
|
327
|
+
if (structured && typeof structured === "object") {
|
|
328
|
+
if (isLikelySliceResult(structured))
|
|
329
|
+
return normalizeSliceResult(structured);
|
|
330
|
+
const parsedStructured = parseEmbeddedText(structured);
|
|
331
|
+
if (parsedStructured)
|
|
332
|
+
return parsedStructured;
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
if (typeof structured === "string") {
|
|
336
|
+
const parsedStructured = parseSliceJsonText(structured);
|
|
337
|
+
if (parsedStructured)
|
|
338
|
+
return parsedStructured;
|
|
339
|
+
}
|
|
340
|
+
// Claude text-mode envelopes can sometimes return JSON in `result`.
|
|
341
|
+
const parsedResultObject = parseEmbeddedText(record.result);
|
|
342
|
+
if (parsedResultObject)
|
|
343
|
+
return parsedResultObject;
|
|
344
|
+
if (typeof record.result === "string") {
|
|
345
|
+
const parsedResult = parseSliceJsonText(record.result);
|
|
346
|
+
if (parsedResult)
|
|
347
|
+
return parsedResult;
|
|
348
|
+
}
|
|
349
|
+
if (typeof record.output_text === "string") {
|
|
350
|
+
const parsedOutputText = parseSliceJsonText(record.output_text);
|
|
351
|
+
if (parsedOutputText)
|
|
352
|
+
return parsedOutputText;
|
|
353
|
+
}
|
|
354
|
+
// Responses-style envelopes can return text in output/message/content arrays.
|
|
355
|
+
const output = record.output;
|
|
356
|
+
if (Array.isArray(output)) {
|
|
357
|
+
for (let i = output.length - 1; i >= 0; i -= 1) {
|
|
358
|
+
const item = output[i];
|
|
359
|
+
if (!item || typeof item !== "object")
|
|
360
|
+
continue;
|
|
361
|
+
const itemRecord = item;
|
|
362
|
+
const directText = parseEmbeddedText(itemRecord.text);
|
|
363
|
+
if (directText)
|
|
364
|
+
return directText;
|
|
365
|
+
const outputText = parseEmbeddedText(itemRecord.output_text);
|
|
366
|
+
if (outputText)
|
|
367
|
+
return outputText;
|
|
368
|
+
if (!Array.isArray(itemRecord.content))
|
|
369
|
+
continue;
|
|
370
|
+
for (let j = itemRecord.content.length - 1; j >= 0; j -= 1) {
|
|
371
|
+
const content = itemRecord.content[j];
|
|
372
|
+
if (!content || typeof content !== "object")
|
|
373
|
+
continue;
|
|
374
|
+
const contentRecord = content;
|
|
375
|
+
const contentDirect = parseEmbeddedText(contentRecord);
|
|
376
|
+
if (contentDirect)
|
|
377
|
+
return contentDirect;
|
|
378
|
+
const contentText = parseEmbeddedText(contentRecord.text);
|
|
379
|
+
if (contentText)
|
|
380
|
+
return contentText;
|
|
381
|
+
const contentOutputText = parseEmbeddedText(contentRecord.output_text);
|
|
382
|
+
if (contentOutputText)
|
|
383
|
+
return contentOutputText;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
return isLikelySliceResult(record) ? normalizeSliceResult(record) : null;
|
|
388
|
+
};
|
|
389
|
+
const trimmed = stripUtf8Bom(raw).trim();
|
|
127
390
|
if (!trimmed)
|
|
128
391
|
return null;
|
|
129
|
-
const direct = parseJsonSafe(trimmed);
|
|
130
|
-
|
|
131
|
-
|
|
392
|
+
const direct = parseJsonSafe(stripMarkdownJsonFence(trimmed));
|
|
393
|
+
const directUnwrapped = unwrapStructuredOutput(direct);
|
|
394
|
+
if (directUnwrapped && typeof directUnwrapped === "object")
|
|
395
|
+
return directUnwrapped;
|
|
396
|
+
const directTextParsed = parseSliceJsonText(trimmed);
|
|
397
|
+
if (directTextParsed && typeof directTextParsed === "object")
|
|
398
|
+
return directTextParsed;
|
|
132
399
|
// Tolerant parse: extract the last complete top-level JSON object from mixed logs.
|
|
133
|
-
const
|
|
400
|
+
const extractTopLevelObjects = (text) => {
|
|
134
401
|
let inString = false;
|
|
135
402
|
let escaped = false;
|
|
136
403
|
let depth = 0;
|
|
137
404
|
let start = -1;
|
|
138
|
-
|
|
405
|
+
const objects = [];
|
|
139
406
|
for (let i = 0; i < text.length; i += 1) {
|
|
140
407
|
const ch = text[i];
|
|
141
408
|
if (inString) {
|
|
@@ -167,18 +434,20 @@ export function parseSliceResult(raw) {
|
|
|
167
434
|
continue;
|
|
168
435
|
depth -= 1;
|
|
169
436
|
if (depth === 0 && start >= 0) {
|
|
170
|
-
|
|
437
|
+
objects.push(text.slice(start, i + 1));
|
|
171
438
|
start = -1;
|
|
172
439
|
}
|
|
173
440
|
}
|
|
174
441
|
}
|
|
175
|
-
return
|
|
442
|
+
return objects;
|
|
176
443
|
};
|
|
177
|
-
const
|
|
178
|
-
|
|
444
|
+
const candidates = extractTopLevelObjects(trimmed);
|
|
445
|
+
for (let i = candidates.length - 1; i >= 0; i -= 1) {
|
|
446
|
+
const candidate = candidates[i];
|
|
179
447
|
const parsed = parseJsonSafe(candidate);
|
|
180
|
-
|
|
181
|
-
|
|
448
|
+
const unwrapped = unwrapStructuredOutput(parsed);
|
|
449
|
+
if (unwrapped && typeof unwrapped === "object")
|
|
450
|
+
return unwrapped;
|
|
182
451
|
}
|
|
183
452
|
return null;
|
|
184
453
|
}
|
|
@@ -237,7 +506,13 @@ export function normalizeCodexArgs(args) {
|
|
|
237
506
|
normalized.unshift("exec");
|
|
238
507
|
}
|
|
239
508
|
if (!normalized.includes("--skip-git-repo-check")) {
|
|
240
|
-
normalized.
|
|
509
|
+
const passthroughIndex = normalized.indexOf("--");
|
|
510
|
+
if (passthroughIndex > -1) {
|
|
511
|
+
normalized.splice(passthroughIndex, 0, "--skip-git-repo-check");
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
normalized.push("--skip-git-repo-check");
|
|
515
|
+
}
|
|
241
516
|
}
|
|
242
517
|
return normalized;
|
|
243
518
|
}
|
|
@@ -423,7 +698,94 @@ export function createCodexBinResolver() {
|
|
|
423
698
|
getCachedCodexProbeSummary,
|
|
424
699
|
};
|
|
425
700
|
}
|
|
701
|
+
function normalizeSkillName(skill) {
|
|
702
|
+
return skill.replace(/^\$/, "").trim();
|
|
703
|
+
}
|
|
704
|
+
function skillAliasesFor(skill) {
|
|
705
|
+
const normalized = normalizeSkillName(skill);
|
|
706
|
+
if (!normalized)
|
|
707
|
+
return [];
|
|
708
|
+
const aliases = [normalized];
|
|
709
|
+
if (normalized.startsWith("orgx-"))
|
|
710
|
+
aliases.push(normalized.slice("orgx-".length));
|
|
711
|
+
if (normalized.endsWith("-agent"))
|
|
712
|
+
aliases.push(normalized.slice(0, -"-agent".length));
|
|
713
|
+
return Array.from(new Set(aliases.filter(Boolean)));
|
|
714
|
+
}
|
|
715
|
+
function buildSkillHints(requiredSkills) {
|
|
716
|
+
return requiredSkills
|
|
717
|
+
.map((skill) => {
|
|
718
|
+
const normalized = normalizeSkillName(skill);
|
|
719
|
+
const aliases = skillAliasesFor(normalized);
|
|
720
|
+
const hintPaths = aliases
|
|
721
|
+
.flatMap((alias) => [
|
|
722
|
+
join(homedir(), ".codex", "skills", alias, "SKILL.md"),
|
|
723
|
+
join(homedir(), ".agents", "skills", alias, "SKILL.md"),
|
|
724
|
+
])
|
|
725
|
+
.filter(Boolean);
|
|
726
|
+
return {
|
|
727
|
+
skill: normalized,
|
|
728
|
+
hintPaths: Array.from(new Set(hintPaths)),
|
|
729
|
+
};
|
|
730
|
+
})
|
|
731
|
+
.filter((entry) => entry.skill.length > 0);
|
|
732
|
+
}
|
|
733
|
+
export function buildSliceOutputInstructions(input) {
|
|
734
|
+
const skillHints = buildSkillHints(input.requiredSkills);
|
|
735
|
+
return [
|
|
736
|
+
"# Slice Execution",
|
|
737
|
+
"",
|
|
738
|
+
`Slice run: ${input.runId}`,
|
|
739
|
+
"",
|
|
740
|
+
"Reporting:",
|
|
741
|
+
"- You MUST emit progress at least twice (start + completion) using an OrgX progress tool.",
|
|
742
|
+
"- Preferred tool: orgx_report_progress. Equivalent aliases are valid (for example mcp__orgx__update_stream_progress).",
|
|
743
|
+
"- If no OrgX progress tool is available, include a blocking decisions_needed entry describing the missing tool.",
|
|
744
|
+
"- Do NOT hunt for OrgX mutation tools to mark tasks done. Instead, request status changes in your FINAL JSON via task_updates/milestone_updates; the coordinator will apply them.",
|
|
745
|
+
"",
|
|
746
|
+
"What to do:",
|
|
747
|
+
"- Choose a coherent slice of work you can complete end-to-end in this run.",
|
|
748
|
+
"- Execute the work (code/docs/config) and produce verifiable outcomes.",
|
|
749
|
+
"- Self-assess confidence when saving artifacts and include `confidence_score` in [0,1].",
|
|
750
|
+
"- If blocked, be explicit about what decision/info is required.",
|
|
751
|
+
"- Keep this run focused: stay inside the current repository/workdir and avoid unrelated exploration.",
|
|
752
|
+
"- Execution budget: prefer <=12 shell commands and <=6 minutes wall time.",
|
|
753
|
+
"- Verification budget: run only targeted checks for changed files. Avoid full-suite commands (for example `npm run test:hooks`, `npm test`, `npm run build`) unless the task explicitly requires them.",
|
|
754
|
+
"- If you hit sandbox/env blockers after one retry, stop and return `status=needs_decision` with the blocker and the smallest unblocking action.",
|
|
755
|
+
"- For each required skill, read the skill document and collect proof (path + sha256 + heading).",
|
|
756
|
+
"",
|
|
757
|
+
"Output requirements:",
|
|
758
|
+
"- Print ONLY a single JSON object as the final output (no interim JSON status messages).",
|
|
759
|
+
`- Your JSON MUST conform to this schema file: ${input.schemaPath}`,
|
|
760
|
+
"- Artifacts must be verifiable: include URLs or local paths, plus verification steps.",
|
|
761
|
+
"- Include `confidence_score` for each artifact (`0` to `1`; use `null` when unknown).",
|
|
762
|
+
"- If you need a human decision, include it in decisions_needed.",
|
|
763
|
+
"- For every decisions_needed entry, ALWAYS set blocking explicitly (true or false).",
|
|
764
|
+
"- If status is blocked, needs_decision, or error: include at least one decisions_needed entry with blocking=true.",
|
|
765
|
+
"- Status/decision consistency is strict:",
|
|
766
|
+
" - If any decision is blocking=true, status MUST be needs_decision or blocked (never completed).",
|
|
767
|
+
" - Only use status=completed when all listed decisions are non-blocking follow-ups.",
|
|
768
|
+
"- Never return status=completed with zero artifacts and zero task/milestone updates.",
|
|
769
|
+
"- skill_evidence is mandatory. Include one object per required skill with:",
|
|
770
|
+
" - skill (exact required skill id without leading $)",
|
|
771
|
+
" - skill_file (absolute SKILL.md path used)",
|
|
772
|
+
" - skill_sha256 (lowercase SHA-256 hex of that file)",
|
|
773
|
+
" - skill_heading (first markdown heading or first non-empty line)",
|
|
774
|
+
"- If you cannot locate/verify a required skill file, return status=needs_decision and a blocking decisions_needed entry.",
|
|
775
|
+
"Skill file hints:",
|
|
776
|
+
...(skillHints.length > 0
|
|
777
|
+
? skillHints.flatMap((entry) => [
|
|
778
|
+
`- ${entry.skill}:`,
|
|
779
|
+
...entry.hintPaths.map((path) => ` - ${path}`),
|
|
780
|
+
])
|
|
781
|
+
: ["- (none)"]),
|
|
782
|
+
"- If you are confident OrgX statuses should change, include task_updates and/or milestone_updates (with a short reason).",
|
|
783
|
+
" - task_updates.status must be one of: todo, in_progress, done, blocked",
|
|
784
|
+
" - milestone_updates.status must be one of: planned, in_progress, completed, at_risk, cancelled",
|
|
785
|
+
].join("\n");
|
|
786
|
+
}
|
|
426
787
|
export function buildWorkstreamSlicePrompt(input) {
|
|
788
|
+
const skillHints = buildSkillHints(input.executionPolicy.requiredSkills);
|
|
427
789
|
const milestones = input.milestoneSummaries
|
|
428
790
|
.map((m) => `- ${m.title} (${m.status}) [${m.id}]`)
|
|
429
791
|
.slice(0, 10)
|
|
@@ -435,8 +797,25 @@ export function buildWorkstreamSlicePrompt(input) {
|
|
|
435
797
|
})
|
|
436
798
|
.slice(0, 18)
|
|
437
799
|
.join("\n");
|
|
800
|
+
const behaviorConfigLines = [
|
|
801
|
+
input.behaviorConfig?.configId
|
|
802
|
+
? `- behavior_config_id: ${input.behaviorConfig.configId}`
|
|
803
|
+
: null,
|
|
804
|
+
input.behaviorConfig?.version
|
|
805
|
+
? `- behavior_config_version: ${input.behaviorConfig.version}`
|
|
806
|
+
: null,
|
|
807
|
+
input.behaviorConfig?.hash
|
|
808
|
+
? `- behavior_config_hash: ${input.behaviorConfig.hash}`
|
|
809
|
+
: null,
|
|
810
|
+
input.behaviorConfig?.policySource
|
|
811
|
+
? `- policy_source: ${input.behaviorConfig.policySource}`
|
|
812
|
+
: null,
|
|
813
|
+
input.behaviorConfig?.context
|
|
814
|
+
? `- behavior_context: ${input.behaviorConfig.context}`
|
|
815
|
+
: null,
|
|
816
|
+
].filter((line) => Boolean(line));
|
|
438
817
|
return [
|
|
439
|
-
"You are an OrgX execution agent running ONE workstream slice in a background
|
|
818
|
+
"You are an OrgX execution agent running ONE workstream slice in a background autonomous session.",
|
|
440
819
|
"",
|
|
441
820
|
`Execution policy: ${input.executionPolicy.domain}`,
|
|
442
821
|
`Required skills: ${input.executionPolicy.requiredSkills.map((s) => (s.startsWith("$") ? s : `$${s}`)).join(", ")}`,
|
|
@@ -444,6 +823,13 @@ export function buildWorkstreamSlicePrompt(input) {
|
|
|
444
823
|
`Initiative: ${input.initiativeTitle} [${input.initiativeId}]`,
|
|
445
824
|
`Workstream: ${input.workstreamTitle} [${input.workstreamId}]`,
|
|
446
825
|
`Slice run: ${input.runId}`,
|
|
826
|
+
...(behaviorConfigLines.length > 0
|
|
827
|
+
? [
|
|
828
|
+
"",
|
|
829
|
+
"Behavior config (plugin-injected context):",
|
|
830
|
+
...behaviorConfigLines,
|
|
831
|
+
]
|
|
832
|
+
: []),
|
|
447
833
|
"",
|
|
448
834
|
"Milestones (context):",
|
|
449
835
|
milestones || "- (none found)",
|
|
@@ -452,25 +838,62 @@ export function buildWorkstreamSlicePrompt(input) {
|
|
|
452
838
|
tasks || "- (none found)",
|
|
453
839
|
"",
|
|
454
840
|
"Reporting:",
|
|
455
|
-
"-
|
|
841
|
+
"- You MUST emit progress at least twice (start + completion) using an OrgX progress tool.",
|
|
842
|
+
"- Preferred tool: orgx_report_progress. Equivalent aliases are valid (for example mcp__orgx__update_stream_progress).",
|
|
843
|
+
"- If no OrgX progress tool is available, include a blocking decisions_needed entry describing the missing tool.",
|
|
456
844
|
"- Do NOT hunt for OrgX mutation tools to mark tasks done. Instead, request status changes in your FINAL JSON via task_updates/milestone_updates; the coordinator will apply them.",
|
|
457
845
|
"",
|
|
458
846
|
"What to do:",
|
|
459
847
|
"- Choose a coherent slice of work you can complete end-to-end in this run.",
|
|
460
848
|
"- Execute the work (code/docs/config) and produce verifiable outcomes.",
|
|
849
|
+
"- Self-assess confidence when saving artifacts and include `confidence_score` in [0,1].",
|
|
461
850
|
"- If blocked, be explicit about what decision/info is required.",
|
|
851
|
+
"- Keep this run focused: stay inside the current repository/workdir and avoid unrelated exploration.",
|
|
852
|
+
"- Execution budget: prefer <=12 shell commands and <=6 minutes wall time.",
|
|
853
|
+
"- Verification budget: run only targeted checks for changed files. Avoid full-suite commands (for example `npm run test:hooks`, `npm test`, `npm run build`) unless the task explicitly requires them.",
|
|
854
|
+
"- If you hit sandbox/env blockers after one retry, stop and return `status=needs_decision` with the blocker and the smallest unblocking action.",
|
|
855
|
+
"- For each required skill, read the skill document and collect proof (path + sha256 + heading).",
|
|
462
856
|
"",
|
|
463
857
|
"Output requirements:",
|
|
464
|
-
"- Print ONLY a single JSON object as the final output.",
|
|
858
|
+
"- Print ONLY a single JSON object as the final output (no interim JSON status messages).",
|
|
465
859
|
`- Your JSON MUST conform to this schema file: ${input.schemaPath}`,
|
|
466
860
|
"- Artifacts must be verifiable: include URLs or local paths, plus verification steps.",
|
|
861
|
+
"- Include `confidence_score` for each artifact (`0` to `1`; use `null` when unknown).",
|
|
467
862
|
"- If you need a human decision, include it in decisions_needed.",
|
|
468
863
|
"- For every decisions_needed entry, ALWAYS set blocking explicitly (true or false).",
|
|
864
|
+
"- If status is blocked, needs_decision, or error: include at least one decisions_needed entry with blocking=true.",
|
|
469
865
|
"- Status/decision consistency is strict:",
|
|
470
866
|
" - If any decision is blocking=true, status MUST be needs_decision or blocked (never completed).",
|
|
471
867
|
" - Only use status=completed when all listed decisions are non-blocking follow-ups.",
|
|
868
|
+
"- Never return status=completed with zero artifacts and zero task/milestone updates.",
|
|
869
|
+
"- skill_evidence is mandatory. Include one object per required skill with:",
|
|
870
|
+
" - skill (exact required skill id without leading $)",
|
|
871
|
+
" - skill_file (absolute SKILL.md path used)",
|
|
872
|
+
" - skill_sha256 (lowercase SHA-256 hex of that file)",
|
|
873
|
+
" - skill_heading (first markdown heading or first non-empty line)",
|
|
874
|
+
"- If you cannot locate/verify a required skill file, return status=needs_decision and a blocking decisions_needed entry.",
|
|
875
|
+
"Skill file hints:",
|
|
876
|
+
...(skillHints.length > 0
|
|
877
|
+
? skillHints.flatMap((entry) => [
|
|
878
|
+
`- ${entry.skill}:`,
|
|
879
|
+
...entry.hintPaths.map((path) => ` - ${path}`),
|
|
880
|
+
])
|
|
881
|
+
: ["- (none)"]),
|
|
472
882
|
"- If you are confident OrgX statuses should change, include task_updates and/or milestone_updates (with a short reason).",
|
|
473
883
|
" - task_updates.status must be one of: todo, in_progress, done, blocked",
|
|
474
884
|
" - milestone_updates.status must be one of: planned, in_progress, completed, at_risk, cancelled",
|
|
475
885
|
].join("\n");
|
|
476
886
|
}
|
|
887
|
+
export function buildScopeDirective(scope, meta) {
|
|
888
|
+
switch (scope) {
|
|
889
|
+
case "milestone":
|
|
890
|
+
return (`You are completing milestone "${meta.milestoneTitles?.[0] ?? "Unknown"}" ` +
|
|
891
|
+
`(${meta.taskCount} tasks). Complete all tasks to close the milestone. Report per-task progress.`);
|
|
892
|
+
case "workstream":
|
|
893
|
+
return (`You are advancing the entire "${meta.workstreamTitle ?? "Unknown"}" workstream ` +
|
|
894
|
+
`(${meta.taskCount} tasks across ${meta.milestoneTitles?.length ?? 0} milestones). ` +
|
|
895
|
+
`Prioritize by dependency order. Report per-milestone progress.`);
|
|
896
|
+
default:
|
|
897
|
+
return "";
|
|
898
|
+
}
|
|
899
|
+
}
|