@voybio/ace-swarm 0.2.5 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -1
- package/README.md +21 -13
- package/assets/.agents/ACE/agent-qa/instructions.md +11 -0
- package/assets/agent-state/EVIDENCE_LOG.md +1 -1
- package/assets/agent-state/MODULES/roles/capability-framework.json +41 -0
- package/assets/agent-state/MODULES/roles/capability-git.json +33 -0
- package/assets/agent-state/MODULES/roles/capability-safety.json +37 -0
- package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +21 -0
- package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +43 -0
- package/assets/agent-state/MODULES/schemas/RUNTIME_TOOL_SPEC_REGISTRY.schema.json +43 -0
- package/assets/agent-state/MODULES/schemas/WORKSPACE_SESSION_REGISTRY.schema.json +11 -0
- package/assets/agent-state/STATUS.md +2 -2
- package/assets/agent-state/runtime-tool-specs.json +70 -2
- package/assets/instructions/ACE_Coder.instructions.md +13 -0
- package/assets/instructions/ACE_UI.instructions.md +11 -0
- package/assets/scripts/ace-hook-dispatch.mjs +70 -6
- package/assets/scripts/render-mcp-configs.sh +19 -5
- package/dist/ace-context.js +91 -11
- package/dist/ace-internal-tools.d.ts +3 -1
- package/dist/ace-internal-tools.js +10 -2
- package/dist/ace-server-instructions.js +3 -3
- package/dist/ace-state-resolver.js +5 -3
- package/dist/agent-runtime/role-adapters.d.ts +18 -1
- package/dist/agent-runtime/role-adapters.js +49 -5
- package/dist/astgrep-index.d.ts +57 -1
- package/dist/astgrep-index.js +140 -4
- package/dist/cli.js +232 -35
- package/dist/discovery-runtime-wrappers.d.ts +108 -0
- package/dist/discovery-runtime-wrappers.js +615 -0
- package/dist/handoff-registry.js +5 -5
- package/dist/helpers/artifacts.d.ts +19 -0
- package/dist/helpers/artifacts.js +152 -0
- package/dist/helpers/bootstrap.d.ts +24 -0
- package/dist/helpers/bootstrap.js +894 -0
- package/dist/helpers/constants.d.ts +53 -0
- package/dist/helpers/constants.js +295 -0
- package/dist/helpers/drift.d.ts +13 -0
- package/dist/helpers/drift.js +45 -0
- package/dist/helpers/path-utils.d.ts +24 -0
- package/dist/helpers/path-utils.js +123 -0
- package/dist/helpers/store-resolution.d.ts +19 -0
- package/dist/helpers/store-resolution.js +305 -0
- package/dist/helpers/workspace-root.d.ts +3 -0
- package/dist/helpers/workspace-root.js +80 -0
- package/dist/helpers.d.ts +8 -125
- package/dist/helpers.js +8 -1768
- package/dist/job-scheduler.js +33 -7
- package/dist/json-sanitizer.d.ts +16 -0
- package/dist/json-sanitizer.js +26 -0
- package/dist/local-model-policy.d.ts +27 -0
- package/dist/local-model-policy.js +84 -0
- package/dist/local-model-runtime.d.ts +6 -0
- package/dist/local-model-runtime.js +33 -21
- package/dist/model-bridge.d.ts +13 -1
- package/dist/model-bridge.js +410 -23
- package/dist/orchestrator-supervisor.d.ts +56 -0
- package/dist/orchestrator-supervisor.js +179 -1
- package/dist/plan-proposal.d.ts +115 -0
- package/dist/plan-proposal.js +1073 -0
- package/dist/run-ledger.js +3 -3
- package/dist/runtime-command.d.ts +8 -0
- package/dist/runtime-command.js +38 -6
- package/dist/runtime-executor.d.ts +20 -1
- package/dist/runtime-executor.js +737 -172
- package/dist/runtime-profile.d.ts +32 -0
- package/dist/runtime-profile.js +89 -13
- package/dist/runtime-tool-specs.d.ts +39 -0
- package/dist/runtime-tool-specs.js +144 -28
- package/dist/safe-edit.d.ts +7 -0
- package/dist/safe-edit.js +163 -37
- package/dist/schemas.js +48 -1
- package/dist/server.js +51 -0
- package/dist/shared.d.ts +3 -2
- package/dist/shared.js +2 -0
- package/dist/status-events.js +9 -6
- package/dist/store/ace-packed-store.d.ts +3 -2
- package/dist/store/ace-packed-store.js +188 -110
- package/dist/store/bootstrap-store.d.ts +2 -1
- package/dist/store/bootstrap-store.js +102 -83
- package/dist/store/cache-workspace.js +11 -5
- package/dist/store/materializers/context-snapshot-materializer.js +6 -2
- package/dist/store/materializers/hook-context-materializer.d.ts +6 -9
- package/dist/store/materializers/hook-context-materializer.js +11 -21
- package/dist/store/materializers/host-file-materializer.js +6 -0
- package/dist/store/materializers/projection-manager.d.ts +0 -1
- package/dist/store/materializers/projection-manager.js +5 -13
- package/dist/store/materializers/scheduler-projection-materializer.js +1 -1
- package/dist/store/materializers/vericify-projector.d.ts +7 -7
- package/dist/store/materializers/vericify-projector.js +11 -11
- package/dist/store/repositories/local-model-runtime-repository.d.ts +120 -3
- package/dist/store/repositories/local-model-runtime-repository.js +242 -6
- package/dist/store/repositories/vericify-repository.d.ts +1 -1
- package/dist/store/skills-install.d.ts +4 -0
- package/dist/store/skills-install.js +21 -12
- package/dist/store/state-reader.d.ts +2 -0
- package/dist/store/state-reader.js +20 -0
- package/dist/store/store-artifacts.d.ts +7 -0
- package/dist/store/store-artifacts.js +27 -1
- package/dist/store/store-authority-audit.d.ts +18 -1
- package/dist/store/store-authority-audit.js +115 -5
- package/dist/store/store-snapshot.d.ts +3 -0
- package/dist/store/store-snapshot.js +22 -2
- package/dist/store/workspace-store-paths.d.ts +39 -0
- package/dist/store/workspace-store-paths.js +94 -0
- package/dist/store/write-coordinator.d.ts +65 -0
- package/dist/store/write-coordinator.js +386 -0
- package/dist/todo-state.js +5 -5
- package/dist/tools-agent.d.ts +20 -0
- package/dist/tools-agent.js +789 -25
- package/dist/tools-discovery.js +136 -1
- package/dist/tools-files.d.ts +7 -0
- package/dist/tools-files.js +1002 -11
- package/dist/tools-framework.js +105 -66
- package/dist/tools-handoff.js +2 -2
- package/dist/tools-lifecycle.js +4 -4
- package/dist/tools-memory.js +6 -6
- package/dist/tools-todo.js +2 -2
- package/dist/tracker-adapters.d.ts +1 -1
- package/dist/tracker-adapters.js +13 -18
- package/dist/tracker-sync.js +5 -3
- package/dist/tui/agent-runner.js +3 -1
- package/dist/tui/chat.js +103 -7
- package/dist/tui/dashboard.d.ts +1 -0
- package/dist/tui/dashboard.js +43 -0
- package/dist/tui/index.js +10 -1
- package/dist/tui/layout.d.ts +20 -0
- package/dist/tui/layout.js +31 -1
- package/dist/tui/local-model-contract.d.ts +6 -2
- package/dist/tui/local-model-contract.js +16 -3
- package/dist/tui/ollama.d.ts +8 -1
- package/dist/tui/ollama.js +53 -12
- package/dist/tui/openai-compatible.d.ts +13 -0
- package/dist/tui/openai-compatible.js +305 -5
- package/dist/tui/provider-discovery.d.ts +1 -0
- package/dist/tui/provider-discovery.js +35 -11
- package/dist/vericify-bridge.d.ts +6 -1
- package/dist/vericify-bridge.js +27 -3
- package/dist/workspace-manager.d.ts +30 -3
- package/dist/workspace-manager.js +257 -27
- package/package.json +1 -2
- package/dist/internal-tool-runtime.d.ts +0 -21
- package/dist/internal-tool-runtime.js +0 -136
- package/dist/store/workspace-snapshot.d.ts +0 -26
- package/dist/store/workspace-snapshot.js +0 -107
package/dist/tools-framework.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { bootstrapStoreWorkspace } from "./store/bootstrap-store.js";
|
|
7
|
-
import { ACE_ROOT_REL, ACE_TASKS_ROOT_REL, ALL_MCP_CLIENTS, ALL_LLM_PROVIDERS, ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, WORKSPACE_ROOT, classifyPathSource, detectAssetDrift, getAllMcpServerConfigSnippets, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, getMcpClientInstallHint, getMcpServerConfigSnippet, getTaskArtifactPath, isSwarmRole, listAvailableSkills, normalizePathForValidation, resolveWorkspaceRoot, safeRead,
|
|
7
|
+
import { ACE_ROOT_REL, ACE_TASKS_ROOT_REL, ALL_MCP_CLIENTS, ALL_LLM_PROVIDERS, ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, WORKSPACE_ROOT, classifyPathSource, detectAssetDrift, getAllMcpServerConfigSnippets, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, getMcpClientInstallHint, getMcpServerConfigSnippet, getTaskArtifactPath, isSwarmRole, listAvailableSkills, normalizePathForValidation, resolveWorkspaceRoot, safeRead, safeWriteAsync, withFileLock, wsPath, } from "./helpers.js";
|
|
8
8
|
import { getRoleTitle, MCP_CLIENT_ENUM, scoreDomains, } from "./shared.js";
|
|
9
9
|
import { defaultModelForProvider, } from "./tui/provider-discovery.js";
|
|
10
10
|
import { refreshAstgrepIndex } from "./astgrep-index.js";
|
|
@@ -21,6 +21,21 @@ import { auditStoreAuthority, writeStoreAuthorityAuditReport, } from "./store/st
|
|
|
21
21
|
import { PROVENANCE_CRITICAL_EVENT_TYPES, validateArtifactManifestPayload, validateProvenanceLogContent, validateTealConfigContent, } from "./schemas.js";
|
|
22
22
|
import { readAceTaskContractAssessment } from "./ace-autonomy.js";
|
|
23
23
|
import { listStoreKeysSync, readStoreBlobSync } from "./store/store-snapshot.js";
|
|
24
|
+
import { parseJsonLikeText } from "./json-sanitizer.js";
|
|
25
|
+
function executionRoleForDomain(domain) {
|
|
26
|
+
switch (domain) {
|
|
27
|
+
case "venture":
|
|
28
|
+
return "vos";
|
|
29
|
+
case "ux":
|
|
30
|
+
return "ui";
|
|
31
|
+
case "engineering":
|
|
32
|
+
return "coders";
|
|
33
|
+
case "research":
|
|
34
|
+
return "research";
|
|
35
|
+
default:
|
|
36
|
+
return "orchestrator";
|
|
37
|
+
}
|
|
38
|
+
}
|
|
24
39
|
function getArtifactManifestEntries(payload) {
|
|
25
40
|
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
26
41
|
return [];
|
|
@@ -61,6 +76,14 @@ function parseGateManifest(raw, sourceRef) {
|
|
|
61
76
|
return undefined;
|
|
62
77
|
}
|
|
63
78
|
}
|
|
79
|
+
function parseJsonForValidation(raw) {
|
|
80
|
+
return parseJsonLikeText(raw);
|
|
81
|
+
}
|
|
82
|
+
function jsonValidationDetail(parsed, validDetail = "valid JSON") {
|
|
83
|
+
return parsed.sanitized.removed_control_bytes > 0
|
|
84
|
+
? `control bytes removed before parse (${parsed.sanitized.removed_control_bytes}); source requires repair`
|
|
85
|
+
: validDetail;
|
|
86
|
+
}
|
|
64
87
|
function readGateManifests(gatesDir) {
|
|
65
88
|
const files = readdirSync(gatesDir).filter((f) => f.endsWith(".json"));
|
|
66
89
|
const allGates = [];
|
|
@@ -287,7 +310,7 @@ async function appendEvidenceLogEntrySafe(review) {
|
|
|
287
310
|
const timestamp = new Date().toISOString();
|
|
288
311
|
const anchor = `#ts:${timestamp}`;
|
|
289
312
|
const evidenceRef = `agent-state/EVIDENCE_LOG.md${anchor}`;
|
|
290
|
-
return withFileLock("agent-state/EVIDENCE_LOG.md", () => {
|
|
313
|
+
return withFileLock("agent-state/EVIDENCE_LOG.md", async () => {
|
|
291
314
|
const existing = safeRead("agent-state/EVIDENCE_LOG.md");
|
|
292
315
|
const seed = existing.startsWith("[FILE NOT FOUND]") || existing.startsWith("[ACCESS DENIED]")
|
|
293
316
|
? "# EVIDENCE LOG\n\nAppend-only validation evidence.\n\n## Entries\n"
|
|
@@ -319,7 +342,7 @@ async function appendEvidenceLogEntrySafe(review) {
|
|
|
319
342
|
})
|
|
320
343
|
: [" - none"]),
|
|
321
344
|
];
|
|
322
|
-
const path =
|
|
345
|
+
const path = await safeWriteAsync("agent-state/EVIDENCE_LOG.md", `${seed}${lines.join("\n")}\n`);
|
|
323
346
|
return { path, evidenceRef };
|
|
324
347
|
});
|
|
325
348
|
}
|
|
@@ -534,6 +557,12 @@ export function registerFrameworkTools(server) {
|
|
|
534
557
|
recommendedSubagents.add("memory");
|
|
535
558
|
}
|
|
536
559
|
return {
|
|
560
|
+
structuredContent: {
|
|
561
|
+
detected_domain: detected,
|
|
562
|
+
suggested_execution_role: executionRoleForDomain(detected),
|
|
563
|
+
default_entry_agent: "orchestrator",
|
|
564
|
+
task_contract_ok: taskContract.ok,
|
|
565
|
+
},
|
|
537
566
|
content: [
|
|
538
567
|
{
|
|
539
568
|
type: "text",
|
|
@@ -635,7 +664,7 @@ export function registerFrameworkTools(server) {
|
|
|
635
664
|
model: resolvedLlmModel ?? undefined,
|
|
636
665
|
baseUrl: resolvedLlmBaseUrl ?? undefined,
|
|
637
666
|
});
|
|
638
|
-
const astIndex = refreshAstgrepIndex({
|
|
667
|
+
const astIndex = await refreshAstgrepIndex({
|
|
639
668
|
scope: ".",
|
|
640
669
|
append_evidence: true,
|
|
641
670
|
emit_event: true,
|
|
@@ -662,7 +691,7 @@ export function registerFrameworkTools(server) {
|
|
|
662
691
|
category: "major_update",
|
|
663
692
|
message: "Bootstrapped ACE workspace state",
|
|
664
693
|
artifacts: [
|
|
665
|
-
|
|
694
|
+
storeResult.storePath,
|
|
666
695
|
`${ACE_TASKS_ROOT_REL}/todo.md`,
|
|
667
696
|
normalizePathForValidation(delta.index_path),
|
|
668
697
|
"agent-state/AST_GREP_INDEX.json",
|
|
@@ -717,7 +746,10 @@ export function registerFrameworkTools(server) {
|
|
|
717
746
|
"",
|
|
718
747
|
"## LLM Runtime Profile",
|
|
719
748
|
`- provider: ${llm_provider}`,
|
|
720
|
-
`- model: ${resolvedLlmModel ??
|
|
749
|
+
`- model: ${resolvedLlmModel ??
|
|
750
|
+
(llm_provider === "llama.cpp"
|
|
751
|
+
? "(set via ace connect or ace doctor --scan)"
|
|
752
|
+
: defaultModelForProvider(llm_provider))}`,
|
|
721
753
|
`- base_url: ${resolvedLlmBaseUrl ??
|
|
722
754
|
(llm_provider === "ollama" || llm_provider === "llama.cpp"
|
|
723
755
|
? "discover via ace doctor --scan or set explicitly"
|
|
@@ -990,58 +1022,60 @@ export function registerFrameworkTools(server) {
|
|
|
990
1022
|
// Check: handoff registry parseable
|
|
991
1023
|
const hrRaw = safeRead("agent-state/handoff-registry.json");
|
|
992
1024
|
const hrOk = !hrRaw.startsWith("[FILE NOT FOUND]");
|
|
1025
|
+
let hrParsed;
|
|
993
1026
|
if (hrOk) {
|
|
994
|
-
|
|
995
|
-
|
|
1027
|
+
const parsed = parseJsonForValidation(hrRaw);
|
|
1028
|
+
if (parsed.ok) {
|
|
1029
|
+
hrParsed = parsed.value;
|
|
996
1030
|
checks.push({
|
|
997
1031
|
name: "handoff-registry:parse",
|
|
998
|
-
ok:
|
|
999
|
-
detail:
|
|
1032
|
+
ok: parsed.sanitized.removed_control_bytes === 0,
|
|
1033
|
+
detail: jsonValidationDetail(parsed),
|
|
1000
1034
|
});
|
|
1001
1035
|
}
|
|
1002
|
-
|
|
1036
|
+
else {
|
|
1003
1037
|
checks.push({
|
|
1004
1038
|
name: "handoff-registry:parse",
|
|
1005
1039
|
ok: false,
|
|
1006
|
-
detail:
|
|
1040
|
+
detail: `agent-state/handoff-registry.json: ${parsed.error}`,
|
|
1007
1041
|
});
|
|
1008
1042
|
}
|
|
1009
1043
|
}
|
|
1010
1044
|
// Check: run-ledger parseable
|
|
1011
1045
|
const rlRaw = safeRead("agent-state/run-ledger.json");
|
|
1012
1046
|
if (!rlRaw.startsWith("[FILE NOT FOUND]")) {
|
|
1013
|
-
|
|
1014
|
-
|
|
1047
|
+
const parsed = parseJsonForValidation(rlRaw);
|
|
1048
|
+
if (parsed.ok) {
|
|
1015
1049
|
checks.push({
|
|
1016
1050
|
name: "run-ledger:parse",
|
|
1017
|
-
ok:
|
|
1018
|
-
detail:
|
|
1051
|
+
ok: parsed.sanitized.removed_control_bytes === 0,
|
|
1052
|
+
detail: jsonValidationDetail(parsed),
|
|
1019
1053
|
});
|
|
1020
1054
|
}
|
|
1021
|
-
|
|
1055
|
+
else {
|
|
1022
1056
|
checks.push({
|
|
1023
1057
|
name: "run-ledger:parse",
|
|
1024
1058
|
ok: false,
|
|
1025
|
-
detail:
|
|
1059
|
+
detail: `agent-state/run-ledger.json: ${parsed.error}`,
|
|
1026
1060
|
});
|
|
1027
1061
|
}
|
|
1028
1062
|
}
|
|
1029
1063
|
// Check: todo-state parseable
|
|
1030
1064
|
const tsRaw = safeRead("agent-state/todo-state.json");
|
|
1031
1065
|
if (!tsRaw.startsWith("[FILE NOT FOUND]")) {
|
|
1032
|
-
|
|
1033
|
-
|
|
1066
|
+
const parsed = parseJsonForValidation(tsRaw);
|
|
1067
|
+
if (parsed.ok) {
|
|
1034
1068
|
checks.push({
|
|
1035
1069
|
name: "todo-state:parse",
|
|
1036
|
-
ok:
|
|
1037
|
-
detail:
|
|
1070
|
+
ok: parsed.sanitized.removed_control_bytes === 0,
|
|
1071
|
+
detail: jsonValidationDetail(parsed),
|
|
1038
1072
|
});
|
|
1039
1073
|
}
|
|
1040
|
-
|
|
1074
|
+
else {
|
|
1041
1075
|
checks.push({
|
|
1042
1076
|
name: "todo-state:parse",
|
|
1043
1077
|
ok: false,
|
|
1044
|
-
detail:
|
|
1078
|
+
detail: `agent-state/todo-state.json: ${parsed.error}`,
|
|
1045
1079
|
});
|
|
1046
1080
|
}
|
|
1047
1081
|
}
|
|
@@ -1061,19 +1095,19 @@ export function registerFrameworkTools(server) {
|
|
|
1061
1095
|
});
|
|
1062
1096
|
continue;
|
|
1063
1097
|
}
|
|
1064
|
-
|
|
1065
|
-
|
|
1098
|
+
const parsed = parseJsonForValidation(raw);
|
|
1099
|
+
if (parsed.ok) {
|
|
1066
1100
|
checks.push({
|
|
1067
1101
|
name: check.name,
|
|
1068
|
-
ok:
|
|
1069
|
-
detail:
|
|
1102
|
+
ok: parsed.sanitized.removed_control_bytes === 0,
|
|
1103
|
+
detail: jsonValidationDetail(parsed),
|
|
1070
1104
|
});
|
|
1071
1105
|
}
|
|
1072
|
-
|
|
1106
|
+
else {
|
|
1073
1107
|
checks.push({
|
|
1074
1108
|
name: check.name,
|
|
1075
1109
|
ok: false,
|
|
1076
|
-
detail:
|
|
1110
|
+
detail: `${check.rel}: ${parsed.error}`,
|
|
1077
1111
|
});
|
|
1078
1112
|
}
|
|
1079
1113
|
}
|
|
@@ -1127,25 +1161,28 @@ export function registerFrameworkTools(server) {
|
|
|
1127
1161
|
const artifactManifestRaw = safeRead("agent-state/ARTIFACT_MANIFEST.json");
|
|
1128
1162
|
let artifactManifestEntries = [];
|
|
1129
1163
|
if (!artifactManifestRaw.startsWith("[FILE NOT FOUND]")) {
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
const validation = validateArtifactManifestPayload(parsed);
|
|
1164
|
+
const parsed = parseJsonForValidation(artifactManifestRaw);
|
|
1165
|
+
if (parsed.ok) {
|
|
1166
|
+
const validation = validateArtifactManifestPayload(parsed.value);
|
|
1167
|
+
const controlBytesOk = parsed.sanitized.removed_control_bytes === 0;
|
|
1133
1168
|
checks.push({
|
|
1134
1169
|
name: "artifact-manifest:schema",
|
|
1135
|
-
ok: validation.ok,
|
|
1136
|
-
detail:
|
|
1137
|
-
?
|
|
1138
|
-
: validation.
|
|
1170
|
+
ok: validation.ok && controlBytesOk,
|
|
1171
|
+
detail: !controlBytesOk
|
|
1172
|
+
? jsonValidationDetail(parsed)
|
|
1173
|
+
: validation.ok
|
|
1174
|
+
? `valid (${validation.schema})`
|
|
1175
|
+
: validation.errors.join("; "),
|
|
1139
1176
|
});
|
|
1140
1177
|
if (validation.ok) {
|
|
1141
|
-
artifactManifestEntries = getArtifactManifestEntries(parsed);
|
|
1178
|
+
artifactManifestEntries = getArtifactManifestEntries(parsed.value);
|
|
1142
1179
|
}
|
|
1143
1180
|
}
|
|
1144
|
-
|
|
1181
|
+
else {
|
|
1145
1182
|
checks.push({
|
|
1146
1183
|
name: "artifact-manifest:parse",
|
|
1147
1184
|
ok: false,
|
|
1148
|
-
detail:
|
|
1185
|
+
detail: `agent-state/ARTIFACT_MANIFEST.json: ${parsed.error}`,
|
|
1149
1186
|
});
|
|
1150
1187
|
}
|
|
1151
1188
|
}
|
|
@@ -1183,8 +1220,16 @@ export function registerFrameworkTools(server) {
|
|
|
1183
1220
|
// Check: module registry role coverage vs event emitters
|
|
1184
1221
|
const registryRaw = safeRead("agent-state/MODULES/registry.json");
|
|
1185
1222
|
if (!registryRaw.startsWith("[FILE NOT FOUND]")) {
|
|
1186
|
-
|
|
1187
|
-
|
|
1223
|
+
const parsed = parseJsonForValidation(registryRaw);
|
|
1224
|
+
if (parsed.ok) {
|
|
1225
|
+
if (parsed.sanitized.removed_control_bytes > 0) {
|
|
1226
|
+
checks.push({
|
|
1227
|
+
name: "registry:parse",
|
|
1228
|
+
ok: false,
|
|
1229
|
+
detail: jsonValidationDetail(parsed),
|
|
1230
|
+
});
|
|
1231
|
+
}
|
|
1232
|
+
const registry = parsed.value;
|
|
1188
1233
|
const registeredRoles = new Set(registry.roles ?? []);
|
|
1189
1234
|
const expectedEmitters = [
|
|
1190
1235
|
"capability-safety",
|
|
@@ -1203,11 +1248,11 @@ export function registerFrameworkTools(server) {
|
|
|
1203
1248
|
});
|
|
1204
1249
|
}
|
|
1205
1250
|
}
|
|
1206
|
-
|
|
1251
|
+
else {
|
|
1207
1252
|
checks.push({
|
|
1208
1253
|
name: "registry:parse",
|
|
1209
1254
|
ok: false,
|
|
1210
|
-
detail:
|
|
1255
|
+
detail: `agent-state/MODULES/registry.json: ${parsed.error}`,
|
|
1211
1256
|
});
|
|
1212
1257
|
}
|
|
1213
1258
|
}
|
|
@@ -1228,30 +1273,24 @@ export function registerFrameworkTools(server) {
|
|
|
1228
1273
|
});
|
|
1229
1274
|
}
|
|
1230
1275
|
// Check: handoff consistency (open handoffs have source files)
|
|
1231
|
-
if (hrOk) {
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
if (fileContent.startsWith("[FILE NOT FOUND]"))
|
|
1241
|
-
openWithoutFile++;
|
|
1242
|
-
}
|
|
1276
|
+
if (hrOk && hrParsed) {
|
|
1277
|
+
const handoffs = Object.values(hrParsed.handoffs ?? {});
|
|
1278
|
+
let openWithoutFile = 0;
|
|
1279
|
+
for (const h of handoffs) {
|
|
1280
|
+
if ((h.status === "open" || h.status === "accepted") &&
|
|
1281
|
+
h.source_file) {
|
|
1282
|
+
const fileContent = safeRead(h.source_file);
|
|
1283
|
+
if (fileContent.startsWith("[FILE NOT FOUND]"))
|
|
1284
|
+
openWithoutFile++;
|
|
1243
1285
|
}
|
|
1244
|
-
checks.push({
|
|
1245
|
-
name: "handoff:source-file-integrity",
|
|
1246
|
-
ok: openWithoutFile === 0,
|
|
1247
|
-
detail: openWithoutFile === 0
|
|
1248
|
-
? "all open handoffs have source files"
|
|
1249
|
-
: `${openWithoutFile} open handoffs reference missing source files`,
|
|
1250
|
-
});
|
|
1251
|
-
}
|
|
1252
|
-
catch {
|
|
1253
|
-
/* already caught above */
|
|
1254
1286
|
}
|
|
1287
|
+
checks.push({
|
|
1288
|
+
name: "handoff:source-file-integrity",
|
|
1289
|
+
ok: openWithoutFile === 0,
|
|
1290
|
+
detail: openWithoutFile === 0
|
|
1291
|
+
? "all open handoffs have source files"
|
|
1292
|
+
: `${openWithoutFile} open handoffs reference missing source files`,
|
|
1293
|
+
});
|
|
1255
1294
|
}
|
|
1256
1295
|
// Check: event provenance gaps in recent events.
|
|
1257
1296
|
// Scans for provenance-critical event types that are missing
|
package/dist/tools-handoff.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
-
import { ACE_TASKS_ROOT_REL, normalizePathForValidation, readTaskArtifact,
|
|
6
|
+
import { ACE_TASKS_ROOT_REL, normalizePathForValidation, readTaskArtifact, safeWriteAsync, wsPath, WORKSPACE_ROOT, } from "./helpers.js";
|
|
7
7
|
import { ROLE_ENUM, HANDOFF_VALIDATION_MODE, HANDOFF_LIFECYCLE_STATUS_ENUM, } from "./shared.js";
|
|
8
8
|
import { validateHandoffPayload, validateSwarmHandoffPayload, lintHandoffPayload, } from "./schemas.js";
|
|
9
9
|
import { acknowledgeHandoffSafe, getHandoffRegistryPath, readHandoffRegistry, registerHandoffSafe, } from "./handoff-registry.js";
|
|
@@ -247,7 +247,7 @@ export function registerHandoffTools(server) {
|
|
|
247
247
|
.replace("T", "-")
|
|
248
248
|
.slice(0, 15);
|
|
249
249
|
const filePath = wsPath("tasks", `SWARM_HANDOFF.${from}_to_${to}_${timeStr}_${shortId}.json`);
|
|
250
|
-
|
|
250
|
+
await safeWriteAsync(filePath, JSON.stringify(handoff, null, 2));
|
|
251
251
|
const registry = await registerHandoffSafe({
|
|
252
252
|
handoff_id: handoff.handoff_id,
|
|
253
253
|
from: handoff.router.from,
|
package/dist/tools-lifecycle.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Lifecycle tool registrations: status events, circuit breaker, and kanban.
|
|
3
3
|
*/
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
import { safeRead,
|
|
6
|
-
import { appendStatusEventSafe, getStatusEventsPath, readStatusEvents
|
|
5
|
+
import { safeRead, safeWriteAsync } from "./helpers.js";
|
|
6
|
+
import { appendStatusEventSafe, getStatusEventsPath, readStatusEvents } from "./status-events.js";
|
|
7
7
|
import { refreshKanbanArtifacts } from "./kanban.js";
|
|
8
8
|
export function registerLifecycleTools(server) {
|
|
9
9
|
server.tool("emit_status_event", "Append a schema-valid lifecycle event into agent-state/STATUS_EVENTS.ndjson", {
|
|
@@ -119,7 +119,7 @@ export function registerLifecycleTools(server) {
|
|
|
119
119
|
? "# STATUS\n\n"
|
|
120
120
|
: current.trimEnd();
|
|
121
121
|
const next = `${seed}\n- [${timestamp}] CIRCUIT_BREAKER_OPENED: ${reason}${owner ? ` (owner: ${owner})` : ""}\n`;
|
|
122
|
-
const statusPath =
|
|
122
|
+
const statusPath = await safeWriteAsync("agent-state/STATUS.md", next);
|
|
123
123
|
const event = await appendStatusEventSafe({
|
|
124
124
|
source_module: "capability-ops",
|
|
125
125
|
event_type: "CIRCUIT_BREAKER_OPENED",
|
|
@@ -158,7 +158,7 @@ export function registerLifecycleTools(server) {
|
|
|
158
158
|
? "# STATUS\n\n"
|
|
159
159
|
: current.trimEnd();
|
|
160
160
|
const next = `${seed}\n- [${timestamp}] CIRCUIT_BREAKER_CLOSED: ${reason}\n`;
|
|
161
|
-
const statusPath =
|
|
161
|
+
const statusPath = await safeWriteAsync("agent-state/STATUS.md", next);
|
|
162
162
|
const event = await appendStatusEventSafe({
|
|
163
163
|
source_module: "capability-ops",
|
|
164
164
|
event_type: "CIRCUIT_BREAKER_CLOSED",
|
package/dist/tools-memory.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { existsSync } from "node:fs";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
-
import { resolveWorkspaceRoot, safeRead,
|
|
6
|
+
import { resolveWorkspaceRoot, safeRead, safeWriteAsync, wsPath } from "./helpers.js";
|
|
7
7
|
import { isReadError } from "./shared.js";
|
|
8
8
|
import { appendRunLedgerEntrySafe } from "./run-ledger.js";
|
|
9
9
|
import { appendStatusEventSafe } from "./status-events.js";
|
|
@@ -13,7 +13,7 @@ import { openStore } from "./store/ace-packed-store.js";
|
|
|
13
13
|
import { ProjectionManager } from "./store/materializers/projection-manager.js";
|
|
14
14
|
import { ContextSnapshotRepository } from "./store/repositories/context-snapshot-repository.js";
|
|
15
15
|
import { getWorkspaceStorePath, storeExistsSync, toVirtualStorePath, } from "./store/store-snapshot.js";
|
|
16
|
-
import {
|
|
16
|
+
import { withStoreWriteCoordinator } from "./store/write-coordinator.js";
|
|
17
17
|
const CONTEXT_STORE_REL = "agent-state/context-snapshots";
|
|
18
18
|
export function registerMemoryTools(server) {
|
|
19
19
|
server.tool("context_snapshot", "Capture a named context snapshot for later retrieval (decisions, progress, state)", {
|
|
@@ -41,7 +41,7 @@ export function registerMemoryTools(server) {
|
|
|
41
41
|
let path = wsPath(CONTEXT_STORE_REL, `${name}.json`);
|
|
42
42
|
if (storeExistsSync(root) && existsSync(getWorkspaceStorePath(root))) {
|
|
43
43
|
const storePath = getWorkspaceStorePath(root);
|
|
44
|
-
const saved = await
|
|
44
|
+
const saved = await withStoreWriteCoordinator(storePath, async () => {
|
|
45
45
|
const store = await openStore(storePath);
|
|
46
46
|
try {
|
|
47
47
|
const repo = new ContextSnapshotRepository(store);
|
|
@@ -62,7 +62,7 @@ export function registerMemoryTools(server) {
|
|
|
62
62
|
finally {
|
|
63
63
|
await store.close();
|
|
64
64
|
}
|
|
65
|
-
});
|
|
65
|
+
}, { operation_label: "contextSnapshotSave" });
|
|
66
66
|
path = toVirtualStorePath(storePath, `state/memory/context_snapshots/${saved.file}`);
|
|
67
67
|
}
|
|
68
68
|
else {
|
|
@@ -82,7 +82,7 @@ export function registerMemoryTools(server) {
|
|
|
82
82
|
.slice(0, 48);
|
|
83
83
|
const filename = `${slug}.json`;
|
|
84
84
|
path = wsPath(CONTEXT_STORE_REL, filename);
|
|
85
|
-
|
|
85
|
+
await safeWriteAsync(path, JSON.stringify(snapshot, null, 2));
|
|
86
86
|
const indexPath = wsPath(CONTEXT_STORE_REL, "index.json");
|
|
87
87
|
const indexRaw = safeRead(indexPath);
|
|
88
88
|
let index = { snapshots: [] };
|
|
@@ -97,7 +97,7 @@ export function registerMemoryTools(server) {
|
|
|
97
97
|
index.snapshots = index.snapshots.filter((s) => s.name !== name);
|
|
98
98
|
index.snapshots.push({ name, file: filename, timestamp, summary });
|
|
99
99
|
index.snapshots.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
100
|
-
|
|
100
|
+
await safeWriteAsync(indexPath, JSON.stringify(index, null, 2));
|
|
101
101
|
}
|
|
102
102
|
const ledger = await appendRunLedgerEntrySafe({
|
|
103
103
|
tool: "context_snapshot",
|
package/dist/tools-todo.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* TODO, task management, and run-ledger tool registrations.
|
|
3
3
|
*/
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
import { ACE_TASKS_ROOT_REL, readTaskArtifact, resolveWritableTaskPath,
|
|
5
|
+
import { ACE_TASKS_ROOT_REL, readTaskArtifact, resolveWritableTaskPath, safeWriteAsync, } from "./helpers.js";
|
|
6
6
|
import { TODO_STATUS_ENUM } from "./shared.js";
|
|
7
7
|
import { getTodoStatePath, readTodoState, syncTodoStateSafe, transitionTodoNodeSafe, } from "./todo-state.js";
|
|
8
8
|
import { appendRunLedgerEntrySafe, getRunLedgerPath, readRunLedger, } from "./run-ledger.js";
|
|
@@ -33,7 +33,7 @@ export function registerTodoTools(server) {
|
|
|
33
33
|
}, async ({ new_content, node_id, status, note }) => {
|
|
34
34
|
if (typeof new_content === "string") {
|
|
35
35
|
const synced = await syncTodoStateSafe(new_content);
|
|
36
|
-
const path =
|
|
36
|
+
const path = await safeWriteAsync(resolveWritableTaskPath("todo"), new_content);
|
|
37
37
|
const runLedger = await appendRunLedgerEntrySafe({
|
|
38
38
|
tool: "update_todo",
|
|
39
39
|
category: "major_update",
|
|
@@ -67,7 +67,7 @@ export declare function validateTrackerSnapshotContent(raw: string): ValidationR
|
|
|
67
67
|
export declare function loadTrackerSnapshot(explicitPath?: string): TrackerSnapshotResult;
|
|
68
68
|
export declare function readTrackerSnapshot(): TrackerSnapshot;
|
|
69
69
|
export declare function getTrackerSnapshotPath(): string;
|
|
70
|
-
export declare function writeTrackerSnapshot(snapshot: TrackerSnapshot): string
|
|
70
|
+
export declare function writeTrackerSnapshot(snapshot: TrackerSnapshot): Promise<string>;
|
|
71
71
|
export declare function listTrackerAdapterKinds(): string[];
|
|
72
72
|
export declare function getTrackerAdapter(kind?: string): IssueTrackerAdapter;
|
|
73
73
|
export declare function buildDefaultTrackerSnapshot(kind?: TrackerAdapterKind): TrackerSnapshot;
|
package/dist/tracker-adapters.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
|
-
import { existsSync,
|
|
4
|
-
import {
|
|
3
|
+
import { existsSync, readFileSync, } from "node:fs";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
5
|
import { DEFAULTS_ROOT, resolveWorkspaceArtifactPath as resolveWorkspaceArtifactPathHelper, resolveWorkspaceRoot, } from "./helpers.js";
|
|
6
6
|
import { validateTrackerSnapshotPayload } from "./schemas.js";
|
|
7
|
-
import {
|
|
7
|
+
import { appendStatusEventSafe } from "./status-events.js";
|
|
8
8
|
import { readRuntimeProfile } from "./runtime-profile.js";
|
|
9
|
+
import { safeWriteAsync } from "./helpers.js";
|
|
9
10
|
export const TRACKER_SNAPSHOT_REL_PATH = "agent-state/tracker-snapshot.json";
|
|
10
11
|
export const TRACKER_SNAPSHOT_SCHEMA_REL_PATH = "agent-state/MODULES/schemas/TRACKER_SNAPSHOT.schema.json";
|
|
11
12
|
export const TRACKER_SNAPSHOT_SCHEMA_NAME = "tracker-snapshot@1.0.0";
|
|
@@ -40,14 +41,6 @@ function resolveTrackerSnapshotTarget(explicitPath) {
|
|
|
40
41
|
function resolveWorkspaceArtifactPath(filePath) {
|
|
41
42
|
return resolveWorkspaceArtifactPathHelper(filePath, "write");
|
|
42
43
|
}
|
|
43
|
-
function safeWriteWorkspaceFile(filePath, content) {
|
|
44
|
-
const abs = resolveWorkspaceArtifactPath(filePath);
|
|
45
|
-
mkdirSync(dirname(abs), { recursive: true });
|
|
46
|
-
const tmpPath = `${abs}.${process.pid}.${Date.now()}.tmp`;
|
|
47
|
-
writeFileSync(tmpPath, content, "utf-8");
|
|
48
|
-
renameSync(tmpPath, abs);
|
|
49
|
-
return abs;
|
|
50
|
-
}
|
|
51
44
|
function normalizeTrackerItem(item) {
|
|
52
45
|
return {
|
|
53
46
|
...item,
|
|
@@ -150,12 +143,14 @@ function filterTrackerItems(items, filter) {
|
|
|
150
143
|
}
|
|
151
144
|
function emitTrackerEvent(eventType, summary, payload) {
|
|
152
145
|
try {
|
|
153
|
-
|
|
146
|
+
void appendStatusEventSafe({
|
|
154
147
|
source_module: "capability-framework",
|
|
155
148
|
event_type: eventType,
|
|
156
149
|
status: eventType === "TRACKER_SNAPSHOT_REFRESH_FAILED" ? "fail" : "done",
|
|
157
150
|
summary,
|
|
158
151
|
payload,
|
|
152
|
+
}).catch(() => {
|
|
153
|
+
// Tracker operations must not fail because event logging failed.
|
|
159
154
|
});
|
|
160
155
|
}
|
|
161
156
|
catch {
|
|
@@ -455,7 +450,7 @@ async function githubCreateComment(itemId, body) {
|
|
|
455
450
|
}),
|
|
456
451
|
];
|
|
457
452
|
nextSnapshot.updated_at = now;
|
|
458
|
-
writeTrackerSnapshot(nextSnapshot);
|
|
453
|
+
await writeTrackerSnapshot(nextSnapshot);
|
|
459
454
|
emitTrackerEvent("TRACKER_COMMENT_CREATED", `Tracker comment created for ${issue.item_id}.`, {
|
|
460
455
|
adapter_kind: "external",
|
|
461
456
|
provider: "github",
|
|
@@ -502,7 +497,7 @@ async function githubUpdateItemState(itemId, state) {
|
|
|
502
497
|
try {
|
|
503
498
|
const issue = (await githubGetIssuesById([itemId]))[0];
|
|
504
499
|
const snapshot = upsertTrackerItem(readOrBuildExternalSnapshot(), issue);
|
|
505
|
-
writeTrackerSnapshot(snapshot);
|
|
500
|
+
await writeTrackerSnapshot(snapshot);
|
|
506
501
|
emitTrackerEvent("TRACKER_ITEM_STATE_UPDATED", `Tracker item ${issue.item_id} moved to ${issue.state}.`, {
|
|
507
502
|
adapter_kind: "external",
|
|
508
503
|
provider: "github",
|
|
@@ -569,13 +564,13 @@ export function readTrackerSnapshot() {
|
|
|
569
564
|
export function getTrackerSnapshotPath() {
|
|
570
565
|
return resolveTrackerSnapshotTarget().path;
|
|
571
566
|
}
|
|
572
|
-
export function writeTrackerSnapshot(snapshot) {
|
|
567
|
+
export async function writeTrackerSnapshot(snapshot) {
|
|
573
568
|
const normalized = normalizeTrackerSnapshot(snapshot);
|
|
574
569
|
const validation = validateTrackerSnapshotPayload(normalized);
|
|
575
570
|
if (!validation.ok) {
|
|
576
571
|
throw new Error(`Tracker snapshot failed validation (${validation.schema}): ${validation.errors.join("; ")}`);
|
|
577
572
|
}
|
|
578
|
-
return
|
|
573
|
+
return safeWriteAsync(TRACKER_SNAPSHOT_REL_PATH, JSON.stringify(normalized, null, 2));
|
|
579
574
|
}
|
|
580
575
|
const noneTrackerAdapter = {
|
|
581
576
|
kind: "none",
|
|
@@ -700,7 +695,7 @@ const memoryTrackerAdapter = {
|
|
|
700
695
|
updated_at: now,
|
|
701
696
|
comments: [...snapshot.comments, comment],
|
|
702
697
|
};
|
|
703
|
-
writeTrackerSnapshot(nextSnapshot);
|
|
698
|
+
await writeTrackerSnapshot(nextSnapshot);
|
|
704
699
|
emitTrackerEvent("TRACKER_COMMENT_CREATED", `Tracker comment created for ${comment.item_id}.`, {
|
|
705
700
|
adapter_kind: "memory",
|
|
706
701
|
item_id: comment.item_id,
|
|
@@ -743,7 +738,7 @@ const memoryTrackerAdapter = {
|
|
|
743
738
|
updated_at: now,
|
|
744
739
|
items,
|
|
745
740
|
};
|
|
746
|
-
writeTrackerSnapshot(nextSnapshot);
|
|
741
|
+
await writeTrackerSnapshot(nextSnapshot);
|
|
747
742
|
emitTrackerEvent("TRACKER_ITEM_STATE_UPDATED", `Tracker item ${items[itemIndex].item_id} moved to ${nextState}.`, {
|
|
748
743
|
adapter_kind: "memory",
|
|
749
744
|
item_id: items[itemIndex].item_id,
|
package/dist/tracker-sync.js
CHANGED
|
@@ -2,15 +2,17 @@ import { resolve } from "node:path";
|
|
|
2
2
|
import { resolveWorkspaceRoot } from "./helpers.js";
|
|
3
3
|
import { readRuntimeProfile } from "./runtime-profile.js";
|
|
4
4
|
import { buildDefaultTrackerSnapshot, getTrackerAdapter, writeTrackerSnapshot, readTrackerSnapshot, TRACKER_SNAPSHOT_REL_PATH, } from "./tracker-adapters.js";
|
|
5
|
-
import {
|
|
5
|
+
import { appendStatusEventSafe } from "./status-events.js";
|
|
6
6
|
function emitTrackerSyncEvent(eventType, summary, payload) {
|
|
7
7
|
try {
|
|
8
|
-
|
|
8
|
+
void appendStatusEventSafe({
|
|
9
9
|
source_module: "capability-framework",
|
|
10
10
|
event_type: eventType,
|
|
11
11
|
status: eventType === "TRACKER_SNAPSHOT_REFRESH_FAILED" ? "fail" : "done",
|
|
12
12
|
summary,
|
|
13
13
|
payload,
|
|
14
|
+
}).catch(() => {
|
|
15
|
+
// Snapshot refresh must not fail because observability logging failed.
|
|
14
16
|
});
|
|
15
17
|
}
|
|
16
18
|
catch {
|
|
@@ -52,7 +54,7 @@ export async function refreshTrackerSnapshot(kind) {
|
|
|
52
54
|
items,
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
|
-
const writtenPath = writeTrackerSnapshot(snapshot);
|
|
57
|
+
const writtenPath = await writeTrackerSnapshot(snapshot);
|
|
56
58
|
emitTrackerSyncEvent("TRACKER_SNAPSHOT_REFRESHED", `Tracker snapshot refreshed using ${snapshot.adapter_kind}.`, {
|
|
57
59
|
adapter_kind: snapshot.adapter_kind,
|
|
58
60
|
snapshot_path: writtenPath,
|
package/dist/tui/agent-runner.js
CHANGED
|
@@ -17,7 +17,9 @@ import { readAgentInstructions } from "../helpers.js";
|
|
|
17
17
|
export class AgentRunner extends EventEmitter {
|
|
18
18
|
agents = new Map();
|
|
19
19
|
workspaceRoot;
|
|
20
|
-
|
|
20
|
+
// Full-suite test runs can heavily contend CPU/IO while workers bootstrap.
|
|
21
|
+
// Keep startup resilient to transient contention before declaring failure.
|
|
22
|
+
startupTimeoutMs = 12000;
|
|
21
23
|
constructor(workspaceRoot) {
|
|
22
24
|
super();
|
|
23
25
|
this.workspaceRoot = workspaceRoot;
|