@voybio/ace-swarm 0.1.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/CHANGELOG.md +109 -0
- package/LICENSE +186 -0
- package/README.md +229 -0
- package/assets/.agents/ACE/ACE-Init/AGENTS.md +210 -0
- package/assets/.agents/ACE/ACE-Init/instructions.md +118 -0
- package/assets/.agents/ACE/ACE_coders/AGENTS.md +154 -0
- package/assets/.agents/ACE/ACE_coders/INSTRUCTIONS.md +216 -0
- package/assets/.agents/ACE/AGENT_REGISTRY.md +70 -0
- package/assets/.agents/ACE/AGENT_REGISTRY_7.md +9 -0
- package/assets/.agents/ACE/DIRECTIVE_KERNEL.md +234 -0
- package/assets/.agents/ACE/UI/AGENTS.md +115 -0
- package/assets/.agents/ACE/UI/instructions.md +178 -0
- package/assets/.agents/ACE/VOS/ACE_VOS_MISSING_INFO_MATRIX.md +42 -0
- package/assets/.agents/ACE/VOS/AGENTS.md +72 -0
- package/assets/.agents/ACE/VOS/instructions.md +211 -0
- package/assets/.agents/ACE/agent-astgrep/AGENTS.md +123 -0
- package/assets/.agents/ACE/agent-astgrep/instructions.md +91 -0
- package/assets/.agents/ACE/agent-builder/AGENTS.md +172 -0
- package/assets/.agents/ACE/agent-builder/instructions.md +137 -0
- package/assets/.agents/ACE/agent-docs/AGENTS.md +159 -0
- package/assets/.agents/ACE/agent-docs/instructions.md +133 -0
- package/assets/.agents/ACE/agent-eval/AGENTS.md +46 -0
- package/assets/.agents/ACE/agent-eval/instructions.md +56 -0
- package/assets/.agents/ACE/agent-memory/AGENTS.md +49 -0
- package/assets/.agents/ACE/agent-memory/instructions.md +50 -0
- package/assets/.agents/ACE/agent-observability/AGENTS.md +46 -0
- package/assets/.agents/ACE/agent-observability/instructions.md +50 -0
- package/assets/.agents/ACE/agent-ops/AGENTS.md +201 -0
- package/assets/.agents/ACE/agent-ops/instructions.md +136 -0
- package/assets/.agents/ACE/agent-qa/AGENTS.md +189 -0
- package/assets/.agents/ACE/agent-qa/instructions.md +121 -0
- package/assets/.agents/ACE/agent-release/AGENTS.md +48 -0
- package/assets/.agents/ACE/agent-release/instructions.md +49 -0
- package/assets/.agents/ACE/agent-research/AGENTS.md +160 -0
- package/assets/.agents/ACE/agent-research/instructions.md +118 -0
- package/assets/.agents/ACE/agent-security/AGENTS.md +48 -0
- package/assets/.agents/ACE/agent-security/instructions.md +50 -0
- package/assets/.agents/ACE/agent-skeptic/AGENTS.md +178 -0
- package/assets/.agents/ACE/agent-skeptic/instructions.md +196 -0
- package/assets/.agents/ACE/agent-spec/AGENTS.md +169 -0
- package/assets/.agents/ACE/agent-spec/instructions.md +116 -0
- package/assets/.agents/ACE/orchestrator/AGENTS.md +365 -0
- package/assets/.agents/ACE/orchestrator/instructions.md +231 -0
- package/assets/.agents/skills/ace-orchestrator/SKILL.md +63 -0
- package/assets/.agents/skills/ace-orchestrator/references/engineering-bootstrap-playbook.md +360 -0
- package/assets/.agents/skills/astgrep-index/SKILL.md +58 -0
- package/assets/.agents/skills/codemunch/SKILL.md +65 -0
- package/assets/.agents/skills/codemunch/references/ast-driven-protocol.md +543 -0
- package/assets/.agents/skills/codesnipe/SKILL.md +64 -0
- package/assets/.agents/skills/codesnipe/references/dual-codebase-playbook.md +671 -0
- package/assets/.agents/skills/eval-harness/SKILL.md +203 -0
- package/assets/.agents/skills/handoff-lint/SKILL.md +164 -0
- package/assets/.agents/skills/incident-commander/SKILL.md +174 -0
- package/assets/.agents/skills/landing-review-watcher/SKILL.md +68 -0
- package/assets/.agents/skills/memory-curator/SKILL.md +179 -0
- package/assets/.agents/skills/problem-triage/SKILL.md +57 -0
- package/assets/.agents/skills/problem-triage/agents/openai.yaml +3 -0
- package/assets/.agents/skills/release-sentry/SKILL.md +189 -0
- package/assets/.agents/skills/risk-quant/SKILL.md +190 -0
- package/assets/.agents/skills/schema-forge/SKILL.md +174 -0
- package/assets/.agents/skills/skill-auditor/SKILL.md +52 -0
- package/assets/.agents/skills/state-auditor/SKILL.md +182 -0
- package/assets/.github/hooks/ace-copilot.json +68 -0
- package/assets/agent-state/ACE_WORKFLOW.md +131 -0
- package/assets/agent-state/ARTIFACT_MANIFEST.json +5 -0
- package/assets/agent-state/AST_GREP_COMMANDS.md +121 -0
- package/assets/agent-state/AST_GREP_INDEX.json +13 -0
- package/assets/agent-state/AST_GREP_INDEX.md +15 -0
- package/assets/agent-state/DECISIONS.md +7 -0
- package/assets/agent-state/EVIDENCE_LOG.md +7 -0
- package/assets/agent-state/HANDOFF.json +24 -0
- package/assets/agent-state/INTERFACE_REGISTRY.md +75 -0
- package/assets/agent-state/MODULES/gates/gate-autonomy.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-completeness.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-correctness.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-evaluation.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-operability.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-security.json +7 -0
- package/assets/agent-state/MODULES/gates/gate-typescript-public-surface.json +7 -0
- package/assets/agent-state/MODULES/registry.json +41 -0
- package/assets/agent-state/MODULES/roles/capability-astgrep.json +49 -0
- package/assets/agent-state/MODULES/roles/capability-build.json +39 -0
- package/assets/agent-state/MODULES/roles/capability-docs.json +38 -0
- package/assets/agent-state/MODULES/roles/capability-eval.json +20 -0
- package/assets/agent-state/MODULES/roles/capability-memory.json +20 -0
- package/assets/agent-state/MODULES/roles/capability-observability.json +20 -0
- package/assets/agent-state/MODULES/roles/capability-ops.json +45 -0
- package/assets/agent-state/MODULES/roles/capability-qa.json +40 -0
- package/assets/agent-state/MODULES/roles/capability-release.json +21 -0
- package/assets/agent-state/MODULES/roles/capability-research.json +44 -0
- package/assets/agent-state/MODULES/roles/capability-security.json +21 -0
- package/assets/agent-state/MODULES/roles/capability-skeptic.json +48 -0
- package/assets/agent-state/MODULES/roles/capability-spec.json +42 -0
- package/assets/agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json +289 -0
- package/assets/agent-state/MODULES/schemas/ARTIFACT_MANIFEST.schema.json +185 -0
- package/assets/agent-state/MODULES/schemas/HANDOFF.agent-state.schema.json +124 -0
- package/assets/agent-state/MODULES/schemas/HANDOFF.schema.json +55 -0
- package/assets/agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json +290 -0
- package/assets/agent-state/MODULES/schemas/RUNTIME_TOOL_SPEC_REGISTRY.schema.json +144 -0
- package/assets/agent-state/MODULES/schemas/STATUS_EVENT.schema.json +84 -0
- package/assets/agent-state/MODULES/schemas/SWARM_HANDOFF.schema.json +138 -0
- package/assets/agent-state/MODULES/schemas/TRACKER_SNAPSHOT.schema.json +134 -0
- package/assets/agent-state/MODULES/schemas/VERICIFY_BRIDGE_SNAPSHOT.schema.json +157 -0
- package/assets/agent-state/MODULES/schemas/VERICIFY_PROCESS_POST_LOG.schema.json +93 -0
- package/assets/agent-state/MODULES/schemas/WORKSPACE_SESSION_REGISTRY.schema.json +133 -0
- package/assets/agent-state/PROVENANCE_LOG.md +28 -0
- package/assets/agent-state/QUALITY_GATES.md +15 -0
- package/assets/agent-state/RISKS.md +8 -0
- package/assets/agent-state/SCOPE.md +20 -0
- package/assets/agent-state/SKILL_CATALOG.md +48 -0
- package/assets/agent-state/STATUS.md +8 -0
- package/assets/agent-state/STATUS_EVENTS.ndjson +1 -0
- package/assets/agent-state/TASK.md +18 -0
- package/assets/agent-state/TEAL_CONFIG.md +117 -0
- package/assets/agent-state/handoff-registry.json +5 -0
- package/assets/agent-state/index-fingerprints.json +7 -0
- package/assets/agent-state/index.json +32 -0
- package/assets/agent-state/run-ledger.json +5 -0
- package/assets/agent-state/runtime-executor-sessions.json +5 -0
- package/assets/agent-state/runtime-tool-specs.json +5 -0
- package/assets/agent-state/runtime-workspaces.json +5 -0
- package/assets/agent-state/todo-state.json +7 -0
- package/assets/agent-state/tracker-snapshot.json +7 -0
- package/assets/agent-state/vericify/ace-bridge.json +60 -0
- package/assets/agent-state/vericify/process-posts.json +5 -0
- package/assets/instructions/ACE.instructions.md +187 -0
- package/assets/instructions/ACE_Coder.instructions.md +146 -0
- package/assets/instructions/ACE_UI.instructions.md +178 -0
- package/assets/instructions/ACE_VOS.instructions.md +211 -0
- package/assets/scripts/ace-hook-dispatch.mjs +538 -0
- package/assets/scripts/bootstrap-workspace.sh +27 -0
- package/assets/scripts/copilot-hook-dispatch.mjs +3 -0
- package/assets/scripts/eval-harness.sh +68 -0
- package/assets/scripts/render-mcp-configs.sh +396 -0
- package/assets/tasks/README.md +48 -0
- package/assets/tasks/SWARM_HANDOFF.example.json +53 -0
- package/assets/tasks/SWARM_HANDOFF.example_ui_to_coders.json +55 -0
- package/assets/tasks/SWARM_HANDOFF.example_vos_to_ui.json +55 -0
- package/assets/tasks/SWARM_HANDOFF.template.json +52 -0
- package/assets/tasks/cli_work_split.md +22 -0
- package/assets/tasks/lessons.md +17 -0
- package/assets/tasks/role_tasks.md +206 -0
- package/assets/tasks/todo.md +23 -0
- package/dist/ace-autonomy.d.ts +137 -0
- package/dist/ace-autonomy.js +472 -0
- package/dist/ace-context.d.ts +29 -0
- package/dist/ace-context.js +240 -0
- package/dist/ace-internal-tools.d.ts +8 -0
- package/dist/ace-internal-tools.js +76 -0
- package/dist/ace-server-instructions.d.ts +12 -0
- package/dist/ace-server-instructions.js +324 -0
- package/dist/agent-runtime/role-adapters.d.ts +29 -0
- package/dist/agent-runtime/role-adapters.js +573 -0
- package/dist/astgrep-index.d.ts +24 -0
- package/dist/astgrep-index.js +476 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +591 -0
- package/dist/git-ops.d.ts +53 -0
- package/dist/git-ops.js +238 -0
- package/dist/handoff-registry.d.ts +71 -0
- package/dist/handoff-registry.js +422 -0
- package/dist/helpers.d.ts +126 -0
- package/dist/helpers.js +1687 -0
- package/dist/index-store.d.ts +51 -0
- package/dist/index-store.js +328 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +7 -0
- package/dist/internal-tool-runtime.d.ts +21 -0
- package/dist/internal-tool-runtime.js +136 -0
- package/dist/job-scheduler.d.ts +175 -0
- package/dist/job-scheduler.js +1217 -0
- package/dist/kanban.d.ts +27 -0
- package/dist/kanban.js +339 -0
- package/dist/local-model-runtime.d.ts +40 -0
- package/dist/local-model-runtime.js +174 -0
- package/dist/model-bridge.d.ts +54 -0
- package/dist/model-bridge.js +587 -0
- package/dist/orchestrator-supervisor.d.ts +100 -0
- package/dist/orchestrator-supervisor.js +399 -0
- package/dist/problem-triage.d.ts +23 -0
- package/dist/problem-triage.js +448 -0
- package/dist/prompts.d.ts +7 -0
- package/dist/prompts.js +628 -0
- package/dist/public-surface.d.ts +30 -0
- package/dist/public-surface.js +316 -0
- package/dist/resources.d.ts +7 -0
- package/dist/resources.js +545 -0
- package/dist/run-ledger.d.ts +36 -0
- package/dist/run-ledger.js +257 -0
- package/dist/runtime-command.d.ts +18 -0
- package/dist/runtime-command.js +76 -0
- package/dist/runtime-executor.d.ts +104 -0
- package/dist/runtime-executor.js +985 -0
- package/dist/runtime-profile.d.ts +116 -0
- package/dist/runtime-profile.js +532 -0
- package/dist/runtime-tool-specs.d.ts +68 -0
- package/dist/runtime-tool-specs.js +527 -0
- package/dist/safe-edit.d.ts +52 -0
- package/dist/safe-edit.js +255 -0
- package/dist/schemas.d.ts +44 -0
- package/dist/schemas.js +830 -0
- package/dist/semantic-cache.d.ts +147 -0
- package/dist/semantic-cache.js +552 -0
- package/dist/semantic-hash.d.ts +83 -0
- package/dist/semantic-hash.js +346 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.js +46 -0
- package/dist/shared.d.ts +136 -0
- package/dist/shared.js +269 -0
- package/dist/skill-auditor.d.ts +26 -0
- package/dist/skill-auditor.js +184 -0
- package/dist/skill-catalog.d.ts +60 -0
- package/dist/skill-catalog.js +305 -0
- package/dist/status-events.d.ts +40 -0
- package/dist/status-events.js +269 -0
- package/dist/store/ace-packed-store.d.ts +69 -0
- package/dist/store/ace-packed-store.js +434 -0
- package/dist/store/bootstrap-store.d.ts +46 -0
- package/dist/store/bootstrap-store.js +242 -0
- package/dist/store/catalog-builder.d.ts +21 -0
- package/dist/store/catalog-builder.js +68 -0
- package/dist/store/importer.d.ts +19 -0
- package/dist/store/importer.js +157 -0
- package/dist/store/knowledge-bake.d.ts +59 -0
- package/dist/store/knowledge-bake.js +339 -0
- package/dist/store/materializers/hook-context-materializer.d.ts +25 -0
- package/dist/store/materializers/hook-context-materializer.js +100 -0
- package/dist/store/materializers/host-file-materializer.d.ts +37 -0
- package/dist/store/materializers/host-file-materializer.js +271 -0
- package/dist/store/materializers/todo-syncer.d.ts +30 -0
- package/dist/store/materializers/todo-syncer.js +140 -0
- package/dist/store/materializers/vericify-projector.d.ts +38 -0
- package/dist/store/materializers/vericify-projector.js +239 -0
- package/dist/store/repositories/discovery-repository.d.ts +24 -0
- package/dist/store/repositories/discovery-repository.js +58 -0
- package/dist/store/repositories/handoff-repository.d.ts +31 -0
- package/dist/store/repositories/handoff-repository.js +67 -0
- package/dist/store/repositories/ledger-repository.d.ts +26 -0
- package/dist/store/repositories/ledger-repository.js +49 -0
- package/dist/store/repositories/runtime-kv-repository.d.ts +16 -0
- package/dist/store/repositories/runtime-kv-repository.js +36 -0
- package/dist/store/repositories/scheduler-repository.d.ts +50 -0
- package/dist/store/repositories/scheduler-repository.js +123 -0
- package/dist/store/repositories/session-repository.d.ts +33 -0
- package/dist/store/repositories/session-repository.js +82 -0
- package/dist/store/repositories/todo-repository.d.ts +31 -0
- package/dist/store/repositories/todo-repository.js +77 -0
- package/dist/store/repositories/tracker-repository.d.ts +25 -0
- package/dist/store/repositories/tracker-repository.js +43 -0
- package/dist/store/repositories/vericify-repository.d.ts +32 -0
- package/dist/store/repositories/vericify-repository.js +58 -0
- package/dist/store/skills-install.d.ts +28 -0
- package/dist/store/skills-install.js +86 -0
- package/dist/store/state-reader.d.ts +49 -0
- package/dist/store/state-reader.js +111 -0
- package/dist/store/store-artifacts.d.ts +12 -0
- package/dist/store/store-artifacts.js +138 -0
- package/dist/store/store-snapshot.d.ts +19 -0
- package/dist/store/store-snapshot.js +140 -0
- package/dist/store/topology-bake.d.ts +15 -0
- package/dist/store/topology-bake.js +215 -0
- package/dist/store/types.d.ts +155 -0
- package/dist/store/types.js +35 -0
- package/dist/store/workspace-snapshot.d.ts +26 -0
- package/dist/store/workspace-snapshot.js +107 -0
- package/dist/store/write-queue.d.ts +7 -0
- package/dist/store/write-queue.js +26 -0
- package/dist/todo-state.d.ts +41 -0
- package/dist/todo-state.js +399 -0
- package/dist/tools-agent.d.ts +7 -0
- package/dist/tools-agent.js +1542 -0
- package/dist/tools-discovery.d.ts +6 -0
- package/dist/tools-discovery.js +178 -0
- package/dist/tools-drift.d.ts +13 -0
- package/dist/tools-drift.js +357 -0
- package/dist/tools-files.d.ts +6 -0
- package/dist/tools-files.js +679 -0
- package/dist/tools-framework.d.ts +7 -0
- package/dist/tools-framework.js +1414 -0
- package/dist/tools-git.d.ts +6 -0
- package/dist/tools-git.js +183 -0
- package/dist/tools-handoff.d.ts +32 -0
- package/dist/tools-handoff.js +489 -0
- package/dist/tools-lifecycle.d.ts +6 -0
- package/dist/tools-lifecycle.js +205 -0
- package/dist/tools-memory.d.ts +6 -0
- package/dist/tools-memory.js +260 -0
- package/dist/tools-scheduler.d.ts +6 -0
- package/dist/tools-scheduler.js +228 -0
- package/dist/tools-skills.d.ts +3 -0
- package/dist/tools-skills.js +104 -0
- package/dist/tools-todo.d.ts +6 -0
- package/dist/tools-todo.js +154 -0
- package/dist/tools.d.ts +9 -0
- package/dist/tools.js +33 -0
- package/dist/tracker-adapters.d.ts +74 -0
- package/dist/tracker-adapters.js +776 -0
- package/dist/tracker-sync.d.ts +10 -0
- package/dist/tracker-sync.js +84 -0
- package/dist/tui/agent-runner.d.ts +137 -0
- package/dist/tui/agent-runner.js +466 -0
- package/dist/tui/agent-worker.d.ts +10 -0
- package/dist/tui/agent-worker.js +347 -0
- package/dist/tui/chat.d.ts +84 -0
- package/dist/tui/chat.js +368 -0
- package/dist/tui/commands.d.ts +57 -0
- package/dist/tui/commands.js +432 -0
- package/dist/tui/dashboard.d.ts +24 -0
- package/dist/tui/dashboard.js +110 -0
- package/dist/tui/index.d.ts +114 -0
- package/dist/tui/index.js +1059 -0
- package/dist/tui/input.d.ts +49 -0
- package/dist/tui/input.js +336 -0
- package/dist/tui/layout.d.ts +116 -0
- package/dist/tui/layout.js +367 -0
- package/dist/tui/ollama.d.ts +116 -0
- package/dist/tui/ollama.js +192 -0
- package/dist/tui/openai-compatible.d.ts +63 -0
- package/dist/tui/openai-compatible.js +370 -0
- package/dist/tui/provider-discovery.d.ts +59 -0
- package/dist/tui/provider-discovery.js +530 -0
- package/dist/tui/renderer.d.ts +166 -0
- package/dist/tui/renderer.js +304 -0
- package/dist/tui/tabs.d.ts +70 -0
- package/dist/tui/tabs.js +208 -0
- package/dist/tui/telemetry.d.ts +56 -0
- package/dist/tui/telemetry.js +106 -0
- package/dist/vericify-bridge.d.ts +146 -0
- package/dist/vericify-bridge.js +571 -0
- package/dist/vericify-context.d.ts +10 -0
- package/dist/vericify-context.js +72 -0
- package/dist/workspace-manager.d.ts +107 -0
- package/dist/workspace-manager.js +636 -0
- package/package.json +83 -0
|
@@ -0,0 +1,1414 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework tool registrations: bootstrap, status, config, routing,
|
|
3
|
+
* plus new run_tests and validate_framework tools.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { bootstrapStoreWorkspace } from "./store/bootstrap-store.js";
|
|
7
|
+
import { ACE_ROOT_REL, ACE_TASKS_ROOT_REL, ALL_MCP_CLIENTS, 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";
|
|
8
|
+
import { getRoleTitle, MCP_CLIENT_ENUM, scoreDomains, } from "./shared.js";
|
|
9
|
+
import { DEFAULT_LLAMA_CPP_MODEL, DEFAULT_OLLAMA_MODEL, } from "./tui/provider-discovery.js";
|
|
10
|
+
import { refreshAstgrepIndex } from "./astgrep-index.js";
|
|
11
|
+
import { scanWorkspaceDelta } from "./index-store.js";
|
|
12
|
+
import { getOrRefreshKanbanSnapshot } from "./kanban.js";
|
|
13
|
+
import { appendRunLedgerEntrySafe } from "./run-ledger.js";
|
|
14
|
+
import { appendStatusEventSafe } from "./status-events.js";
|
|
15
|
+
import { runTestSuite } from "./safe-edit.js";
|
|
16
|
+
import { isGitRepo, gitStatus } from "./git-ops.js";
|
|
17
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
18
|
+
import { resolve } from "node:path";
|
|
19
|
+
import { auditPublicSurface } from "./public-surface.js";
|
|
20
|
+
import { PROVENANCE_CRITICAL_EVENT_TYPES, validateArtifactManifestPayload, validateProvenanceLogContent, validateTealConfigContent, } from "./schemas.js";
|
|
21
|
+
import { readAceTaskContractAssessment } from "./ace-autonomy.js";
|
|
22
|
+
function getArtifactManifestEntries(payload) {
|
|
23
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
24
|
+
return [];
|
|
25
|
+
const manifest = payload;
|
|
26
|
+
if (Array.isArray(manifest.artifacts)) {
|
|
27
|
+
return manifest.artifacts.filter((entry) => !!entry &&
|
|
28
|
+
typeof entry === "object" &&
|
|
29
|
+
typeof entry.artifact_id === "string" &&
|
|
30
|
+
typeof entry.checksum === "string" &&
|
|
31
|
+
typeof entry.evidence_ref === "string");
|
|
32
|
+
}
|
|
33
|
+
if (typeof manifest.artifact_id === "string" &&
|
|
34
|
+
typeof manifest.checksum === "string" &&
|
|
35
|
+
typeof manifest.evidence_ref === "string") {
|
|
36
|
+
return [manifest];
|
|
37
|
+
}
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
function readGateManifests(gatesDir) {
|
|
41
|
+
const files = readdirSync(gatesDir).filter((f) => f.endsWith(".json"));
|
|
42
|
+
const allGates = [];
|
|
43
|
+
for (const file of files) {
|
|
44
|
+
try {
|
|
45
|
+
const raw = readFileSync(resolve(gatesDir, file), "utf-8");
|
|
46
|
+
const gate = JSON.parse(raw);
|
|
47
|
+
if (gate.id)
|
|
48
|
+
allGates.push(gate);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
/* skip corrupt manifests */
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return allGates;
|
|
55
|
+
}
|
|
56
|
+
function evaluateGateTargets(targets) {
|
|
57
|
+
const results = [];
|
|
58
|
+
for (const gate of targets) {
|
|
59
|
+
if (gate.type === "executable" && gate.command.trim().length > 0) {
|
|
60
|
+
const testResult = runTestSuite(gate.command);
|
|
61
|
+
results.push({
|
|
62
|
+
id: gate.id,
|
|
63
|
+
type: gate.type,
|
|
64
|
+
ok: testResult.ok,
|
|
65
|
+
detail: testResult.ok
|
|
66
|
+
? `PASS (exit ${testResult.exit_code}, ${testResult.duration_ms}ms)`
|
|
67
|
+
: `FAIL (exit ${testResult.exit_code}): ${testResult.output.slice(0, 500)}`,
|
|
68
|
+
invariant: gate.invariant,
|
|
69
|
+
evidence_requirement: gate.evidence_requirement,
|
|
70
|
+
});
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
if (gate.type === "artifact_scan") {
|
|
74
|
+
const evidenceReq = gate.evidence_requirement.trim();
|
|
75
|
+
const looksLikeProse = evidenceReq.includes(" ") &&
|
|
76
|
+
!/\.(md|json|ts|js|yaml|yml|ndjson|txt)\b/.test(evidenceReq) &&
|
|
77
|
+
!evidenceReq.includes("/");
|
|
78
|
+
const missing = [];
|
|
79
|
+
if (looksLikeProse) {
|
|
80
|
+
const knownArtifacts = [
|
|
81
|
+
"STATUS.md",
|
|
82
|
+
"EVIDENCE_LOG.md",
|
|
83
|
+
"HANDOFF.json",
|
|
84
|
+
"DECISIONS.md",
|
|
85
|
+
"RISKS.md",
|
|
86
|
+
"SCOPE.md",
|
|
87
|
+
"TASK.md",
|
|
88
|
+
"QUALITY_GATES.md",
|
|
89
|
+
"SPEC_CONTRACT.json",
|
|
90
|
+
"TEAL_CONFIG.md",
|
|
91
|
+
];
|
|
92
|
+
const invariantLower = gate.invariant.toLowerCase();
|
|
93
|
+
const relevantArtifacts = knownArtifacts.filter((artifact) => invariantLower.includes(artifact.replace(/\.\w+$/, "").toLowerCase().replace(/_/g, " ")) || invariantLower.includes(artifact.toLowerCase()));
|
|
94
|
+
if (relevantArtifacts.length === 0) {
|
|
95
|
+
missing.push(`(prose evidence cannot be auto-verified: "${evidenceReq.slice(0, 80)}")`);
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
for (const artifact of relevantArtifacts) {
|
|
99
|
+
if (!existsSync(wsPath("agent-state", artifact))) {
|
|
100
|
+
missing.push(artifact);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
const evidenceFiles = evidenceReq
|
|
107
|
+
.split(/[+,&]/)
|
|
108
|
+
.map((s) => s.trim())
|
|
109
|
+
.filter(Boolean);
|
|
110
|
+
for (const ref of evidenceFiles) {
|
|
111
|
+
const candidates = [wsPath("agent-state", ref), wsPath(ref)];
|
|
112
|
+
const found = candidates.some((candidate) => existsSync(candidate));
|
|
113
|
+
if (!found) {
|
|
114
|
+
const asFile = ref.replace(/\s+/g, "_").replace(/[^a-zA-Z0-9_./-]/g, "");
|
|
115
|
+
const fileFound = existsSync(wsPath("agent-state", asFile));
|
|
116
|
+
if (!fileFound)
|
|
117
|
+
missing.push(ref);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
results.push({
|
|
122
|
+
id: gate.id,
|
|
123
|
+
type: gate.type,
|
|
124
|
+
ok: missing.length === 0,
|
|
125
|
+
detail: missing.length === 0
|
|
126
|
+
? "PASS (all evidence artifacts present)"
|
|
127
|
+
: `FAIL (missing evidence: ${missing.join(", ")})`,
|
|
128
|
+
invariant: gate.invariant,
|
|
129
|
+
evidence_requirement: gate.evidence_requirement,
|
|
130
|
+
});
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (gate.type === "manual_review") {
|
|
134
|
+
results.push({
|
|
135
|
+
id: gate.id,
|
|
136
|
+
type: gate.type,
|
|
137
|
+
ok: false,
|
|
138
|
+
detail: "PENDING — requires manual review (not auto-enforceable, blocking until reviewed)",
|
|
139
|
+
invariant: gate.invariant,
|
|
140
|
+
evidence_requirement: gate.evidence_requirement,
|
|
141
|
+
});
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
results.push({
|
|
145
|
+
id: gate.id,
|
|
146
|
+
type: gate.type ?? "unknown",
|
|
147
|
+
ok: false,
|
|
148
|
+
detail: "Unknown gate type or no command specified",
|
|
149
|
+
invariant: gate.invariant,
|
|
150
|
+
evidence_requirement: gate.evidence_requirement,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
return results;
|
|
154
|
+
}
|
|
155
|
+
function buildAdversarialClaim(result) {
|
|
156
|
+
switch (result.type) {
|
|
157
|
+
case "executable":
|
|
158
|
+
return `Executable gate ${result.id} failed its invariant check.`;
|
|
159
|
+
case "artifact_scan":
|
|
160
|
+
return `Artifact evidence for gate ${result.id} is not sufficient to trust the invariant.`;
|
|
161
|
+
case "manual_review":
|
|
162
|
+
return `Gate ${result.id} still depends on human review before the invariant can be trusted.`;
|
|
163
|
+
default:
|
|
164
|
+
return `Gate ${result.id} could not be verified cleanly.`;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function inferRouteHint(result) {
|
|
168
|
+
if (result.type === "executable")
|
|
169
|
+
return "agent-builder";
|
|
170
|
+
if (result.type === "artifact_scan" &&
|
|
171
|
+
result.detail.toLowerCase().includes("prose evidence cannot be auto-verified")) {
|
|
172
|
+
return "agent-spec";
|
|
173
|
+
}
|
|
174
|
+
if (result.type === "artifact_scan")
|
|
175
|
+
return "agent-ops";
|
|
176
|
+
if (result.type === "manual_review")
|
|
177
|
+
return "agent-skeptic";
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
function buildAdversarialReview(results, reviewFocus) {
|
|
181
|
+
const candidates = results
|
|
182
|
+
.filter((result) => !result.ok)
|
|
183
|
+
.map((result) => ({
|
|
184
|
+
gate_id: result.id,
|
|
185
|
+
gate_type: result.type,
|
|
186
|
+
claim: buildAdversarialClaim(result),
|
|
187
|
+
detail: result.detail,
|
|
188
|
+
invariant: result.invariant,
|
|
189
|
+
evidence_requirement: result.evidence_requirement,
|
|
190
|
+
route_hint: inferRouteHint(result),
|
|
191
|
+
}));
|
|
192
|
+
const disproved = [];
|
|
193
|
+
const confirmed = [];
|
|
194
|
+
for (const finding of candidates) {
|
|
195
|
+
if (finding.gate_type === "manual_review") {
|
|
196
|
+
disproved.push({
|
|
197
|
+
...finding,
|
|
198
|
+
reason: "Pending manual review alone is not enough to confirm an actionable defect.",
|
|
199
|
+
});
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (finding.gate_type === "artifact_scan" &&
|
|
203
|
+
finding.detail.toLowerCase().includes("prose evidence cannot be auto-verified")) {
|
|
204
|
+
disproved.push({
|
|
205
|
+
...finding,
|
|
206
|
+
reason: "The evidence contract is too vague to confirm a defect without stronger artifacts.",
|
|
207
|
+
});
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
confirmed.push(finding);
|
|
211
|
+
}
|
|
212
|
+
return {
|
|
213
|
+
mode: "skeptic_adversarial",
|
|
214
|
+
focus: reviewFocus?.trim() || undefined,
|
|
215
|
+
candidates,
|
|
216
|
+
disproved,
|
|
217
|
+
confirmed,
|
|
218
|
+
summary: {
|
|
219
|
+
candidate_count: candidates.length,
|
|
220
|
+
disproved_count: disproved.length,
|
|
221
|
+
confirmed_count: confirmed.length,
|
|
222
|
+
actionable_gate_ids: confirmed.map((finding) => finding.gate_id),
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
async function appendEvidenceLogEntrySafe(review) {
|
|
227
|
+
const timestamp = new Date().toISOString();
|
|
228
|
+
const anchor = `#ts:${timestamp}`;
|
|
229
|
+
const evidenceRef = `agent-state/EVIDENCE_LOG.md${anchor}`;
|
|
230
|
+
return withFileLock("agent-state/EVIDENCE_LOG.md", () => {
|
|
231
|
+
const existing = safeRead("agent-state/EVIDENCE_LOG.md");
|
|
232
|
+
const seed = existing.startsWith("[FILE NOT FOUND]") || existing.startsWith("[ACCESS DENIED]")
|
|
233
|
+
? "# EVIDENCE LOG\n\nAppend-only validation evidence.\n\n## Entries\n"
|
|
234
|
+
: existing.trimEnd();
|
|
235
|
+
const lines = [
|
|
236
|
+
"",
|
|
237
|
+
`[${timestamp}] Skeptic adversarial review via execute_gates`,
|
|
238
|
+
`- evidence_ref: ${anchor}`,
|
|
239
|
+
...(review.focus ? [`- focus: ${review.focus}`] : []),
|
|
240
|
+
`- candidates: ${review.summary.candidate_count}`,
|
|
241
|
+
`- disproved: ${review.summary.disproved_count}`,
|
|
242
|
+
`- confirmed: ${review.summary.confirmed_count}`,
|
|
243
|
+
`- actionable_gate_ids: ${review.summary.actionable_gate_ids.length > 0
|
|
244
|
+
? review.summary.actionable_gate_ids.join(", ")
|
|
245
|
+
: "none"}`,
|
|
246
|
+
"- bug_hunter_candidates:",
|
|
247
|
+
...(review.candidates.length > 0
|
|
248
|
+
? review.candidates.map((finding) => ` - ${finding.gate_id} [${finding.gate_type}]: ${finding.claim} (${finding.detail})`)
|
|
249
|
+
: [" - none"]),
|
|
250
|
+
"- disprover_results:",
|
|
251
|
+
...(review.disproved.length > 0
|
|
252
|
+
? review.disproved.map((finding) => ` - ${finding.gate_id}: ${finding.reason ?? "candidate rejected"}`)
|
|
253
|
+
: [" - none"]),
|
|
254
|
+
"- adjudicator_confirmed:",
|
|
255
|
+
...(review.confirmed.length > 0
|
|
256
|
+
? review.confirmed.map((finding) => {
|
|
257
|
+
const route = finding.route_hint ? ` route_hint=${finding.route_hint}` : "";
|
|
258
|
+
return ` - ${finding.gate_id}: ${finding.detail}.${route}`;
|
|
259
|
+
})
|
|
260
|
+
: [" - none"]),
|
|
261
|
+
];
|
|
262
|
+
const path = safeWrite("agent-state/EVIDENCE_LOG.md", `${seed}${lines.join("\n")}\n`);
|
|
263
|
+
return { path, evidenceRef };
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
export function registerFrameworkTools(server) {
|
|
267
|
+
// ── Routing (improved with weighted scoring) ──────────────────────
|
|
268
|
+
server.tool("route_task", "Determine which ACE agent(s) or skill should handle a task", {
|
|
269
|
+
description: z.string().describe("Describe the task or question"),
|
|
270
|
+
domain: z
|
|
271
|
+
.enum([
|
|
272
|
+
"venture",
|
|
273
|
+
"ux",
|
|
274
|
+
"engineering",
|
|
275
|
+
"mixed",
|
|
276
|
+
"research",
|
|
277
|
+
"unknown",
|
|
278
|
+
])
|
|
279
|
+
.optional()
|
|
280
|
+
.describe("Known domain, or unknown for auto-detect"),
|
|
281
|
+
}, async ({ description, domain }) => {
|
|
282
|
+
const text = description.toLowerCase();
|
|
283
|
+
let detected = domain ?? "unknown";
|
|
284
|
+
// Weighted scoring replaces naive if/else chain
|
|
285
|
+
if (detected === "unknown") {
|
|
286
|
+
const { domain: scored } = scoreDomains(text);
|
|
287
|
+
detected = scored;
|
|
288
|
+
}
|
|
289
|
+
const routingMap = {
|
|
290
|
+
venture: {
|
|
291
|
+
swarm_agents: ["vos"],
|
|
292
|
+
subagents: [
|
|
293
|
+
"astgrep",
|
|
294
|
+
"research",
|
|
295
|
+
"spec",
|
|
296
|
+
"memory",
|
|
297
|
+
"skeptic",
|
|
298
|
+
"ops",
|
|
299
|
+
],
|
|
300
|
+
pipeline: "VOS -> UI -> Coders (as needed) with composable Research/Spec/Skeptic/Ops support",
|
|
301
|
+
prompt: "ace-vos",
|
|
302
|
+
},
|
|
303
|
+
ux: {
|
|
304
|
+
swarm_agents: ["ui"],
|
|
305
|
+
subagents: [
|
|
306
|
+
"astgrep",
|
|
307
|
+
"research",
|
|
308
|
+
"spec",
|
|
309
|
+
"builder",
|
|
310
|
+
"qa",
|
|
311
|
+
"docs",
|
|
312
|
+
"skeptic",
|
|
313
|
+
"ops",
|
|
314
|
+
],
|
|
315
|
+
pipeline: "UI -> Coders with composable Spec/Builder/QA and Skeptic/Ops sidecars",
|
|
316
|
+
prompt: "ace-ui",
|
|
317
|
+
},
|
|
318
|
+
engineering: {
|
|
319
|
+
swarm_agents: ["coders"],
|
|
320
|
+
subagents: [
|
|
321
|
+
"astgrep",
|
|
322
|
+
"spec",
|
|
323
|
+
"builder",
|
|
324
|
+
"qa",
|
|
325
|
+
"docs",
|
|
326
|
+
"security",
|
|
327
|
+
"observability",
|
|
328
|
+
"eval",
|
|
329
|
+
"release",
|
|
330
|
+
"skeptic",
|
|
331
|
+
"ops",
|
|
332
|
+
],
|
|
333
|
+
pipeline: "Coders with composable Spec -> Builder -> QA -> Docs and Skeptic/Ops guards",
|
|
334
|
+
prompt: "ace-coders",
|
|
335
|
+
},
|
|
336
|
+
mixed: {
|
|
337
|
+
swarm_agents: ["orchestrator"],
|
|
338
|
+
subagents: [...COMPOSABLE_AGENTS],
|
|
339
|
+
pipeline: "Orchestrator -> VOS/UI/Coders with full composable agent support",
|
|
340
|
+
prompt: "ace-orchestrator",
|
|
341
|
+
},
|
|
342
|
+
research: {
|
|
343
|
+
swarm_agents: ["orchestrator"],
|
|
344
|
+
subagents: [
|
|
345
|
+
"astgrep",
|
|
346
|
+
"research",
|
|
347
|
+
"spec",
|
|
348
|
+
"memory",
|
|
349
|
+
"skeptic",
|
|
350
|
+
"ops",
|
|
351
|
+
],
|
|
352
|
+
pipeline: "Orchestrator -> Research/Spec with Skeptic/Ops governance",
|
|
353
|
+
skills: ["astgrep-index", "codemunch", "codesnipe"],
|
|
354
|
+
prompt: "ace-orchestrator",
|
|
355
|
+
},
|
|
356
|
+
};
|
|
357
|
+
const route = routingMap[detected] ?? routingMap.mixed;
|
|
358
|
+
const recommendedSkills = new Set(route.skills ?? []);
|
|
359
|
+
const recommendedSubagents = new Set(route.subagents);
|
|
360
|
+
const taskContract = readAceTaskContractAssessment();
|
|
361
|
+
const stateConflictRequested = text.includes("contradict") ||
|
|
362
|
+
text.includes("conflict") ||
|
|
363
|
+
text.includes("misalign") ||
|
|
364
|
+
text.includes("drift") ||
|
|
365
|
+
text.includes("blocked");
|
|
366
|
+
const requiresGovernance = detected === "mixed" || !taskContract.ok || stateConflictRequested;
|
|
367
|
+
const activeRoute = requiresGovernance ? routingMap.mixed : route;
|
|
368
|
+
if (text.includes("schema") || text.includes("contract")) {
|
|
369
|
+
recommendedSubagents.add("spec");
|
|
370
|
+
recommendedSkills.add("schema-forge");
|
|
371
|
+
}
|
|
372
|
+
if (text.includes("handoff")) {
|
|
373
|
+
recommendedSubagents.add("ops");
|
|
374
|
+
recommendedSkills.add("handoff-lint");
|
|
375
|
+
}
|
|
376
|
+
if (text.includes("state") || text.includes("status")) {
|
|
377
|
+
recommendedSubagents.add("astgrep");
|
|
378
|
+
recommendedSubagents.add("ops");
|
|
379
|
+
recommendedSubagents.add("skeptic");
|
|
380
|
+
recommendedSkills.add("state-auditor");
|
|
381
|
+
}
|
|
382
|
+
if (text.includes("ast-grep") ||
|
|
383
|
+
text.includes("index") ||
|
|
384
|
+
text.includes("discovery")) {
|
|
385
|
+
recommendedSubagents.add("astgrep");
|
|
386
|
+
recommendedSubagents.add("research");
|
|
387
|
+
recommendedSkills.add("astgrep-index");
|
|
388
|
+
}
|
|
389
|
+
if (text.includes("memory") || text.includes("context drift")) {
|
|
390
|
+
recommendedSubagents.add("memory");
|
|
391
|
+
recommendedSubagents.add("research");
|
|
392
|
+
recommendedSubagents.add("docs");
|
|
393
|
+
recommendedSkills.add("memory-curator");
|
|
394
|
+
}
|
|
395
|
+
if (text.includes("skill") &&
|
|
396
|
+
(text.includes("triage") ||
|
|
397
|
+
text.includes("trigger") ||
|
|
398
|
+
text.includes("frontmatter") ||
|
|
399
|
+
text.includes("portable") ||
|
|
400
|
+
text.includes("portability") ||
|
|
401
|
+
text.includes("adapter") ||
|
|
402
|
+
text.includes("overlay") ||
|
|
403
|
+
text.includes("claude") ||
|
|
404
|
+
text.includes("cursor") ||
|
|
405
|
+
text.includes("codex") ||
|
|
406
|
+
text.includes("antigravity") ||
|
|
407
|
+
text.includes("openai.yaml") ||
|
|
408
|
+
text.includes("openai yaml") ||
|
|
409
|
+
text.includes("metadata") ||
|
|
410
|
+
text.includes("canary"))) {
|
|
411
|
+
recommendedSubagents.add("research");
|
|
412
|
+
recommendedSubagents.add("spec");
|
|
413
|
+
recommendedSubagents.add("ops");
|
|
414
|
+
recommendedSkills.add("problem-triage");
|
|
415
|
+
}
|
|
416
|
+
if (text.includes("skill") && (text.includes("audit") || text.includes("readiness"))) {
|
|
417
|
+
recommendedSubagents.add("research");
|
|
418
|
+
recommendedSubagents.add("skeptic");
|
|
419
|
+
recommendedSubagents.add("ops");
|
|
420
|
+
recommendedSkills.add("skill-auditor");
|
|
421
|
+
}
|
|
422
|
+
if (text.includes("risk") || text.includes("threat")) {
|
|
423
|
+
recommendedSubagents.add("security");
|
|
424
|
+
recommendedSubagents.add("skeptic");
|
|
425
|
+
recommendedSubagents.add("ops");
|
|
426
|
+
recommendedSkills.add("risk-quant");
|
|
427
|
+
}
|
|
428
|
+
if (text.includes("eval") ||
|
|
429
|
+
text.includes("benchmark") ||
|
|
430
|
+
text.includes("regression")) {
|
|
431
|
+
recommendedSubagents.add("eval");
|
|
432
|
+
recommendedSubagents.add("qa");
|
|
433
|
+
recommendedSkills.add("eval-harness");
|
|
434
|
+
}
|
|
435
|
+
if (text.includes("incident") ||
|
|
436
|
+
text.includes("slo") ||
|
|
437
|
+
text.includes("outage")) {
|
|
438
|
+
recommendedSubagents.add("observability");
|
|
439
|
+
recommendedSubagents.add("ops");
|
|
440
|
+
recommendedSkills.add("incident-commander");
|
|
441
|
+
}
|
|
442
|
+
if (text.includes("release") ||
|
|
443
|
+
text.includes("rollback") ||
|
|
444
|
+
text.includes("promote")) {
|
|
445
|
+
recommendedSubagents.add("release");
|
|
446
|
+
recommendedSubagents.add("security");
|
|
447
|
+
recommendedSubagents.add("eval");
|
|
448
|
+
recommendedSubagents.add("observability");
|
|
449
|
+
recommendedSubagents.add("qa");
|
|
450
|
+
recommendedSubagents.add("docs");
|
|
451
|
+
recommendedSkills.add("release-sentry");
|
|
452
|
+
}
|
|
453
|
+
if (text.includes("review") ||
|
|
454
|
+
text.includes("landing") ||
|
|
455
|
+
text.includes("merge") ||
|
|
456
|
+
text.includes("pull request") ||
|
|
457
|
+
/\bpr\b/.test(text) ||
|
|
458
|
+
/\bci\b/.test(text)) {
|
|
459
|
+
recommendedSubagents.add("release");
|
|
460
|
+
recommendedSubagents.add("qa");
|
|
461
|
+
recommendedSubagents.add("ops");
|
|
462
|
+
recommendedSkills.add("landing-review-watcher");
|
|
463
|
+
recommendedSkills.add("release-sentry");
|
|
464
|
+
}
|
|
465
|
+
if (text.includes("build") ||
|
|
466
|
+
text.includes("code") ||
|
|
467
|
+
text.includes("implement") ||
|
|
468
|
+
text.includes("fix")) {
|
|
469
|
+
recommendedSubagents.add("builder");
|
|
470
|
+
}
|
|
471
|
+
if (requiresGovernance) {
|
|
472
|
+
recommendedSubagents.add("skeptic");
|
|
473
|
+
recommendedSubagents.add("ops");
|
|
474
|
+
recommendedSubagents.add("memory");
|
|
475
|
+
}
|
|
476
|
+
return {
|
|
477
|
+
content: [
|
|
478
|
+
{
|
|
479
|
+
type: "text",
|
|
480
|
+
text: [
|
|
481
|
+
"# Task Routing Decision",
|
|
482
|
+
"",
|
|
483
|
+
`**Task:** ${description}`,
|
|
484
|
+
`**Detected Domain:** ${detected}`,
|
|
485
|
+
`**Primary Swarm Agent(s):** ${activeRoute.swarm_agents
|
|
486
|
+
.map((agent) => `ACE-${getRoleTitle(agent)}`)
|
|
487
|
+
.join(", ")}`,
|
|
488
|
+
"**Hierarchy Rule:** Top-level routing stays locked to ACE-Orchestrator, ACE-VOS, ACE-UI, or ACE-Coders. Composable agents are delegated specialists, not peer replacements.",
|
|
489
|
+
`**Preflight Owner:** ACE-Orchestrator`,
|
|
490
|
+
`**Task Contract:** ${taskContract.ok ? "aligned" : "attention required"}`,
|
|
491
|
+
`**Composable Subagents (Universal):** ${[...COMPOSABLE_AGENTS].join(", ")}`,
|
|
492
|
+
`**Recommended Delegated Subagents:** ${[...recommendedSubagents].join(", ")}`,
|
|
493
|
+
`**Pipeline:** ${activeRoute.pipeline}`,
|
|
494
|
+
`**Recommended Prompt:** ${activeRoute.prompt}`,
|
|
495
|
+
recommendedSkills.size > 0
|
|
496
|
+
? `**Recommended Skills:** ${[...recommendedSkills].join(", ")}`
|
|
497
|
+
: "",
|
|
498
|
+
...(!taskContract.ok
|
|
499
|
+
? [
|
|
500
|
+
"",
|
|
501
|
+
"## Preflight Risks",
|
|
502
|
+
...taskContract.files.map((entry) => `- ${entry.path}: ${entry.valid ? "ok" : entry.note}`),
|
|
503
|
+
...taskContract.blockers.map((entry) => `- blocker: ${entry}`),
|
|
504
|
+
]
|
|
505
|
+
: []),
|
|
506
|
+
"",
|
|
507
|
+
"## Preflight Expectations",
|
|
508
|
+
"1. Recall current ACE context from TASK, SCOPE, QUALITY_GATES, STATUS, HANDOFF, and EVIDENCE artifacts.",
|
|
509
|
+
"2. Validate the ACE quartet before dispatching substantial work.",
|
|
510
|
+
"3. Route ambiguity or contract drift through skeptic/validation before handoff.",
|
|
511
|
+
"",
|
|
512
|
+
"## Next Steps",
|
|
513
|
+
`1. Activate prompt: \`${activeRoute.prompt}\``,
|
|
514
|
+
"2. Run `validate_framework` and inspect current ACE state before cross-role dispatch.",
|
|
515
|
+
"3. Load shared kernel context with `get_kernel_artifact` (`directive_kernel`, `agent_registry`)",
|
|
516
|
+
"4. Generate a structured handoff with `create_handoff` only after preflight clears",
|
|
517
|
+
]
|
|
518
|
+
.filter(Boolean)
|
|
519
|
+
.join("\n"),
|
|
520
|
+
},
|
|
521
|
+
],
|
|
522
|
+
};
|
|
523
|
+
});
|
|
524
|
+
// ── Bootstrap ─────────────────────────────────────────────────────
|
|
525
|
+
server.tool("bootstrap_state", "Bootstrap ACE framework files (state, tasks, instructions, skills, scripts, MCP configs, optional local LLM profile)", {
|
|
526
|
+
project_name: z
|
|
527
|
+
.string()
|
|
528
|
+
.optional()
|
|
529
|
+
.describe("Project name for MASTER_PLAN.md"),
|
|
530
|
+
force: z
|
|
531
|
+
.boolean()
|
|
532
|
+
.optional()
|
|
533
|
+
.describe("Overwrite existing scaffold files"),
|
|
534
|
+
include_mcp_config: z
|
|
535
|
+
.boolean()
|
|
536
|
+
.optional()
|
|
537
|
+
.describe("Write the minimal .vscode/mcp.json workspace bridge"),
|
|
538
|
+
include_client_config_bundle: z
|
|
539
|
+
.boolean()
|
|
540
|
+
.optional()
|
|
541
|
+
.describe("Write minimal workspace host stubs (AGENTS.md, CLAUDE.md, .cursorrules, .github/copilot-instructions.md)"),
|
|
542
|
+
llm_provider: z
|
|
543
|
+
.enum(["ollama", "llama.cpp"])
|
|
544
|
+
.optional()
|
|
545
|
+
.describe("Optional local LLM profile provider to scaffold"),
|
|
546
|
+
ollama_model: z
|
|
547
|
+
.string()
|
|
548
|
+
.optional()
|
|
549
|
+
.describe("Model name for generated local profile (legacy field name kept for compatibility)"),
|
|
550
|
+
ollama_base_url: z
|
|
551
|
+
.string()
|
|
552
|
+
.optional()
|
|
553
|
+
.describe("Local runtime base URL for generated profile (legacy field name kept for compatibility)"),
|
|
554
|
+
}, async ({ project_name, force, include_mcp_config, include_client_config_bundle, llm_provider, ollama_model, ollama_base_url, }) => {
|
|
555
|
+
// Store-first bootstrap — initializes ace-state.zarr, bakes host bundles into store,
|
|
556
|
+
// and optionally materializes minimal workspace stubs.
|
|
557
|
+
const storeResult = await bootstrapStoreWorkspace({
|
|
558
|
+
workspaceRoot: WORKSPACE_ROOT,
|
|
559
|
+
projectName: project_name ?? undefined,
|
|
560
|
+
force,
|
|
561
|
+
includeMcpConfig: include_mcp_config,
|
|
562
|
+
includeClientConfigBundle: include_client_config_bundle,
|
|
563
|
+
llm: llm_provider ?? undefined,
|
|
564
|
+
model: ollama_model ?? undefined,
|
|
565
|
+
ollamaUrl: ollama_base_url ?? undefined,
|
|
566
|
+
});
|
|
567
|
+
const astIndex = refreshAstgrepIndex({
|
|
568
|
+
scope: ".",
|
|
569
|
+
append_evidence: true,
|
|
570
|
+
emit_event: true,
|
|
571
|
+
include_rep_corpus: true,
|
|
572
|
+
});
|
|
573
|
+
const delta = scanWorkspaceDelta({
|
|
574
|
+
path: ".",
|
|
575
|
+
depth: 8,
|
|
576
|
+
max_files: 25000,
|
|
577
|
+
include_hidden: false,
|
|
578
|
+
exclude: [
|
|
579
|
+
".git",
|
|
580
|
+
"node_modules",
|
|
581
|
+
"dist",
|
|
582
|
+
"target",
|
|
583
|
+
".venv",
|
|
584
|
+
"__pycache__",
|
|
585
|
+
".DS_Store",
|
|
586
|
+
],
|
|
587
|
+
file_entry_cap: 0,
|
|
588
|
+
});
|
|
589
|
+
const runLedger = await appendRunLedgerEntrySafe({
|
|
590
|
+
tool: "bootstrap_state",
|
|
591
|
+
category: "major_update",
|
|
592
|
+
message: "Bootstrapped ACE workspace state",
|
|
593
|
+
artifacts: [
|
|
594
|
+
`${ACE_ROOT_REL}/ace-state.zarr`,
|
|
595
|
+
`${ACE_TASKS_ROOT_REL}/todo.md`,
|
|
596
|
+
normalizePathForValidation(delta.index_path),
|
|
597
|
+
"agent-state/AST_GREP_INDEX.json",
|
|
598
|
+
],
|
|
599
|
+
metadata: {
|
|
600
|
+
materialized: storeResult.materialized.length,
|
|
601
|
+
force: Boolean(force),
|
|
602
|
+
llm_provider: llm_provider ?? null,
|
|
603
|
+
llm_model: ollama_model ?? null,
|
|
604
|
+
llm_base_url: ollama_base_url ?? null,
|
|
605
|
+
indexed_files: delta.snapshot.file_count,
|
|
606
|
+
index_truncated: delta.truncated,
|
|
607
|
+
ast_index_scope: astIndex.scope,
|
|
608
|
+
ast_hotspot_files: astIndex.stats.hotspot_files,
|
|
609
|
+
},
|
|
610
|
+
});
|
|
611
|
+
return {
|
|
612
|
+
content: [
|
|
613
|
+
{
|
|
614
|
+
type: "text",
|
|
615
|
+
text: [
|
|
616
|
+
"# Bootstrap Complete",
|
|
617
|
+
"",
|
|
618
|
+
`Store: ${storeResult.storePath}`,
|
|
619
|
+
`Agents baked: ${storeResult.agents}`,
|
|
620
|
+
`Materialized files: ${storeResult.materialized.length}`,
|
|
621
|
+
"",
|
|
622
|
+
"## Discovery Index",
|
|
623
|
+
`- path: ${delta.index_path}`,
|
|
624
|
+
`- root: ${delta.snapshot.root}`,
|
|
625
|
+
`- file_count: ${delta.snapshot.file_count}`,
|
|
626
|
+
`- stored_file_count: ${delta.snapshot.stored_file_count}`,
|
|
627
|
+
`- file_entry_cap: ${delta.snapshot.options.file_entry_cap}`,
|
|
628
|
+
`- scanned_count: ${delta.scanned_count}`,
|
|
629
|
+
`- truncated: ${delta.truncated ? "yes" : "no"}`,
|
|
630
|
+
"",
|
|
631
|
+
"## AST Discovery Index",
|
|
632
|
+
`- scope: ${astIndex.scope}`,
|
|
633
|
+
`- ast_grep_command: ${astIndex.astgrep_command ?? "unavailable"}`,
|
|
634
|
+
`- hotspot_files: ${astIndex.stats.hotspot_files}`,
|
|
635
|
+
`- language_profile_entries: ${astIndex.stats.language_profile_entries}`,
|
|
636
|
+
`- json: ${astIndex.output_json_path}`,
|
|
637
|
+
`- md: ${astIndex.output_md_path}`,
|
|
638
|
+
"",
|
|
639
|
+
"## Materialized",
|
|
640
|
+
...(storeResult.materialized.length > 0
|
|
641
|
+
? storeResult.materialized.map((p) => `- ${p}`)
|
|
642
|
+
: ["- (none)"]),
|
|
643
|
+
"",
|
|
644
|
+
...(llm_provider
|
|
645
|
+
? [
|
|
646
|
+
"",
|
|
647
|
+
"## Local LLM Profile",
|
|
648
|
+
`- provider: ${llm_provider}`,
|
|
649
|
+
`- model: ${ollama_model ?? (llm_provider === "llama.cpp" ? DEFAULT_LLAMA_CPP_MODEL : DEFAULT_OLLAMA_MODEL)}`,
|
|
650
|
+
`- base_url: ${ollama_base_url ?? "discover via ace doctor --scan or set explicitly"}`,
|
|
651
|
+
`- profile_path: ${storeResult.storePath}#state/runtime/llm_profile`,
|
|
652
|
+
`- doctor_path: ${storeResult.storePath}#state/runtime/doctor_checks.md`,
|
|
653
|
+
]
|
|
654
|
+
: []),
|
|
655
|
+
"",
|
|
656
|
+
"## Run Ledger",
|
|
657
|
+
`- path: ${runLedger.path}`,
|
|
658
|
+
`- entry: ${runLedger.entry.id}`,
|
|
659
|
+
].join("\n"),
|
|
660
|
+
},
|
|
661
|
+
],
|
|
662
|
+
};
|
|
663
|
+
});
|
|
664
|
+
// ── Framework Status ──────────────────────────────────────────────
|
|
665
|
+
server.tool("get_framework_status", "Inspect ACE framework wiring: agents, tasks, skills, and core state files", {}, async () => {
|
|
666
|
+
const swarmGroup = [...SWARM_AGENTS].join(", ");
|
|
667
|
+
const composableGroup = [...COMPOSABLE_AGENTS].join(", ");
|
|
668
|
+
const agentLines = ALL_AGENTS.flatMap((role) => {
|
|
669
|
+
const instructionPath = getAgentInstructionPath(role);
|
|
670
|
+
const manifestPath = getAgentManifestPath(role);
|
|
671
|
+
const group = isSwarmRole(role) ? "swarm" : "composable";
|
|
672
|
+
return [
|
|
673
|
+
`- ${role} [${group}]: instructions -> ${classifyPathSource(instructionPath)}${instructionPath ? ` (${instructionPath})` : ""}`,
|
|
674
|
+
` manifest -> ${classifyPathSource(manifestPath)}${manifestPath ? ` (${manifestPath})` : ""}`,
|
|
675
|
+
isSwarmRole(role)
|
|
676
|
+
? ` subagents -> ${SWARM_SUBAGENT_MAP[role].join(", ")}`
|
|
677
|
+
: ` available-to -> ${[...SWARM_AGENTS].join(", ")}`,
|
|
678
|
+
];
|
|
679
|
+
});
|
|
680
|
+
const kernelKeys = ["directive_kernel", "agent_registry"];
|
|
681
|
+
const kernelLines = kernelKeys.map((key) => {
|
|
682
|
+
const path = getKernelArtifactPath(key);
|
|
683
|
+
return `- ${key}: ${classifyPathSource(path)}${path ? ` (${path})` : ""}`;
|
|
684
|
+
});
|
|
685
|
+
const taskKeys = [
|
|
686
|
+
"todo",
|
|
687
|
+
"role_tasks",
|
|
688
|
+
"cli_work_split",
|
|
689
|
+
"lessons",
|
|
690
|
+
"handoff_template",
|
|
691
|
+
];
|
|
692
|
+
const taskLines = taskKeys.map((key) => {
|
|
693
|
+
const path = getTaskArtifactPath(key);
|
|
694
|
+
return `- ${key}: ${classifyPathSource(path)}${path ? ` (${path})` : ""}`;
|
|
695
|
+
});
|
|
696
|
+
const skills = listAvailableSkills();
|
|
697
|
+
const skillsLines = skills.map((skill) => `- ${skill.name}: ${skill.source} (${skill.path})`);
|
|
698
|
+
const stateChecks = [
|
|
699
|
+
"agent-state/TASK.md",
|
|
700
|
+
"agent-state/STATUS.md",
|
|
701
|
+
"agent-state/SCOPE.md",
|
|
702
|
+
"agent-state/QUALITY_GATES.md",
|
|
703
|
+
"agent-state/EVIDENCE_LOG.md",
|
|
704
|
+
"agent-state/DECISIONS.md",
|
|
705
|
+
"agent-state/RISKS.md",
|
|
706
|
+
"agent-state/TEAL_CONFIG.md",
|
|
707
|
+
"agent-state/PROVENANCE_LOG.md",
|
|
708
|
+
"agent-state/ARTIFACT_MANIFEST.json",
|
|
709
|
+
"agent-state/ACE_WORKFLOW.md",
|
|
710
|
+
"agent-state/runtime-workspaces.json",
|
|
711
|
+
"agent-state/runtime-tool-specs.json",
|
|
712
|
+
"agent-state/runtime-executor-sessions.json",
|
|
713
|
+
"agent-state/tracker-snapshot.json",
|
|
714
|
+
"agent-state/vericify/ace-bridge.json",
|
|
715
|
+
"agent-state/vericify/process-posts.json",
|
|
716
|
+
"agent-state/PUBLIC_SURFACE_REPORT.md",
|
|
717
|
+
"agent-state/HANDOFF.json",
|
|
718
|
+
"agent-state/STATUS_EVENTS.ndjson",
|
|
719
|
+
"agent-state/handoff-registry.json",
|
|
720
|
+
"agent-state/run-ledger.json",
|
|
721
|
+
"agent-state/index.json",
|
|
722
|
+
"agent-state/index-fingerprints.json",
|
|
723
|
+
"agent-state/AST_GREP_COMMANDS.md",
|
|
724
|
+
"agent-state/AST_GREP_INDEX.md",
|
|
725
|
+
"agent-state/AST_GREP_INDEX.json",
|
|
726
|
+
"agent-state/MODULES/schemas/ACE_RUNTIME_PROFILE.schema.json",
|
|
727
|
+
"agent-state/MODULES/schemas/WORKSPACE_SESSION_REGISTRY.schema.json",
|
|
728
|
+
"agent-state/MODULES/schemas/RUNTIME_TOOL_SPEC_REGISTRY.schema.json",
|
|
729
|
+
"agent-state/MODULES/schemas/RUNTIME_EXECUTOR_SESSION_REGISTRY.schema.json",
|
|
730
|
+
"agent-state/MODULES/schemas/TRACKER_SNAPSHOT.schema.json",
|
|
731
|
+
"agent-state/MODULES/schemas/VERICIFY_BRIDGE_SNAPSHOT.schema.json",
|
|
732
|
+
"agent-state/MODULES/schemas/VERICIFY_PROCESS_POST_LOG.schema.json",
|
|
733
|
+
"agent-state/todo-state.json",
|
|
734
|
+
"agent-state/job-queue.json",
|
|
735
|
+
"agent-state/job-locks.json",
|
|
736
|
+
"agent-state/scheduler-lease.json",
|
|
737
|
+
"agent-state/kanban.json",
|
|
738
|
+
"agent-state/kanban.html",
|
|
739
|
+
];
|
|
740
|
+
const stateLines = stateChecks.map((relPath) => {
|
|
741
|
+
const abs = wsPath(relPath);
|
|
742
|
+
const exists = safeRead(relPath).startsWith("[FILE NOT FOUND]")
|
|
743
|
+
? "missing"
|
|
744
|
+
: "ok";
|
|
745
|
+
return `- ${relPath}: ${exists} (${abs})`;
|
|
746
|
+
});
|
|
747
|
+
const kanban = getOrRefreshKanbanSnapshot("tool:get_framework_status");
|
|
748
|
+
const kanbanLine = `- kanban-counts: backlog=${kanban.counts.backlog}, blocked=${kanban.counts.blocked}, in_progress=${kanban.counts.in_progress}, gated=${kanban.counts.gated}, done=${kanban.counts.done}`;
|
|
749
|
+
// New: git status
|
|
750
|
+
const gitLine = isGitRepo()
|
|
751
|
+
? (() => {
|
|
752
|
+
const gs = gitStatus();
|
|
753
|
+
return `- git: branch=${gs.branch}, clean=${gs.clean}`;
|
|
754
|
+
})()
|
|
755
|
+
: "- git: not a git repository";
|
|
756
|
+
return {
|
|
757
|
+
content: [
|
|
758
|
+
{
|
|
759
|
+
type: "text",
|
|
760
|
+
text: [
|
|
761
|
+
"# ACE Framework Status",
|
|
762
|
+
"",
|
|
763
|
+
"## Agent Groups",
|
|
764
|
+
`- swarm: ${swarmGroup}`,
|
|
765
|
+
`- composable: ${composableGroup}`,
|
|
766
|
+
"",
|
|
767
|
+
"## Agent Artifacts",
|
|
768
|
+
...agentLines,
|
|
769
|
+
"",
|
|
770
|
+
"## Kernel Artifacts",
|
|
771
|
+
...kernelLines,
|
|
772
|
+
"",
|
|
773
|
+
"## Task Artifacts",
|
|
774
|
+
...taskLines,
|
|
775
|
+
"",
|
|
776
|
+
"## Skills",
|
|
777
|
+
...(skillsLines.length > 0 ? skillsLines : ["- none found"]),
|
|
778
|
+
"",
|
|
779
|
+
"## Core State",
|
|
780
|
+
...stateLines,
|
|
781
|
+
kanbanLine,
|
|
782
|
+
"",
|
|
783
|
+
"## Version Control",
|
|
784
|
+
gitLine,
|
|
785
|
+
].join("\n"),
|
|
786
|
+
},
|
|
787
|
+
],
|
|
788
|
+
};
|
|
789
|
+
});
|
|
790
|
+
// ── MCP Config ────────────────────────────────────────────────────
|
|
791
|
+
server.tool("get_mcp_config", "Get MCP client config snippet(s) for this package", {
|
|
792
|
+
client: MCP_CLIENT_ENUM.optional().describe("codex|vscode|claude|cursor|antigravity (default: vscode)"),
|
|
793
|
+
all: z
|
|
794
|
+
.boolean()
|
|
795
|
+
.optional()
|
|
796
|
+
.describe("Return snippets and install hints for all supported clients"),
|
|
797
|
+
}, async ({ client, all }) => {
|
|
798
|
+
if (all) {
|
|
799
|
+
const snippets = getAllMcpServerConfigSnippets();
|
|
800
|
+
const body = ALL_MCP_CLIENTS.map((name) => {
|
|
801
|
+
const fence = name === "codex" ? "toml" : "json";
|
|
802
|
+
return [
|
|
803
|
+
`## ${name}`,
|
|
804
|
+
"",
|
|
805
|
+
`Install hint: ${getMcpClientInstallHint(name)}`,
|
|
806
|
+
"",
|
|
807
|
+
`\`\`\`${fence}`,
|
|
808
|
+
snippets[name],
|
|
809
|
+
"```",
|
|
810
|
+
].join("\n");
|
|
811
|
+
}).join("\n\n");
|
|
812
|
+
return {
|
|
813
|
+
content: [
|
|
814
|
+
{ type: "text", text: `# MCP Client Configs\n\n${body}` },
|
|
815
|
+
],
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
const selected = (client ?? "vscode");
|
|
819
|
+
const fence = selected === "codex" ? "toml" : "json";
|
|
820
|
+
return {
|
|
821
|
+
content: [
|
|
822
|
+
{
|
|
823
|
+
type: "text",
|
|
824
|
+
text: [
|
|
825
|
+
`# MCP Config (${selected})`,
|
|
826
|
+
"",
|
|
827
|
+
`Install hint: ${getMcpClientInstallHint(selected)}`,
|
|
828
|
+
"",
|
|
829
|
+
`\`\`\`${fence}`,
|
|
830
|
+
getMcpServerConfigSnippet(selected),
|
|
831
|
+
"```",
|
|
832
|
+
].join("\n"),
|
|
833
|
+
},
|
|
834
|
+
],
|
|
835
|
+
};
|
|
836
|
+
});
|
|
837
|
+
// ── Run Tests (new P0 tool) ───────────────────────────────────────
|
|
838
|
+
server.tool("run_tests", "Execute the project test suite and report results", {
|
|
839
|
+
command: z
|
|
840
|
+
.string()
|
|
841
|
+
.optional()
|
|
842
|
+
.describe("Custom test command (auto-detected from package.json if omitted)"),
|
|
843
|
+
}, async ({ command }) => {
|
|
844
|
+
const result = runTestSuite(command);
|
|
845
|
+
appendStatusEventSafe({
|
|
846
|
+
source_module: "capability-safety",
|
|
847
|
+
event_type: result.ok ? "TESTS_PASSED" : "TESTS_FAILED",
|
|
848
|
+
status: result.ok ? "pass" : "fail",
|
|
849
|
+
summary: `Tests ${result.ok ? "passed" : "FAILED"} (exit ${result.exit_code}, ${result.duration_ms}ms)`,
|
|
850
|
+
payload: {
|
|
851
|
+
command: result.command,
|
|
852
|
+
exit_code: result.exit_code,
|
|
853
|
+
duration_ms: result.duration_ms,
|
|
854
|
+
},
|
|
855
|
+
});
|
|
856
|
+
const ledger = await appendRunLedgerEntrySafe({
|
|
857
|
+
tool: "run_tests",
|
|
858
|
+
category: result.ok ? "info" : "regression",
|
|
859
|
+
message: `Tests ${result.ok ? "passed" : "FAILED"}: ${result.command}`,
|
|
860
|
+
artifacts: [],
|
|
861
|
+
metadata: {
|
|
862
|
+
exit_code: result.exit_code,
|
|
863
|
+
duration_ms: result.duration_ms,
|
|
864
|
+
command: result.command,
|
|
865
|
+
},
|
|
866
|
+
});
|
|
867
|
+
return {
|
|
868
|
+
content: [
|
|
869
|
+
{
|
|
870
|
+
type: "text",
|
|
871
|
+
text: [
|
|
872
|
+
result.ok ? "✅ Tests passed" : "❌ Tests FAILED",
|
|
873
|
+
`Command: ${result.command}`,
|
|
874
|
+
`Exit code: ${result.exit_code}`,
|
|
875
|
+
`Duration: ${result.duration_ms}ms`,
|
|
876
|
+
`Run ledger: ${ledger.path} (${ledger.entry.id})`,
|
|
877
|
+
"",
|
|
878
|
+
"```",
|
|
879
|
+
result.output,
|
|
880
|
+
"```",
|
|
881
|
+
].join("\n"),
|
|
882
|
+
},
|
|
883
|
+
],
|
|
884
|
+
};
|
|
885
|
+
});
|
|
886
|
+
// ── Validate Framework (new P1 tool) ──────────────────────────────
|
|
887
|
+
server.tool("validate_framework", "Run self-checks to detect drift between agent state, schemas, and filesystem", {}, async () => {
|
|
888
|
+
const checks = [];
|
|
889
|
+
// Check: required state files exist
|
|
890
|
+
const requiredFiles = [
|
|
891
|
+
"agent-state/TASK.md",
|
|
892
|
+
"agent-state/SCOPE.md",
|
|
893
|
+
"agent-state/QUALITY_GATES.md",
|
|
894
|
+
"agent-state/HANDOFF.json",
|
|
895
|
+
"agent-state/STATUS.md",
|
|
896
|
+
"agent-state/EVIDENCE_LOG.md",
|
|
897
|
+
"agent-state/DECISIONS.md",
|
|
898
|
+
"agent-state/RISKS.md",
|
|
899
|
+
"agent-state/TEAL_CONFIG.md",
|
|
900
|
+
"agent-state/PROVENANCE_LOG.md",
|
|
901
|
+
"agent-state/ARTIFACT_MANIFEST.json",
|
|
902
|
+
`${ACE_TASKS_ROOT_REL}/todo.md`,
|
|
903
|
+
`${ACE_TASKS_ROOT_REL}/role_tasks.md`,
|
|
904
|
+
`${ACE_TASKS_ROOT_REL}/lessons.md`,
|
|
905
|
+
`${ACE_ROOT_REL}/global-state/MASTER_PLAN.md`,
|
|
906
|
+
];
|
|
907
|
+
for (const f of requiredFiles) {
|
|
908
|
+
const content = safeRead(f);
|
|
909
|
+
const exists = !content.startsWith("[FILE NOT FOUND]");
|
|
910
|
+
checks.push({
|
|
911
|
+
name: `state-file:${f}`,
|
|
912
|
+
ok: exists,
|
|
913
|
+
detail: exists ? "present" : "MISSING",
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
// Check: handoff registry parseable
|
|
917
|
+
const hrRaw = safeRead("agent-state/handoff-registry.json");
|
|
918
|
+
const hrOk = !hrRaw.startsWith("[FILE NOT FOUND]");
|
|
919
|
+
if (hrOk) {
|
|
920
|
+
try {
|
|
921
|
+
JSON.parse(hrRaw);
|
|
922
|
+
checks.push({
|
|
923
|
+
name: "handoff-registry:parse",
|
|
924
|
+
ok: true,
|
|
925
|
+
detail: "valid JSON",
|
|
926
|
+
});
|
|
927
|
+
}
|
|
928
|
+
catch {
|
|
929
|
+
checks.push({
|
|
930
|
+
name: "handoff-registry:parse",
|
|
931
|
+
ok: false,
|
|
932
|
+
detail: "CORRUPT JSON",
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
// Check: run-ledger parseable
|
|
937
|
+
const rlRaw = safeRead("agent-state/run-ledger.json");
|
|
938
|
+
if (!rlRaw.startsWith("[FILE NOT FOUND]")) {
|
|
939
|
+
try {
|
|
940
|
+
JSON.parse(rlRaw);
|
|
941
|
+
checks.push({
|
|
942
|
+
name: "run-ledger:parse",
|
|
943
|
+
ok: true,
|
|
944
|
+
detail: "valid JSON",
|
|
945
|
+
});
|
|
946
|
+
}
|
|
947
|
+
catch {
|
|
948
|
+
checks.push({
|
|
949
|
+
name: "run-ledger:parse",
|
|
950
|
+
ok: false,
|
|
951
|
+
detail: "CORRUPT JSON",
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
// Check: todo-state parseable
|
|
956
|
+
const tsRaw = safeRead("agent-state/todo-state.json");
|
|
957
|
+
if (!tsRaw.startsWith("[FILE NOT FOUND]")) {
|
|
958
|
+
try {
|
|
959
|
+
JSON.parse(tsRaw);
|
|
960
|
+
checks.push({
|
|
961
|
+
name: "todo-state:parse",
|
|
962
|
+
ok: true,
|
|
963
|
+
detail: "valid JSON",
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
catch {
|
|
967
|
+
checks.push({
|
|
968
|
+
name: "todo-state:parse",
|
|
969
|
+
ok: false,
|
|
970
|
+
detail: "CORRUPT JSON",
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
// Check: scheduler stores parseable
|
|
975
|
+
const schedulerStoreChecks = [
|
|
976
|
+
{ rel: "agent-state/job-queue.json", name: "job-queue:parse" },
|
|
977
|
+
{ rel: "agent-state/job-locks.json", name: "job-locks:parse" },
|
|
978
|
+
{ rel: "agent-state/scheduler-lease.json", name: "scheduler-lease:parse" },
|
|
979
|
+
];
|
|
980
|
+
for (const check of schedulerStoreChecks) {
|
|
981
|
+
const raw = safeRead(check.rel);
|
|
982
|
+
if (raw.startsWith("[FILE NOT FOUND]")) {
|
|
983
|
+
checks.push({
|
|
984
|
+
name: check.name,
|
|
985
|
+
ok: false,
|
|
986
|
+
detail: "MISSING",
|
|
987
|
+
});
|
|
988
|
+
continue;
|
|
989
|
+
}
|
|
990
|
+
try {
|
|
991
|
+
JSON.parse(raw);
|
|
992
|
+
checks.push({
|
|
993
|
+
name: check.name,
|
|
994
|
+
ok: true,
|
|
995
|
+
detail: "valid JSON",
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
catch {
|
|
999
|
+
checks.push({
|
|
1000
|
+
name: check.name,
|
|
1001
|
+
ok: false,
|
|
1002
|
+
detail: "CORRUPT JSON",
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
// Check: TEAL config has exactly one active YAML block
|
|
1007
|
+
const tealRaw = safeRead("agent-state/TEAL_CONFIG.md");
|
|
1008
|
+
if (!tealRaw.startsWith("[FILE NOT FOUND]")) {
|
|
1009
|
+
const validation = validateTealConfigContent(tealRaw);
|
|
1010
|
+
checks.push({
|
|
1011
|
+
name: "teal-config:structure",
|
|
1012
|
+
ok: validation.ok,
|
|
1013
|
+
detail: validation.ok
|
|
1014
|
+
? `valid (${validation.schema})`
|
|
1015
|
+
: validation.errors.join("; "),
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
// Check: provenance log contains canonical provenance fields
|
|
1019
|
+
const provenanceRaw = safeRead("agent-state/PROVENANCE_LOG.md");
|
|
1020
|
+
if (!provenanceRaw.startsWith("[FILE NOT FOUND]")) {
|
|
1021
|
+
const validation = validateProvenanceLogContent(provenanceRaw);
|
|
1022
|
+
checks.push({
|
|
1023
|
+
name: "provenance-log:structure",
|
|
1024
|
+
ok: validation.ok,
|
|
1025
|
+
detail: validation.ok
|
|
1026
|
+
? `valid (${validation.schema})`
|
|
1027
|
+
: validation.errors.join("; "),
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
// Check: artifact manifest exists and satisfies provenance contract
|
|
1031
|
+
const artifactManifestRaw = safeRead("agent-state/ARTIFACT_MANIFEST.json");
|
|
1032
|
+
let artifactManifestEntries = [];
|
|
1033
|
+
if (!artifactManifestRaw.startsWith("[FILE NOT FOUND]")) {
|
|
1034
|
+
try {
|
|
1035
|
+
const parsed = JSON.parse(artifactManifestRaw);
|
|
1036
|
+
const validation = validateArtifactManifestPayload(parsed);
|
|
1037
|
+
checks.push({
|
|
1038
|
+
name: "artifact-manifest:schema",
|
|
1039
|
+
ok: validation.ok,
|
|
1040
|
+
detail: validation.ok
|
|
1041
|
+
? `valid (${validation.schema})`
|
|
1042
|
+
: validation.errors.join("; "),
|
|
1043
|
+
});
|
|
1044
|
+
if (validation.ok) {
|
|
1045
|
+
artifactManifestEntries = getArtifactManifestEntries(parsed);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
catch {
|
|
1049
|
+
checks.push({
|
|
1050
|
+
name: "artifact-manifest:parse",
|
|
1051
|
+
ok: false,
|
|
1052
|
+
detail: "CORRUPT JSON",
|
|
1053
|
+
});
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
if (artifactManifestEntries.length > 0 &&
|
|
1057
|
+
!provenanceRaw.startsWith("[FILE NOT FOUND]")) {
|
|
1058
|
+
const missingLinks = artifactManifestEntries.filter((entry) => !provenanceRaw.includes(entry.artifact_id) ||
|
|
1059
|
+
!provenanceRaw.includes(entry.checksum) ||
|
|
1060
|
+
!provenanceRaw.includes(entry.evidence_ref));
|
|
1061
|
+
checks.push({
|
|
1062
|
+
name: "provenance-log:manifest-linkage",
|
|
1063
|
+
ok: missingLinks.length === 0,
|
|
1064
|
+
detail: missingLinks.length === 0
|
|
1065
|
+
? `all ${artifactManifestEntries.length} manifest entries linked in PROVENANCE_LOG.md`
|
|
1066
|
+
: `${missingLinks.length} manifest entries missing provenance links in PROVENANCE_LOG.md`,
|
|
1067
|
+
});
|
|
1068
|
+
}
|
|
1069
|
+
const taskContract = readAceTaskContractAssessment();
|
|
1070
|
+
checks.push({
|
|
1071
|
+
name: "task-contract:quartet",
|
|
1072
|
+
ok: taskContract.ok,
|
|
1073
|
+
detail: taskContract.ok
|
|
1074
|
+
? taskContract.summary
|
|
1075
|
+
: [
|
|
1076
|
+
...taskContract.files.map((entry) => `${entry.path}=${entry.valid ? "ok" : entry.note}`),
|
|
1077
|
+
...taskContract.blockers,
|
|
1078
|
+
].join("; "),
|
|
1079
|
+
});
|
|
1080
|
+
// Check: git status
|
|
1081
|
+
checks.push({
|
|
1082
|
+
name: "git-repo",
|
|
1083
|
+
ok: isGitRepo(),
|
|
1084
|
+
detail: isGitRepo() ? "initialized" : "NOT a git repo",
|
|
1085
|
+
});
|
|
1086
|
+
// ── Deep checks (P2 hardening) ─────────────────────────────────
|
|
1087
|
+
// Check: module registry role coverage vs event emitters
|
|
1088
|
+
const registryRaw = safeRead("agent-state/MODULES/registry.json");
|
|
1089
|
+
if (!registryRaw.startsWith("[FILE NOT FOUND]")) {
|
|
1090
|
+
try {
|
|
1091
|
+
const registry = JSON.parse(registryRaw);
|
|
1092
|
+
const registeredRoles = new Set(registry.roles ?? []);
|
|
1093
|
+
const expectedEmitters = [
|
|
1094
|
+
"capability-safety",
|
|
1095
|
+
"capability-framework",
|
|
1096
|
+
"capability-git",
|
|
1097
|
+
"capability-astgrep",
|
|
1098
|
+
"capability-ops",
|
|
1099
|
+
"capability-memory",
|
|
1100
|
+
];
|
|
1101
|
+
for (const emitter of expectedEmitters) {
|
|
1102
|
+
const found = registeredRoles.has(emitter);
|
|
1103
|
+
checks.push({
|
|
1104
|
+
name: `registry-role:${emitter}`,
|
|
1105
|
+
ok: found,
|
|
1106
|
+
detail: found ? "registered" : "MISSING from registry",
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
catch {
|
|
1111
|
+
checks.push({
|
|
1112
|
+
name: "registry:parse",
|
|
1113
|
+
ok: false,
|
|
1114
|
+
detail: "registry.json is corrupt",
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
// Check: asset drift detection
|
|
1119
|
+
const drift = detectAssetDrift();
|
|
1120
|
+
checks.push({
|
|
1121
|
+
name: "asset-drift:total",
|
|
1122
|
+
ok: drift.drifted === 0,
|
|
1123
|
+
detail: drift.drifted === 0
|
|
1124
|
+
? `${drift.checked} files checked, no drift`
|
|
1125
|
+
: `${drift.drifted}/${drift.checked} files drifted`,
|
|
1126
|
+
});
|
|
1127
|
+
if (drift.missing_runtime > 0) {
|
|
1128
|
+
checks.push({
|
|
1129
|
+
name: "asset-drift:missing-runtime",
|
|
1130
|
+
ok: false,
|
|
1131
|
+
detail: `${drift.missing_runtime} asset files missing from runtime workspace`,
|
|
1132
|
+
});
|
|
1133
|
+
}
|
|
1134
|
+
// Check: handoff consistency (open handoffs have source files)
|
|
1135
|
+
if (hrOk) {
|
|
1136
|
+
try {
|
|
1137
|
+
const registry = JSON.parse(hrRaw);
|
|
1138
|
+
const handoffs = Object.values(registry.handoffs ?? {});
|
|
1139
|
+
let openWithoutFile = 0;
|
|
1140
|
+
for (const h of handoffs) {
|
|
1141
|
+
if ((h.status === "open" || h.status === "accepted") &&
|
|
1142
|
+
h.source_file) {
|
|
1143
|
+
const fileContent = safeRead(h.source_file);
|
|
1144
|
+
if (fileContent.startsWith("[FILE NOT FOUND]"))
|
|
1145
|
+
openWithoutFile++;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
checks.push({
|
|
1149
|
+
name: "handoff:source-file-integrity",
|
|
1150
|
+
ok: openWithoutFile === 0,
|
|
1151
|
+
detail: openWithoutFile === 0
|
|
1152
|
+
? "all open handoffs have source files"
|
|
1153
|
+
: `${openWithoutFile} open handoffs reference missing source files`,
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
catch {
|
|
1157
|
+
/* already caught above */
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1160
|
+
// Check: event provenance gaps in recent events.
|
|
1161
|
+
// Scans for provenance-critical event types that are missing
|
|
1162
|
+
// objective_id, decision_id, AND payload.evidence_ref (all three absent).
|
|
1163
|
+
// The old _provenance_gap marker is obsolete — fail-closed enforcement
|
|
1164
|
+
// now throws before such events are written, but legacy rows may exist.
|
|
1165
|
+
const recentEventsRaw = safeRead("agent-state/STATUS_EVENTS.ndjson");
|
|
1166
|
+
if (!recentEventsRaw.startsWith("[FILE NOT FOUND]")) {
|
|
1167
|
+
const lines = recentEventsRaw.split("\n").filter((l) => l.trim());
|
|
1168
|
+
const recentLines = lines.slice(Math.max(0, lines.length - 50));
|
|
1169
|
+
let provenanceGaps = 0;
|
|
1170
|
+
for (const line of recentLines) {
|
|
1171
|
+
try {
|
|
1172
|
+
const ev = JSON.parse(line);
|
|
1173
|
+
const eventType = ev.event_type;
|
|
1174
|
+
if (!eventType || !PROVENANCE_CRITICAL_EVENT_TYPES.has(eventType))
|
|
1175
|
+
continue;
|
|
1176
|
+
const hasObj = typeof ev.objective_id === "string" && ev.objective_id.length > 0;
|
|
1177
|
+
const hasDec = typeof ev.decision_id === "string" && ev.decision_id.length > 0;
|
|
1178
|
+
const payload = ev.payload;
|
|
1179
|
+
const hasEv = typeof payload?.evidence_ref === "string" && payload.evidence_ref.length > 0;
|
|
1180
|
+
// Legacy gap detection: also flag the old marker for backward compat scan
|
|
1181
|
+
const hasLegacyGap = payload && payload._provenance_gap === true;
|
|
1182
|
+
if ((!hasObj && !hasDec && !hasEv) || hasLegacyGap)
|
|
1183
|
+
provenanceGaps++;
|
|
1184
|
+
}
|
|
1185
|
+
catch {
|
|
1186
|
+
/* skip */
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
checks.push({
|
|
1190
|
+
name: "event-provenance:recent",
|
|
1191
|
+
ok: provenanceGaps === 0,
|
|
1192
|
+
detail: provenanceGaps === 0
|
|
1193
|
+
? "no provenance gaps in recent critical events"
|
|
1194
|
+
: `${provenanceGaps} recent critical events missing provenance fields`,
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1197
|
+
const passed = checks.filter((c) => c.ok).length;
|
|
1198
|
+
const failed = checks.filter((c) => !c.ok).length;
|
|
1199
|
+
const allOk = failed === 0;
|
|
1200
|
+
await appendStatusEventSafe({
|
|
1201
|
+
source_module: "capability-framework",
|
|
1202
|
+
event_type: "FRAMEWORK_VALIDATED",
|
|
1203
|
+
status: allOk ? "pass" : "fail",
|
|
1204
|
+
summary: `Framework validation: ${passed}/${checks.length} passed`,
|
|
1205
|
+
objective_id: "framework-validation",
|
|
1206
|
+
payload: { passed, failed, total: checks.length, evidence_ref: "agent-state/STATUS_EVENTS.ndjson" },
|
|
1207
|
+
});
|
|
1208
|
+
const ledger = await appendRunLedgerEntrySafe({
|
|
1209
|
+
tool: "validate_framework",
|
|
1210
|
+
category: allOk ? "info" : "regression",
|
|
1211
|
+
message: `Framework validation: ${passed}/${checks.length} passed`,
|
|
1212
|
+
artifacts: [],
|
|
1213
|
+
metadata: { passed, failed },
|
|
1214
|
+
});
|
|
1215
|
+
return {
|
|
1216
|
+
content: [
|
|
1217
|
+
{
|
|
1218
|
+
type: "text",
|
|
1219
|
+
text: [
|
|
1220
|
+
allOk
|
|
1221
|
+
? `✅ Framework validated: ${passed}/${checks.length} checks passed`
|
|
1222
|
+
: `⚠️ Framework issues: ${failed}/${checks.length} checks failed`,
|
|
1223
|
+
`Run ledger: ${ledger.path} (${ledger.entry.id})`,
|
|
1224
|
+
"",
|
|
1225
|
+
...checks.map((c) => `- ${c.ok ? "✅" : "❌"} ${c.name}: ${c.detail}`),
|
|
1226
|
+
].join("\n"),
|
|
1227
|
+
},
|
|
1228
|
+
],
|
|
1229
|
+
};
|
|
1230
|
+
});
|
|
1231
|
+
server.tool("audit_public_surface", "Audit exported TypeScript MCP tools/resources/prompts/events and write PUBLIC_SURFACE_REPORT.md", {
|
|
1232
|
+
write_artifact: z
|
|
1233
|
+
.boolean()
|
|
1234
|
+
.optional()
|
|
1235
|
+
.describe("Write agent-state/PUBLIC_SURFACE_REPORT.md (default: true)"),
|
|
1236
|
+
artifact_path: z
|
|
1237
|
+
.string()
|
|
1238
|
+
.optional()
|
|
1239
|
+
.describe("Optional workspace-relative path for the public-surface report"),
|
|
1240
|
+
}, async ({ write_artifact, artifact_path }) => {
|
|
1241
|
+
const result = await auditPublicSurface({
|
|
1242
|
+
write_artifact,
|
|
1243
|
+
artifact_path,
|
|
1244
|
+
});
|
|
1245
|
+
return {
|
|
1246
|
+
content: [
|
|
1247
|
+
{
|
|
1248
|
+
type: "text",
|
|
1249
|
+
text: [
|
|
1250
|
+
result.ok
|
|
1251
|
+
? `✅ Public surface audit passed (${result.summary.tools} tools, ${result.summary.resources} resources, ${result.summary.prompts} prompts)`
|
|
1252
|
+
: `❌ Public surface audit failed (${result.failures.length} failure${result.failures.length === 1 ? "" : "s"})`,
|
|
1253
|
+
`Report: ${result.report_path}`,
|
|
1254
|
+
`Events: ${result.summary.emitted_events}`,
|
|
1255
|
+
...(result.failures.slice(0, 12).map((entry) => `- ${entry}`)),
|
|
1256
|
+
...(result.warnings.slice(0, 12).map((entry) => `- warning: ${entry}`)),
|
|
1257
|
+
].join("\n"),
|
|
1258
|
+
},
|
|
1259
|
+
],
|
|
1260
|
+
};
|
|
1261
|
+
});
|
|
1262
|
+
// ── Execute Gates (manifest-driven gate runner) ───────────────────
|
|
1263
|
+
server.tool("execute_gates", "Run quality gates from agent-state/MODULES/gates/*.json manifests (single source of truth)", {
|
|
1264
|
+
gate_ids: z
|
|
1265
|
+
.array(z.string())
|
|
1266
|
+
.optional()
|
|
1267
|
+
.describe("Specific gate IDs to run (e.g. ['gate-correctness']). Omit to run all registered gates."),
|
|
1268
|
+
review_mode: z
|
|
1269
|
+
.enum(["skeptic_adversarial"])
|
|
1270
|
+
.optional()
|
|
1271
|
+
.describe("Optional skeptic review overlay that keeps only surviving findings actionable."),
|
|
1272
|
+
review_focus: z
|
|
1273
|
+
.string()
|
|
1274
|
+
.optional()
|
|
1275
|
+
.describe("Optional short focus string persisted with skeptic adversarial review evidence."),
|
|
1276
|
+
}, async ({ gate_ids, review_mode, review_focus }) => {
|
|
1277
|
+
const gatesDir = wsPath("agent-state", "MODULES", "gates");
|
|
1278
|
+
if (!existsSync(gatesDir)) {
|
|
1279
|
+
return {
|
|
1280
|
+
content: [
|
|
1281
|
+
{
|
|
1282
|
+
type: "text",
|
|
1283
|
+
text: "❌ Gates directory not found: agent-state/MODULES/gates/",
|
|
1284
|
+
},
|
|
1285
|
+
],
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
const allGates = readGateManifests(gatesDir);
|
|
1289
|
+
// Filter to requested gates (or run all)
|
|
1290
|
+
const targets = gate_ids
|
|
1291
|
+
? allGates.filter((g) => gate_ids.includes(g.id))
|
|
1292
|
+
: allGates;
|
|
1293
|
+
if (targets.length === 0) {
|
|
1294
|
+
return {
|
|
1295
|
+
content: [
|
|
1296
|
+
{
|
|
1297
|
+
type: "text",
|
|
1298
|
+
text: `❌ No matching gates found. Available: ${allGates.map((g) => g.id).join(", ")}`,
|
|
1299
|
+
},
|
|
1300
|
+
],
|
|
1301
|
+
};
|
|
1302
|
+
}
|
|
1303
|
+
const results = evaluateGateTargets(targets);
|
|
1304
|
+
const passed = results.filter((r) => r.ok).length;
|
|
1305
|
+
const failed = results.filter((r) => !r.ok).length;
|
|
1306
|
+
const review = review_mode === "skeptic_adversarial"
|
|
1307
|
+
? buildAdversarialReview(results, review_focus)
|
|
1308
|
+
: undefined;
|
|
1309
|
+
const evidence = review_mode === "skeptic_adversarial" && review
|
|
1310
|
+
? await appendEvidenceLogEntrySafe(review)
|
|
1311
|
+
: undefined;
|
|
1312
|
+
const blockingFailures = review ? review.summary.confirmed_count : failed;
|
|
1313
|
+
const allOk = blockingFailures === 0;
|
|
1314
|
+
await appendStatusEventSafe({
|
|
1315
|
+
source_module: "capability-framework",
|
|
1316
|
+
event_type: "GATES_EXECUTED",
|
|
1317
|
+
status: allOk ? "pass" : "fail",
|
|
1318
|
+
summary: review
|
|
1319
|
+
? `Gates executed with skeptic review: ${passed}/${results.length} passed, ${review.summary.confirmed_count} confirmed findings`
|
|
1320
|
+
: `Gates executed: ${passed}/${results.length} passed`,
|
|
1321
|
+
payload: {
|
|
1322
|
+
gates_run: results.map((r) => r.id),
|
|
1323
|
+
gate_results: results.map((r) => ({
|
|
1324
|
+
id: r.id,
|
|
1325
|
+
status: r.ok ? "pass" : "fail",
|
|
1326
|
+
detail: r.detail,
|
|
1327
|
+
})),
|
|
1328
|
+
passed,
|
|
1329
|
+
failed,
|
|
1330
|
+
evidence_ref: evidence?.evidenceRef ?? "agent-state/MODULES/gates/",
|
|
1331
|
+
...(review
|
|
1332
|
+
? {
|
|
1333
|
+
review: {
|
|
1334
|
+
mode: review.mode,
|
|
1335
|
+
focus: review.focus,
|
|
1336
|
+
candidate_count: review.summary.candidate_count,
|
|
1337
|
+
disproved_count: review.summary.disproved_count,
|
|
1338
|
+
confirmed_count: review.summary.confirmed_count,
|
|
1339
|
+
actionable_gate_ids: review.summary.actionable_gate_ids,
|
|
1340
|
+
candidates: review.candidates,
|
|
1341
|
+
disproved: review.disproved,
|
|
1342
|
+
confirmed: review.confirmed,
|
|
1343
|
+
evidence_ref: evidence?.evidenceRef,
|
|
1344
|
+
},
|
|
1345
|
+
}
|
|
1346
|
+
: {}),
|
|
1347
|
+
},
|
|
1348
|
+
objective_id: "gate-execution",
|
|
1349
|
+
});
|
|
1350
|
+
const ledger = await appendRunLedgerEntrySafe({
|
|
1351
|
+
tool: "execute_gates",
|
|
1352
|
+
category: allOk ? "info" : "regression",
|
|
1353
|
+
message: review
|
|
1354
|
+
? `Gate execution with skeptic review: ${review.summary.confirmed_count} confirmed findings`
|
|
1355
|
+
: `Gate execution: ${passed}/${results.length} passed`,
|
|
1356
|
+
artifacts: [
|
|
1357
|
+
...results.map((r) => `agent-state/MODULES/gates/${r.id}.json`),
|
|
1358
|
+
...(evidence ? ["agent-state/EVIDENCE_LOG.md"] : []),
|
|
1359
|
+
],
|
|
1360
|
+
metadata: {
|
|
1361
|
+
passed,
|
|
1362
|
+
failed,
|
|
1363
|
+
gate_ids: results.map((r) => r.id),
|
|
1364
|
+
...(review
|
|
1365
|
+
? {
|
|
1366
|
+
review_mode: review.mode,
|
|
1367
|
+
review_focus: review.focus,
|
|
1368
|
+
candidate_count: review.summary.candidate_count,
|
|
1369
|
+
disproved_count: review.summary.disproved_count,
|
|
1370
|
+
confirmed_count: review.summary.confirmed_count,
|
|
1371
|
+
actionable_gate_ids: review.summary.actionable_gate_ids,
|
|
1372
|
+
evidence_ref: evidence?.evidenceRef,
|
|
1373
|
+
}
|
|
1374
|
+
: {}),
|
|
1375
|
+
},
|
|
1376
|
+
});
|
|
1377
|
+
return {
|
|
1378
|
+
content: [
|
|
1379
|
+
{
|
|
1380
|
+
type: "text",
|
|
1381
|
+
text: [
|
|
1382
|
+
review
|
|
1383
|
+
? allOk
|
|
1384
|
+
? `✅ Skeptic adversarial review cleared: ${review.summary.confirmed_count} confirmed findings`
|
|
1385
|
+
: `❌ Skeptic adversarial review found ${review.summary.confirmed_count} confirmed finding${review.summary.confirmed_count === 1 ? "" : "s"}`
|
|
1386
|
+
: allOk
|
|
1387
|
+
? `✅ All gates passed: ${passed}/${results.length}`
|
|
1388
|
+
: `❌ Gate failures: ${failed}/${results.length} failed`,
|
|
1389
|
+
`Run ledger: ${ledger.path} (${ledger.entry.id})`,
|
|
1390
|
+
...(evidence ? [`Evidence: ${evidence.path} (${evidence.evidenceRef})`] : []),
|
|
1391
|
+
"",
|
|
1392
|
+
...(review
|
|
1393
|
+
? [
|
|
1394
|
+
`Review mode: ${review.mode}`,
|
|
1395
|
+
...(review.focus ? [`Review focus: ${review.focus}`] : []),
|
|
1396
|
+
`- bug-hunter candidates: ${review.summary.candidate_count}`,
|
|
1397
|
+
`- disproved candidates: ${review.summary.disproved_count}`,
|
|
1398
|
+
`- confirmed findings: ${review.summary.confirmed_count}`,
|
|
1399
|
+
...review.disproved.map((finding) => `- disproved ${finding.gate_id}: ${finding.reason ?? "candidate rejected"}`),
|
|
1400
|
+
...review.confirmed.map((finding) => {
|
|
1401
|
+
const route = finding.route_hint ? ` (route ${finding.route_hint})` : "";
|
|
1402
|
+
return `- confirmed ${finding.gate_id}: ${finding.detail}${route}`;
|
|
1403
|
+
}),
|
|
1404
|
+
"",
|
|
1405
|
+
]
|
|
1406
|
+
: []),
|
|
1407
|
+
...results.map((r) => `- ${r.ok ? "✅" : "❌"} ${r.id} [${r.type}]: ${r.detail}`),
|
|
1408
|
+
].join("\n"),
|
|
1409
|
+
},
|
|
1410
|
+
],
|
|
1411
|
+
};
|
|
1412
|
+
});
|
|
1413
|
+
}
|
|
1414
|
+
//# sourceMappingURL=tools-framework.js.map
|