@voybio/ace-swarm 0.2.4 → 0.2.5
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/assets/.agents/skills/eval-harness/SKILL.md +14 -0
- package/assets/.agents/skills/handoff-lint/SKILL.md +14 -0
- package/assets/.agents/skills/incident-commander/SKILL.md +14 -0
- package/assets/.agents/skills/memory-curator/SKILL.md +14 -0
- package/assets/.agents/skills/release-sentry/SKILL.md +14 -0
- package/assets/.agents/skills/risk-quant/SKILL.md +14 -0
- package/assets/.agents/skills/schema-forge/SKILL.md +14 -0
- package/assets/.agents/skills/state-auditor/SKILL.md +14 -0
- package/assets/agent-state/MODULES/gates/gate-correctness.json +1 -1
- package/dist/cli.js +25 -0
- package/dist/helpers.d.ts +2 -0
- package/dist/helpers.js +29 -8
- package/dist/store/cache-workspace.d.ts +22 -0
- package/dist/store/cache-workspace.js +143 -0
- package/dist/store/materializers/context-snapshot-materializer.js +1 -6
- package/dist/tools-agent.js +52 -21
- package/dist/tools-framework.js +83 -23
- package/package.json +1 -1
|
@@ -173,6 +173,20 @@ Confidence: <score>% (<label>)
|
|
|
173
173
|
|
|
174
174
|
---
|
|
175
175
|
|
|
176
|
+
## Validation Surface
|
|
177
|
+
|
|
178
|
+
- Run this skill against at least one known-pass baseline and one known-fail fixture before trusting a promotion decision.
|
|
179
|
+
- Validation command example: execute the configured eval harness runner and confirm deterministic suite counts in `agent-state/EVAL_REPORT.md`.
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Portability Notes
|
|
184
|
+
|
|
185
|
+
- Keep this skill vendor-neutral: it should work across Codex, Claude, Cursor, and Antigravity runtimes.
|
|
186
|
+
- Avoid provider-specific assumptions in suite execution or report parsing; rely on ACE artifacts as the source of truth.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
176
190
|
## Anti-Patterns
|
|
177
191
|
|
|
178
192
|
| Anti-Pattern | Correct Behavior |
|
|
@@ -132,6 +132,20 @@ Also use when:
|
|
|
132
132
|
|
|
133
133
|
---
|
|
134
134
|
|
|
135
|
+
## Validation Surface
|
|
136
|
+
|
|
137
|
+
- Run this check with one valid and one intentionally broken handoff payload to verify deterministic PASS/FAIL behavior.
|
|
138
|
+
- Validation command example: execute the handoff lint path used by the runtime and confirm schema, route, and evidence checks all emit rule-level outcomes.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Portability Notes
|
|
143
|
+
|
|
144
|
+
- Keep lint output schema and rule IDs stable so different clients can consume results uniformly.
|
|
145
|
+
- Do not depend on provider-specific behavior; handoff validation must rely only on ACE artifacts and schemas.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
135
149
|
## Anti-Patterns
|
|
136
150
|
|
|
137
151
|
| Anti-Pattern | Correct Behavior |
|
|
@@ -156,6 +156,20 @@ No incident closure without ALL of:
|
|
|
156
156
|
|
|
157
157
|
---
|
|
158
158
|
|
|
159
|
+
## Validation Surface
|
|
160
|
+
|
|
161
|
+
- Run an incident simulation with synthetic `GATE_FAILED` events and verify severity classification, owner assignment, and timeline reconstruction are deterministic.
|
|
162
|
+
- Validation command example: replay a known event stream and confirm `global-state/INCIDENTS.md` and `agent-state/INCIDENT_TIMELINE.md` contain matching evidence-linked rows.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Portability Notes
|
|
167
|
+
|
|
168
|
+
- Incident lifecycle states and emitted event names must remain stable across clients.
|
|
169
|
+
- Keep the protocol provider-agnostic: all decisions should be derivable from ACE state artifacts and event logs.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
159
173
|
## Anti-Patterns
|
|
160
174
|
|
|
161
175
|
| Anti-Pattern | Correct Behavior |
|
|
@@ -161,6 +161,20 @@ Generated: <ISO8601>
|
|
|
161
161
|
|
|
162
162
|
---
|
|
163
163
|
|
|
164
|
+
## Validation Surface
|
|
165
|
+
|
|
166
|
+
- Run this skill on a fixture with known duplicates and contradictions, then verify the reconciliation report counts match expected values.
|
|
167
|
+
- Validation command example: execute memory curation and confirm no source logs are modified while `MEMORY_INDEX.md` updates with provenance links.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Portability Notes
|
|
172
|
+
|
|
173
|
+
- Preserve schema and section labels so downstream consumers can parse curated memory artifacts consistently.
|
|
174
|
+
- Keep curation logic independent of model/provider specifics; evidence linkage is the portable contract.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
164
178
|
## Anti-Patterns
|
|
165
179
|
|
|
166
180
|
| Anti-Pattern | Correct Behavior |
|
|
@@ -160,6 +160,20 @@ Reason: <one sentence>
|
|
|
160
160
|
|
|
161
161
|
---
|
|
162
162
|
|
|
163
|
+
## Validation Surface
|
|
164
|
+
|
|
165
|
+
- Validate this skill with one known-pass and one known-fail release packet to confirm gate outcomes are deterministic.
|
|
166
|
+
- Validation command example: run release sentry checks and verify `RELEASE_DECISION.md` always includes explicit gate evidence rows.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Portability Notes
|
|
171
|
+
|
|
172
|
+
- Keep decision enums and gate names stable so any client can consume release outputs consistently.
|
|
173
|
+
- Avoid provider-specific assumptions; release readiness must be computed from ACE artifacts only.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
163
177
|
## Anti-Patterns
|
|
164
178
|
|
|
165
179
|
| Anti-Pattern | Correct Behavior |
|
|
@@ -158,6 +158,20 @@ Every risk in `RISKS.md` must contain these fields:
|
|
|
158
158
|
|
|
159
159
|
---
|
|
160
160
|
|
|
161
|
+
## Validation Surface
|
|
162
|
+
|
|
163
|
+
- Run this skill against a fixture risk set with expected probability-impact scores and verify computed tiers match exactly.
|
|
164
|
+
- Validation command example: execute risk quantification and confirm HIGH/CRITICAL entries always include owner, mitigation, and verification condition.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Portability Notes
|
|
169
|
+
|
|
170
|
+
- Keep scoring scales and tier thresholds explicit and stable across clients.
|
|
171
|
+
- Quantification must remain vendor-neutral and based on ACE state artifacts, not model-specific behavior.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
161
175
|
## Anti-Patterns
|
|
162
176
|
|
|
163
177
|
| Anti-Pattern | Correct Behavior |
|
|
@@ -151,6 +151,20 @@ Use when:
|
|
|
151
151
|
|
|
152
152
|
---
|
|
153
153
|
|
|
154
|
+
## Validation Surface
|
|
155
|
+
|
|
156
|
+
- Validate schema updates against both old and new sample payload fixtures before promoting contract changes.
|
|
157
|
+
- Validation command example: run JSON-schema validation for backward and forward compatibility samples and record results in `EVIDENCE_LOG.md`.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## Portability Notes
|
|
162
|
+
|
|
163
|
+
- Preserve stable schema IDs, version fields, and migration metadata so any ACE client can consume updates.
|
|
164
|
+
- Keep evolution rules provider-agnostic; compatibility decisions must be artifact-driven, not model-driven.
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
154
168
|
## Anti-Patterns
|
|
155
169
|
|
|
156
170
|
| Anti-Pattern | Correct Behavior |
|
|
@@ -161,6 +161,20 @@ Overall: <PASS | WARN | CRITICAL>
|
|
|
161
161
|
|
|
162
162
|
---
|
|
163
163
|
|
|
164
|
+
## Validation Surface
|
|
165
|
+
|
|
166
|
+
- Run audits against fixtures with known contradictions to verify deterministic CRITICAL/WARN classification.
|
|
167
|
+
- Validation command example: execute the state audit flow and confirm every checklist row maps to a concrete pass/fail artifact reference.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Portability Notes
|
|
172
|
+
|
|
173
|
+
- Keep report structure and checklist IDs stable so multiple clients can parse outputs consistently.
|
|
174
|
+
- State drift checks must remain independent of model/provider implementation details.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
164
178
|
## Anti-Patterns
|
|
165
179
|
|
|
166
180
|
| Anti-Pattern | Correct Behavior |
|
|
@@ -2,6 +2,6 @@
|
|
|
2
2
|
"id": "gate-correctness",
|
|
3
3
|
"type": "executable",
|
|
4
4
|
"invariant": "All required tests pass",
|
|
5
|
-
"command": "cd ace-mcp-server && npm test --silent",
|
|
5
|
+
"command": "if [ -f ace-mcp-server/package.json ]; then cd ace-mcp-server && npm test --silent; elif [ -f package.json ]; then npm test --silent; else echo 'package.json not found for gate-correctness' && exit 1; fi",
|
|
6
6
|
"evidence_requirement": "Command output snippet with exit code 0"
|
|
7
7
|
}
|
package/dist/cli.js
CHANGED
|
@@ -25,6 +25,7 @@ Usage:
|
|
|
25
25
|
ace init [options] Bootstrap the ACE store into current workspace
|
|
26
26
|
ace turnkey [options] Project minimal workspace bootstrap stubs from the ACE store
|
|
27
27
|
ace doctor [options] Validate ACE runtime + MCP readiness
|
|
28
|
+
ace cache [options] Cache ACE artifacts into ace-state.ace and optionally clean projections
|
|
28
29
|
ace mcp-config [options] Print global/client MCP config snippet(s) from store
|
|
29
30
|
ace preconfig Write .mcp-config/ bundle for all supported clients to workspace root
|
|
30
31
|
ace paths Show resolved package/workspace paths
|
|
@@ -53,6 +54,10 @@ Options for doctor:
|
|
|
53
54
|
--ollama-url <url> Legacy alias for --base-url
|
|
54
55
|
--scan Probe common local Ollama + llama.cpp endpoints when URL is unset
|
|
55
56
|
|
|
57
|
+
Options for cache:
|
|
58
|
+
--dry-run Preview what would be cached and cleaned (no writes/deletes)
|
|
59
|
+
--no-clean Keep workspace ACE artifacts after caching them into ace-state.ace
|
|
60
|
+
|
|
56
61
|
Options for mcp-config:
|
|
57
62
|
--client <name> codex|vscode|claude|cursor|antigravity
|
|
58
63
|
--all Print all client snippets for optional global install
|
|
@@ -680,6 +685,26 @@ async function main() {
|
|
|
680
685
|
console.log(`Store compacted: ${result.before} → ${result.after} bytes (saved ${savedKb}KB)`);
|
|
681
686
|
return;
|
|
682
687
|
}
|
|
688
|
+
if (command === "cache") {
|
|
689
|
+
const { cacheWorkspaceArtifacts } = await import("./store/cache-workspace.js");
|
|
690
|
+
const dryRun = args.includes("--dry-run");
|
|
691
|
+
const clean = !args.includes("--no-clean");
|
|
692
|
+
const result = await cacheWorkspaceArtifacts(WORKSPACE_ROOT, { dryRun, clean });
|
|
693
|
+
console.log("ACE cache complete");
|
|
694
|
+
console.log(`Workspace: ${WORKSPACE_ROOT}`);
|
|
695
|
+
console.log(`Store: ${result.storePath}`);
|
|
696
|
+
console.log(`Scanned files: ${result.scanned_files}`);
|
|
697
|
+
console.log(`Cached files: ${result.cached_files}`);
|
|
698
|
+
console.log(`Kept projected files: ${result.kept_projected_files}`);
|
|
699
|
+
console.log(`Skipped files: ${result.skipped_files}`);
|
|
700
|
+
console.log(`Removed files: ${result.removed_files}`);
|
|
701
|
+
if (result.warnings.length > 0) {
|
|
702
|
+
console.warn(`Warnings (${result.warnings.length}):`);
|
|
703
|
+
for (const warning of result.warnings)
|
|
704
|
+
console.warn(` ! ${warning}`);
|
|
705
|
+
}
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
683
708
|
if (command === "help" || command === "--help" || command === "-h") {
|
|
684
709
|
printHelp();
|
|
685
710
|
return;
|
package/dist/helpers.d.ts
CHANGED
|
@@ -66,6 +66,7 @@ export interface BootstrapResult {
|
|
|
66
66
|
skipped: string[];
|
|
67
67
|
}
|
|
68
68
|
export declare function mapAceWorkspaceRelativePath(path: string): string;
|
|
69
|
+
export declare function isProjectedAceWorkspacePath(filePath: string): boolean;
|
|
69
70
|
export declare function acePath(...segments: string[]): string;
|
|
70
71
|
export declare function wsPath(...segments: string[]): string;
|
|
71
72
|
/** Normalize a path for validation: workspace-relative, forward slashes. */
|
|
@@ -79,6 +80,7 @@ export declare function fileExists(filePath: string): boolean;
|
|
|
79
80
|
export declare function resolveWorkspaceWritePath(filePath: string): string;
|
|
80
81
|
export declare function resolveWorkspaceReadPath(filePath: string): string;
|
|
81
82
|
export declare function resolveWorkspaceArtifactPath(filePath: string, mode?: "read" | "write"): string;
|
|
83
|
+
export declare function resolveStoreFallbackKeysForPath(filePath: string): string[];
|
|
82
84
|
export declare function classifyPathSource(path?: string): ArtifactSource;
|
|
83
85
|
/** Safely read a workspace file, returning either text or a not-found/access message. */
|
|
84
86
|
export declare function safeRead(filePath: string): string;
|
package/dist/helpers.js
CHANGED
|
@@ -8,7 +8,7 @@ import { fileURLToPath } from "node:url";
|
|
|
8
8
|
import { buildHostInstructionText } from "./ace-server-instructions.js";
|
|
9
9
|
import { isInside, normalizeRelPath } from "./shared.js";
|
|
10
10
|
import { getWorkspaceStorePath, listStoreKeysSync, parseVirtualStorePath, readStoreBlobSync, readVirtualStorePathSync, toVirtualStorePath, } from "./store/store-snapshot.js";
|
|
11
|
-
import { isOperationalArtifactPath, operationalArtifactKey, writeStoreBlobSync,
|
|
11
|
+
import { isOperationalArtifactPath, operationalArtifactKey, writeStoreBlobSync, } from "./store/store-artifacts.js";
|
|
12
12
|
import { buildProviderDoctorCommands, buildOpenAiCompatibleBaseUrl, defaultModelForProvider, normalizeLocalBaseUrl, normalizeProvider, } from "./tui/provider-discovery.js";
|
|
13
13
|
export { isInside, isReadError, normalizeRelPath, looksLikeSwarmHandoffPath } from "./shared.js";
|
|
14
14
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -111,6 +111,14 @@ export const ACE_GITHUB_ROOT_REL = ".github";
|
|
|
111
111
|
export const ACE_HOST_AGENTS_REL = "AGENTS.md";
|
|
112
112
|
export const ACE_HOST_CLAUDE_REL = "CLAUDE.md";
|
|
113
113
|
export const ACE_HOST_CURSOR_RULES_REL = ".cursorrules";
|
|
114
|
+
const ACE_PROJECTED_WORKSPACE_FILES = new Set([
|
|
115
|
+
`${ACE_TASKS_ROOT_REL}/todo.md`,
|
|
116
|
+
`${ACE_ROOT_REL}/ace-hook-context.json`,
|
|
117
|
+
`${ACE_ROOT_REL}/agent-state/job-queue.json`,
|
|
118
|
+
`${ACE_ROOT_REL}/agent-state/job-locks.json`,
|
|
119
|
+
`${ACE_ROOT_REL}/agent-state/scheduler-lease.json`,
|
|
120
|
+
`${ACE_ROOT_REL}/agent-state/context-snapshots/index.json`,
|
|
121
|
+
]);
|
|
114
122
|
const ACE_MANAGED_PREFIXES = [
|
|
115
123
|
"agent-state",
|
|
116
124
|
"global-state",
|
|
@@ -386,6 +394,10 @@ export function mapAceWorkspaceRelativePath(path) {
|
|
|
386
394
|
}
|
|
387
395
|
return normalized;
|
|
388
396
|
}
|
|
397
|
+
export function isProjectedAceWorkspacePath(filePath) {
|
|
398
|
+
const canonical = mapAceWorkspaceRelativePath(normalizeRelPath(filePath));
|
|
399
|
+
return ACE_PROJECTED_WORKSPACE_FILES.has(canonical);
|
|
400
|
+
}
|
|
389
401
|
export function acePath(...segments) {
|
|
390
402
|
return resolve(currentWorkspaceRoot(), ACE_ROOT_REL, ...segments);
|
|
391
403
|
}
|
|
@@ -532,6 +544,9 @@ function resolveStoreFallbackKeys(filePath) {
|
|
|
532
544
|
const statePrefix = `${ACE_ROOT_REL}/agent-state/`;
|
|
533
545
|
if (canonical.startsWith(statePrefix)) {
|
|
534
546
|
const rel = canonical.slice(statePrefix.length);
|
|
547
|
+
if (!rel.startsWith("context-snapshots/")) {
|
|
548
|
+
keys.add(`state/artifacts/agent-state/${rel}`);
|
|
549
|
+
}
|
|
535
550
|
const runtimeProjectionKey = {
|
|
536
551
|
"job-queue.json": "state/artifacts/agent-state/job-queue.json",
|
|
537
552
|
"job-locks.json": "state/artifacts/agent-state/job-locks.json",
|
|
@@ -549,6 +564,10 @@ function resolveStoreFallbackKeys(filePath) {
|
|
|
549
564
|
if (rel)
|
|
550
565
|
keys.add(`state/memory/context_snapshots/${rel}`);
|
|
551
566
|
}
|
|
567
|
+
const skillsPrefix = `${ACE_SKILLS_ROOT_REL}/`;
|
|
568
|
+
if (canonical.startsWith(skillsPrefix)) {
|
|
569
|
+
keys.add(`knowledge/skills/${canonical.slice(skillsPrefix.length)}`);
|
|
570
|
+
}
|
|
552
571
|
const tasksPrefix = `${ACE_TASKS_ROOT_REL}/`;
|
|
553
572
|
if (canonical.startsWith(tasksPrefix)) {
|
|
554
573
|
keys.add(`knowledge/tasks/${canonical.slice(tasksPrefix.length)}`);
|
|
@@ -584,6 +603,9 @@ function resolveStoreFallbackKeys(filePath) {
|
|
|
584
603
|
}
|
|
585
604
|
return [...keys];
|
|
586
605
|
}
|
|
606
|
+
export function resolveStoreFallbackKeysForPath(filePath) {
|
|
607
|
+
return resolveStoreFallbackKeys(filePath);
|
|
608
|
+
}
|
|
587
609
|
function readFirstAvailable(paths) {
|
|
588
610
|
const found = firstExistingPath(paths);
|
|
589
611
|
if (!found) {
|
|
@@ -631,15 +653,14 @@ export function safeWrite(filePath, content) {
|
|
|
631
653
|
const normalized = normalizeRelPath(filePath);
|
|
632
654
|
const canonical = mapAceWorkspaceRelativePath(normalized);
|
|
633
655
|
const root = currentWorkspaceRoot();
|
|
634
|
-
|
|
635
|
-
const rel = canonical.slice(`${ACE_ROOT_REL}/`.length);
|
|
636
|
-
if (isOperationalArtifactPath(rel) && existsSync(getWorkspaceStorePath(root))) {
|
|
637
|
-
return writeOperationalArtifactSync(root, rel, content);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
656
|
+
let storeVirtualPath;
|
|
640
657
|
const storeKeys = resolveStoreFallbackKeys(filePath);
|
|
641
658
|
if (storeKeys.length > 0 && existsSync(getWorkspaceStorePath(root))) {
|
|
642
|
-
writeStoreBlobSync(root, storeKeys[0], content);
|
|
659
|
+
storeVirtualPath = writeStoreBlobSync(root, storeKeys[0], content);
|
|
660
|
+
const isAcePath = canonical === ACE_ROOT_REL || canonical.startsWith(`${ACE_ROOT_REL}/`);
|
|
661
|
+
if (isAcePath && !isProjectedAceWorkspacePath(canonical)) {
|
|
662
|
+
return storeVirtualPath;
|
|
663
|
+
}
|
|
643
664
|
}
|
|
644
665
|
const abs = resolveWorkspaceWritePath(filePath);
|
|
645
666
|
mkdirSync(dirname(abs), { recursive: true });
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface CacheWorkspaceOptions {
|
|
2
|
+
dryRun?: boolean;
|
|
3
|
+
clean?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export interface CacheWorkspaceResult {
|
|
6
|
+
storePath: string;
|
|
7
|
+
dry_run: boolean;
|
|
8
|
+
clean: boolean;
|
|
9
|
+
scanned_files: number;
|
|
10
|
+
cached_files: number;
|
|
11
|
+
removed_files: number;
|
|
12
|
+
kept_projected_files: number;
|
|
13
|
+
skipped_files: number;
|
|
14
|
+
warnings: string[];
|
|
15
|
+
cached: Array<{
|
|
16
|
+
path: string;
|
|
17
|
+
key: string;
|
|
18
|
+
bytes: number;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
export declare function cacheWorkspaceArtifacts(workspaceRoot: string, options?: CacheWorkspaceOptions): Promise<CacheWorkspaceResult>;
|
|
22
|
+
//# sourceMappingURL=cache-workspace.d.ts.map
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, rmSync } from "node:fs";
|
|
2
|
+
import { dirname, isAbsolute, join, relative } from "node:path";
|
|
3
|
+
import { ACE_ROOT_REL, isProjectedAceWorkspacePath, mapAceWorkspaceRelativePath, resolveStoreFallbackKeysForPath, } from "../helpers.js";
|
|
4
|
+
import { normalizeRelPath } from "../shared.js";
|
|
5
|
+
import { writeStoreBlobsSync } from "./store-artifacts.js";
|
|
6
|
+
const SCAN_ROOTS_REL = [
|
|
7
|
+
"agent-state",
|
|
8
|
+
".agents/ACE/agent-state",
|
|
9
|
+
".agents/ACE/tasks",
|
|
10
|
+
".agents/ACE/skills",
|
|
11
|
+
];
|
|
12
|
+
function isInside(base, target) {
|
|
13
|
+
const rel = relative(base, target);
|
|
14
|
+
return rel === "" || (!rel.startsWith("..") && !isAbsolute(rel));
|
|
15
|
+
}
|
|
16
|
+
function collectFiles(root) {
|
|
17
|
+
const out = [];
|
|
18
|
+
if (!existsSync(root))
|
|
19
|
+
return out;
|
|
20
|
+
const walk = (dir) => {
|
|
21
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
22
|
+
const abs = join(dir, entry.name);
|
|
23
|
+
if (entry.isDirectory()) {
|
|
24
|
+
walk(abs);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (entry.isFile()) {
|
|
28
|
+
out.push(abs);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
walk(root);
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
function pruneEmptyParents(path, stopAt) {
|
|
36
|
+
let cursor = dirname(path);
|
|
37
|
+
while (isInside(stopAt, cursor) && cursor !== stopAt && existsSync(cursor)) {
|
|
38
|
+
const entries = readdirSync(cursor);
|
|
39
|
+
if (entries.length > 0)
|
|
40
|
+
break;
|
|
41
|
+
rmSync(cursor, { recursive: true, force: true });
|
|
42
|
+
cursor = dirname(cursor);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function isTextBuffer(input) {
|
|
46
|
+
return !input.includes(0);
|
|
47
|
+
}
|
|
48
|
+
function selectScanRoots(workspaceRoot) {
|
|
49
|
+
return SCAN_ROOTS_REL.map((relPath) => join(workspaceRoot, relPath)).filter((abs) => existsSync(abs));
|
|
50
|
+
}
|
|
51
|
+
export async function cacheWorkspaceArtifacts(workspaceRoot, options = {}) {
|
|
52
|
+
const dryRun = options.dryRun ?? false;
|
|
53
|
+
const clean = options.clean ?? true;
|
|
54
|
+
const storePath = join(workspaceRoot, ".agents", "ACE", "ace-state.ace");
|
|
55
|
+
if (!existsSync(storePath)) {
|
|
56
|
+
throw new Error(`No store found at ${storePath}. Run 'ace init' first.`);
|
|
57
|
+
}
|
|
58
|
+
const warnings = [];
|
|
59
|
+
const scanRoots = selectScanRoots(workspaceRoot);
|
|
60
|
+
const candidates = [];
|
|
61
|
+
let scanned = 0;
|
|
62
|
+
let keptProjected = 0;
|
|
63
|
+
let skipped = 0;
|
|
64
|
+
for (const scanRoot of scanRoots) {
|
|
65
|
+
for (const absPath of collectFiles(scanRoot)) {
|
|
66
|
+
scanned += 1;
|
|
67
|
+
const relPath = normalizeRelPath(relative(workspaceRoot, absPath));
|
|
68
|
+
const canonicalPath = mapAceWorkspaceRelativePath(relPath);
|
|
69
|
+
if (!canonicalPath.startsWith(`${ACE_ROOT_REL}/`)) {
|
|
70
|
+
skipped += 1;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (canonicalPath === `${ACE_ROOT_REL}/ace-state.ace`) {
|
|
74
|
+
skipped += 1;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (isProjectedAceWorkspacePath(canonicalPath)) {
|
|
78
|
+
keptProjected += 1;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const raw = readFileSync(absPath);
|
|
82
|
+
if (!isTextBuffer(raw)) {
|
|
83
|
+
skipped += 1;
|
|
84
|
+
warnings.push(`Skipped non-text artifact: ${canonicalPath}`);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const fallbackKeys = resolveStoreFallbackKeysForPath(canonicalPath);
|
|
88
|
+
if (fallbackKeys.length === 0) {
|
|
89
|
+
skipped += 1;
|
|
90
|
+
warnings.push(`No store fallback key for ${canonicalPath}`);
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
candidates.push({
|
|
94
|
+
absPath,
|
|
95
|
+
canonicalPath,
|
|
96
|
+
key: fallbackKeys[0],
|
|
97
|
+
content: raw.toString("utf-8"),
|
|
98
|
+
bytes: raw.byteLength,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const dedupByKey = new Map();
|
|
103
|
+
for (const candidate of candidates) {
|
|
104
|
+
dedupByKey.set(candidate.key, candidate);
|
|
105
|
+
}
|
|
106
|
+
const uniqueForWrite = [...dedupByKey.values()];
|
|
107
|
+
if (!dryRun && uniqueForWrite.length > 0) {
|
|
108
|
+
writeStoreBlobsSync(workspaceRoot, uniqueForWrite.map((candidate) => ({
|
|
109
|
+
key: candidate.key,
|
|
110
|
+
content: candidate.content,
|
|
111
|
+
})));
|
|
112
|
+
}
|
|
113
|
+
let removed = 0;
|
|
114
|
+
if (!dryRun && clean && candidates.length > 0) {
|
|
115
|
+
const removedPaths = new Set();
|
|
116
|
+
for (const candidate of candidates) {
|
|
117
|
+
if (removedPaths.has(candidate.absPath))
|
|
118
|
+
continue;
|
|
119
|
+
rmSync(candidate.absPath, { force: true });
|
|
120
|
+
removedPaths.add(candidate.absPath);
|
|
121
|
+
removed += 1;
|
|
122
|
+
const pruneRoot = scanRoots.find((root) => isInside(root, candidate.absPath)) ?? workspaceRoot;
|
|
123
|
+
pruneEmptyParents(candidate.absPath, pruneRoot);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
storePath,
|
|
128
|
+
dry_run: dryRun,
|
|
129
|
+
clean,
|
|
130
|
+
scanned_files: scanned,
|
|
131
|
+
cached_files: candidates.length,
|
|
132
|
+
removed_files: removed,
|
|
133
|
+
kept_projected_files: keptProjected,
|
|
134
|
+
skipped_files: skipped,
|
|
135
|
+
warnings,
|
|
136
|
+
cached: candidates.map((candidate) => ({
|
|
137
|
+
path: candidate.canonicalPath,
|
|
138
|
+
key: candidate.key,
|
|
139
|
+
bytes: candidate.bytes,
|
|
140
|
+
})),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=cache-workspace.js.map
|
|
@@ -26,11 +26,6 @@ export class ContextSnapshotMaterializer {
|
|
|
26
26
|
if (!existsSync(dir))
|
|
27
27
|
mkdirSync(dir, { recursive: true });
|
|
28
28
|
const snapshots = await this.repo.listSnapshots();
|
|
29
|
-
const retained = new Set(["index.json"]);
|
|
30
|
-
for (const snapshot of snapshots) {
|
|
31
|
-
retained.add(snapshot.file);
|
|
32
|
-
writeText(join(dir, snapshot.file), `${JSON.stringify(snapshot.record, null, 2)}\n`);
|
|
33
|
-
}
|
|
34
29
|
writeText(join(dir, "index.json"), `${JSON.stringify({
|
|
35
30
|
snapshots: snapshots.map(({ name, file, timestamp, summary }) => ({
|
|
36
31
|
name,
|
|
@@ -42,7 +37,7 @@ export class ContextSnapshotMaterializer {
|
|
|
42
37
|
for (const file of readdirSync(dir)) {
|
|
43
38
|
if (!file.endsWith(".json"))
|
|
44
39
|
continue;
|
|
45
|
-
if (
|
|
40
|
+
if (file === "index.json")
|
|
46
41
|
continue;
|
|
47
42
|
rmSync(join(dir, file), { force: true });
|
|
48
43
|
}
|
package/dist/tools-agent.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Agent, skill, kernel, and task-pack tool registrations.
|
|
3
3
|
*/
|
|
4
4
|
import { z } from "zod";
|
|
5
|
-
import { ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, classifyPathSource, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, isSwarmRole, listAvailableSkills, readAgentInstructions, readAgentManifest, readKernelArtifact, readSkillInstructions, readTaskArtifact, resolveWritableTaskPath, safeWrite, } from "./helpers.js";
|
|
5
|
+
import { ALL_AGENTS, COMPOSABLE_AGENTS, SWARM_AGENTS, SWARM_SUBAGENT_MAP, classifyPathSource, getAgentInstructionPath, getAgentManifestPath, getKernelArtifactPath, isSwarmRole, listAvailableSkills, readAgentInstructions, readAgentManifest, readKernelArtifact, readSkillInstructions, readTaskArtifact, resolveWorkspaceRoot, resolveWritableTaskPath, safeWrite, } from "./helpers.js";
|
|
6
6
|
import { loadRuntimeProfile, readRuntimePromptTemplate, readRuntimeProfileState, validateRuntimeProfileContent, } from "./runtime-profile.js";
|
|
7
7
|
import { getUnattendedSession, listUnattendedSessions, startUnattendedSession, stopUnattendedSession, validateRuntimeExecutorSessionRegistryContent, waitForUnattendedSession, } from "./runtime-executor.js";
|
|
8
8
|
import { executeRuntimeTool, listRuntimeToolSpecs, loadRuntimeToolRegistry, validateRuntimeToolRegistryContent, } from "./runtime-tool-specs.js";
|
|
@@ -80,6 +80,17 @@ function appendUniqueNote(target, note) {
|
|
|
80
80
|
target.push(note);
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
+
function createToolOnlyBridgeResult(step, reason) {
|
|
84
|
+
return {
|
|
85
|
+
bridge_id: `tool-only-${step.step_id}-${Date.now()}`,
|
|
86
|
+
role: step.role,
|
|
87
|
+
status: "completed",
|
|
88
|
+
summary: `Tool-only orchestrator completion for ${step.step_id} (${step.role}): ${step.task}. ${reason}`,
|
|
89
|
+
turns: 0,
|
|
90
|
+
tool_calls: [],
|
|
91
|
+
child_results: [],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
83
94
|
function buildDefaultOrchestratorAmendment(input) {
|
|
84
95
|
if (input.result.status !== "completed" || input.step.role !== "coders") {
|
|
85
96
|
return undefined;
|
|
@@ -687,13 +698,23 @@ export function registerAgentTools(server) {
|
|
|
687
698
|
.optional()
|
|
688
699
|
.describe("Optional workspace root override; defaults to the active workspace"),
|
|
689
700
|
}, async ({ task, steps, execution_mode, max_turns_per_step, provider, model, base_url, ollama_url, workspace_root }, extra) => {
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
701
|
+
let runtime;
|
|
702
|
+
const runtimeWarnings = [];
|
|
703
|
+
try {
|
|
704
|
+
runtime = resolveLocalModelRuntime({
|
|
705
|
+
workspaceRoot: workspace_root,
|
|
706
|
+
provider,
|
|
707
|
+
model,
|
|
708
|
+
baseUrl: base_url,
|
|
709
|
+
ollamaUrl: ollama_url,
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
catch (error) {
|
|
713
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
714
|
+
appendUniqueNote(runtimeWarnings, `Model bridge runtime unavailable; continuing in tool-only mode. ${message}`);
|
|
715
|
+
}
|
|
716
|
+
const effectiveWorkspaceRoot = runtime?.workspaceRoot ??
|
|
717
|
+
(workspace_root ? resolveRuntimeWorkspaceRoot(workspace_root) : resolveWorkspaceRoot());
|
|
697
718
|
const sessionId = typeof extra?.sessionId === "string" ? extra.sessionId : undefined;
|
|
698
719
|
const planSource = Array.isArray(steps) && steps.length > 0 ? "explicit_steps" : "orchestrator_default_step";
|
|
699
720
|
const planSteps = Array.isArray(steps) && steps.length > 0
|
|
@@ -704,20 +725,27 @@ export function registerAgentTools(server) {
|
|
|
704
725
|
steps: planSteps,
|
|
705
726
|
execution_mode: execution_mode ?? "sequential",
|
|
706
727
|
});
|
|
707
|
-
const bridge =
|
|
728
|
+
const bridge = runtime
|
|
729
|
+
? new ModelBridge(createDefaultModelBridgeClients(runtime))
|
|
730
|
+
: undefined;
|
|
708
731
|
const fallbackHandoffPrefix = `LOCAL-${plan.plan_id}-`;
|
|
709
732
|
const vericifyWarnings = [];
|
|
710
733
|
const supervised = await superviseTaskPlan(plan, {
|
|
711
734
|
async spawnStep(step) {
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
735
|
+
if (bridge && runtime) {
|
|
736
|
+
return bridge.spawn({
|
|
737
|
+
task: step.task,
|
|
738
|
+
role: step.role,
|
|
739
|
+
workspace: runtime.workspaceRoot,
|
|
740
|
+
maxTurns: max_turns_per_step ?? 6,
|
|
741
|
+
provider: runtime.provider,
|
|
742
|
+
model: runtime.model,
|
|
743
|
+
toolScope: step.tool_scope,
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
const reason = runtimeWarnings[0] ??
|
|
747
|
+
"No local model provider/runtime was resolved for model bridge execution.";
|
|
748
|
+
return createToolOnlyBridgeResult(step, reason);
|
|
721
749
|
},
|
|
722
750
|
async createHandoff({ step, plan: activePlan }) {
|
|
723
751
|
const created = await executeAceInternalTool("create_handoff", {
|
|
@@ -756,13 +784,13 @@ export function registerAgentTools(server) {
|
|
|
756
784
|
},
|
|
757
785
|
async getVericifyContext() {
|
|
758
786
|
return tryVericifyPacket(() => getVericifyContextPacket({
|
|
759
|
-
workspaceRoot:
|
|
787
|
+
workspaceRoot: effectiveWorkspaceRoot,
|
|
760
788
|
}), (message) => appendUniqueNote(vericifyWarnings, `Vericify context unavailable for ${plan.plan_id}: ${message}`));
|
|
761
789
|
},
|
|
762
790
|
async getVericifyDelta(since) {
|
|
763
791
|
return tryVericifyPacket(() => getVericifyDelta({
|
|
764
792
|
since,
|
|
765
|
-
workspaceRoot:
|
|
793
|
+
workspaceRoot: effectiveWorkspaceRoot,
|
|
766
794
|
}), (message) => appendUniqueNote(vericifyWarnings, `Vericify delta unavailable for ${plan.plan_id}: ${message}`));
|
|
767
795
|
},
|
|
768
796
|
async openCircuitBreaker(reason) {
|
|
@@ -818,7 +846,10 @@ export function registerAgentTools(server) {
|
|
|
818
846
|
{
|
|
819
847
|
type: "text",
|
|
820
848
|
text: JSON.stringify({
|
|
821
|
-
runtime,
|
|
849
|
+
runtime: runtime ?? null,
|
|
850
|
+
execution_backend: runtime ? "model_bridge" : "tool_only",
|
|
851
|
+
runtime_warnings: runtimeWarnings,
|
|
852
|
+
workspace_root: effectiveWorkspaceRoot,
|
|
822
853
|
plan_source: planSource,
|
|
823
854
|
planning_note: planSource === "orchestrator_default_step"
|
|
824
855
|
? "Auto-planning currently starts with ACE-Orchestrator. Pass explicit steps for multi-step orchestration."
|
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, safeRead, safeWrite, withFileLock, wsPath, } from "./helpers.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, safeWrite, 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";
|
|
@@ -20,6 +20,7 @@ import { auditPublicSurface } from "./public-surface.js";
|
|
|
20
20
|
import { auditStoreAuthority, writeStoreAuthorityAuditReport, } from "./store/store-authority-audit.js";
|
|
21
21
|
import { PROVENANCE_CRITICAL_EVENT_TYPES, validateArtifactManifestPayload, validateProvenanceLogContent, validateTealConfigContent, } from "./schemas.js";
|
|
22
22
|
import { readAceTaskContractAssessment } from "./ace-autonomy.js";
|
|
23
|
+
import { listStoreKeysSync, readStoreBlobSync } from "./store/store-snapshot.js";
|
|
23
24
|
function getArtifactManifestEntries(payload) {
|
|
24
25
|
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
25
26
|
return [];
|
|
@@ -38,15 +39,37 @@ function getArtifactManifestEntries(payload) {
|
|
|
38
39
|
}
|
|
39
40
|
return [];
|
|
40
41
|
}
|
|
42
|
+
function parseGateManifest(raw, sourceRef) {
|
|
43
|
+
try {
|
|
44
|
+
const gate = JSON.parse(raw);
|
|
45
|
+
const id = typeof gate.id === "string" ? gate.id.trim() : "";
|
|
46
|
+
if (!id)
|
|
47
|
+
return undefined;
|
|
48
|
+
const type = gate.type === "executable" || gate.type === "artifact_scan" || gate.type === "manual_review"
|
|
49
|
+
? gate.type
|
|
50
|
+
: "manual_review";
|
|
51
|
+
return {
|
|
52
|
+
id,
|
|
53
|
+
type,
|
|
54
|
+
invariant: typeof gate.invariant === "string" ? gate.invariant : "",
|
|
55
|
+
command: typeof gate.command === "string" ? gate.command : "",
|
|
56
|
+
evidence_requirement: typeof gate.evidence_requirement === "string" ? gate.evidence_requirement : "",
|
|
57
|
+
source_ref: sourceRef,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
41
64
|
function readGateManifests(gatesDir) {
|
|
42
65
|
const files = readdirSync(gatesDir).filter((f) => f.endsWith(".json"));
|
|
43
66
|
const allGates = [];
|
|
44
67
|
for (const file of files) {
|
|
45
68
|
try {
|
|
46
69
|
const raw = readFileSync(resolve(gatesDir, file), "utf-8");
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
49
|
-
allGates.push(
|
|
70
|
+
const parsed = parseGateManifest(raw, `agent-state/MODULES/gates/${file}`);
|
|
71
|
+
if (parsed)
|
|
72
|
+
allGates.push(parsed);
|
|
50
73
|
}
|
|
51
74
|
catch {
|
|
52
75
|
/* skip corrupt manifests */
|
|
@@ -54,6 +77,44 @@ function readGateManifests(gatesDir) {
|
|
|
54
77
|
}
|
|
55
78
|
return allGates;
|
|
56
79
|
}
|
|
80
|
+
function readStoreGateManifests(workspaceRoot) {
|
|
81
|
+
const gateKeys = listStoreKeysSync(workspaceRoot, "knowledge/gates/").filter((key) => key.endsWith(".json"));
|
|
82
|
+
const allGates = [];
|
|
83
|
+
for (const key of gateKeys) {
|
|
84
|
+
const raw = readStoreBlobSync(workspaceRoot, key);
|
|
85
|
+
if (typeof raw !== "string")
|
|
86
|
+
continue;
|
|
87
|
+
const parsed = parseGateManifest(raw, key);
|
|
88
|
+
if (parsed)
|
|
89
|
+
allGates.push(parsed);
|
|
90
|
+
}
|
|
91
|
+
return allGates;
|
|
92
|
+
}
|
|
93
|
+
function resolveGateManifests(gatesDir) {
|
|
94
|
+
if (existsSync(gatesDir)) {
|
|
95
|
+
const workspaceGates = readGateManifests(gatesDir);
|
|
96
|
+
if (workspaceGates.length > 0) {
|
|
97
|
+
return { gates: workspaceGates, source: "workspace" };
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const storeGates = readStoreGateManifests(resolveWorkspaceRoot());
|
|
101
|
+
if (storeGates.length > 0) {
|
|
102
|
+
return { gates: storeGates, source: "store" };
|
|
103
|
+
}
|
|
104
|
+
return { gates: [], source: "none" };
|
|
105
|
+
}
|
|
106
|
+
function hasArtifactEvidence(reference) {
|
|
107
|
+
const normalized = reference.trim();
|
|
108
|
+
if (!normalized)
|
|
109
|
+
return false;
|
|
110
|
+
const candidates = [wsPath("agent-state", normalized), wsPath(normalized)];
|
|
111
|
+
if (candidates.some((candidate) => existsSync(candidate)))
|
|
112
|
+
return true;
|
|
113
|
+
return candidates.some((candidate) => {
|
|
114
|
+
const content = safeRead(candidate);
|
|
115
|
+
return !content.startsWith("[FILE NOT FOUND]") && !content.startsWith("[ACCESS DENIED]");
|
|
116
|
+
});
|
|
117
|
+
}
|
|
57
118
|
function evaluateGateTargets(targets) {
|
|
58
119
|
const results = [];
|
|
59
120
|
for (const gate of targets) {
|
|
@@ -97,7 +158,7 @@ function evaluateGateTargets(targets) {
|
|
|
97
158
|
}
|
|
98
159
|
else {
|
|
99
160
|
for (const artifact of relevantArtifacts) {
|
|
100
|
-
if (!
|
|
161
|
+
if (!hasArtifactEvidence(artifact)) {
|
|
101
162
|
missing.push(artifact);
|
|
102
163
|
}
|
|
103
164
|
}
|
|
@@ -109,11 +170,9 @@ function evaluateGateTargets(targets) {
|
|
|
109
170
|
.map((s) => s.trim())
|
|
110
171
|
.filter(Boolean);
|
|
111
172
|
for (const ref of evidenceFiles) {
|
|
112
|
-
|
|
113
|
-
const found = candidates.some((candidate) => existsSync(candidate));
|
|
114
|
-
if (!found) {
|
|
173
|
+
if (!hasArtifactEvidence(ref)) {
|
|
115
174
|
const asFile = ref.replace(/\s+/g, "_").replace(/[^a-zA-Z0-9_./-]/g, "");
|
|
116
|
-
const fileFound =
|
|
175
|
+
const fileFound = hasArtifactEvidence(asFile);
|
|
117
176
|
if (!fileFound)
|
|
118
177
|
missing.push(ref);
|
|
119
178
|
}
|
|
@@ -1349,31 +1408,27 @@ export function registerFrameworkTools(server) {
|
|
|
1349
1408
|
.describe("Optional short focus string persisted with skeptic adversarial review evidence."),
|
|
1350
1409
|
}, async ({ gate_ids, review_mode, review_focus }) => {
|
|
1351
1410
|
const gatesDir = wsPath("agent-state", "MODULES", "gates");
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
{
|
|
1356
|
-
type: "text",
|
|
1357
|
-
text: "❌ Gates directory not found: agent-state/MODULES/gates/",
|
|
1358
|
-
},
|
|
1359
|
-
],
|
|
1360
|
-
};
|
|
1361
|
-
}
|
|
1362
|
-
const allGates = readGateManifests(gatesDir);
|
|
1411
|
+
const resolved = resolveGateManifests(gatesDir);
|
|
1412
|
+
const allGates = resolved.gates;
|
|
1413
|
+
const gateEvidenceRef = resolved.source === "store" ? "knowledge/gates/*" : "agent-state/MODULES/gates/";
|
|
1363
1414
|
// Filter to requested gates (or run all)
|
|
1364
1415
|
const targets = gate_ids
|
|
1365
1416
|
? allGates.filter((g) => gate_ids.includes(g.id))
|
|
1366
1417
|
: allGates;
|
|
1367
1418
|
if (targets.length === 0) {
|
|
1419
|
+
const noGateMessage = allGates.length === 0
|
|
1420
|
+
? "❌ No gate manifests found in agent-state/MODULES/gates/ or ace-state.ace knowledge/gates/*."
|
|
1421
|
+
: `❌ No matching gates found. Available: ${allGates.map((g) => g.id).join(", ")}`;
|
|
1368
1422
|
return {
|
|
1369
1423
|
content: [
|
|
1370
1424
|
{
|
|
1371
1425
|
type: "text",
|
|
1372
|
-
text:
|
|
1426
|
+
text: noGateMessage,
|
|
1373
1427
|
},
|
|
1374
1428
|
],
|
|
1375
1429
|
};
|
|
1376
1430
|
}
|
|
1431
|
+
const gateArtifactRefs = targets.map((gate) => gate.source_ref ?? gateEvidenceRef);
|
|
1377
1432
|
const results = evaluateGateTargets(targets);
|
|
1378
1433
|
const passed = results.filter((r) => r.ok).length;
|
|
1379
1434
|
const failed = results.filter((r) => !r.ok).length;
|
|
@@ -1401,7 +1456,8 @@ export function registerFrameworkTools(server) {
|
|
|
1401
1456
|
})),
|
|
1402
1457
|
passed,
|
|
1403
1458
|
failed,
|
|
1404
|
-
evidence_ref: evidence?.evidenceRef ??
|
|
1459
|
+
evidence_ref: evidence?.evidenceRef ?? gateEvidenceRef,
|
|
1460
|
+
gate_manifest_source: resolved.source,
|
|
1405
1461
|
...(review
|
|
1406
1462
|
? {
|
|
1407
1463
|
review: {
|
|
@@ -1428,13 +1484,14 @@ export function registerFrameworkTools(server) {
|
|
|
1428
1484
|
? `Gate execution with skeptic review: ${review.summary.confirmed_count} confirmed findings`
|
|
1429
1485
|
: `Gate execution: ${passed}/${results.length} passed`,
|
|
1430
1486
|
artifacts: [
|
|
1431
|
-
...
|
|
1487
|
+
...gateArtifactRefs,
|
|
1432
1488
|
...(evidence ? ["agent-state/EVIDENCE_LOG.md"] : []),
|
|
1433
1489
|
],
|
|
1434
1490
|
metadata: {
|
|
1435
1491
|
passed,
|
|
1436
1492
|
failed,
|
|
1437
1493
|
gate_ids: results.map((r) => r.id),
|
|
1494
|
+
gate_manifest_source: resolved.source,
|
|
1438
1495
|
...(review
|
|
1439
1496
|
? {
|
|
1440
1497
|
review_mode: review.mode,
|
|
@@ -1460,6 +1517,9 @@ export function registerFrameworkTools(server) {
|
|
|
1460
1517
|
: allOk
|
|
1461
1518
|
? `✅ All gates passed: ${passed}/${results.length}`
|
|
1462
1519
|
: `❌ Gate failures: ${failed}/${results.length} failed`,
|
|
1520
|
+
`Gate manifest source: ${resolved.source === "store"
|
|
1521
|
+
? "ace-state.ace (knowledge/gates/*)"
|
|
1522
|
+
: "agent-state/MODULES/gates/"}`,
|
|
1463
1523
|
`Run ledger: ${ledger.path} (${ledger.entry.id})`,
|
|
1464
1524
|
...(evidence ? [`Evidence: ${evidence.path} (${evidence.evidenceRef})`] : []),
|
|
1465
1525
|
"",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voybio/ace-swarm",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.5",
|
|
4
4
|
"description": "ACE Framework MCP server and CLI — single-file ACEPACK state, local-model serving, agent orchestration, and host compliance enforcement.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|