@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
package/dist/schemas.js
ADDED
|
@@ -0,0 +1,830 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { isAbsolute, resolve } from "node:path";
|
|
4
|
+
import { isInside, mapAceWorkspaceRelativePath } from "./helpers.js";
|
|
5
|
+
const NON_EMPTY = z.string().min(1);
|
|
6
|
+
const SHA256 = /^sha256:[a-f0-9]{64}$/;
|
|
7
|
+
const MODULE_ID = /^(capability|agent)-[a-z0-9-]+$/;
|
|
8
|
+
const REQUIRED_PROVENANCE_FIELDS = [
|
|
9
|
+
"artifact_id",
|
|
10
|
+
"artifact_path",
|
|
11
|
+
"producer_module",
|
|
12
|
+
"spec_version",
|
|
13
|
+
"req_ids",
|
|
14
|
+
"checksum",
|
|
15
|
+
"confidence_level",
|
|
16
|
+
"evidence_ref",
|
|
17
|
+
"timestamp",
|
|
18
|
+
];
|
|
19
|
+
const swarmHandoffSchema = z
|
|
20
|
+
.object({
|
|
21
|
+
handoff_id: NON_EMPTY,
|
|
22
|
+
timestamp_utc: z.string().datetime({ offset: true }),
|
|
23
|
+
router: z
|
|
24
|
+
.object({
|
|
25
|
+
from: NON_EMPTY,
|
|
26
|
+
via: NON_EMPTY,
|
|
27
|
+
to: NON_EMPTY,
|
|
28
|
+
})
|
|
29
|
+
.strict(),
|
|
30
|
+
task: z
|
|
31
|
+
.object({
|
|
32
|
+
title: NON_EMPTY,
|
|
33
|
+
type: z.enum(["venture", "ux", "engineering", "mixed"]),
|
|
34
|
+
priority: z.enum(["P0", "P1", "P2"]),
|
|
35
|
+
owner: NON_EMPTY,
|
|
36
|
+
depends_on: z.array(z.string()),
|
|
37
|
+
scope: NON_EMPTY,
|
|
38
|
+
})
|
|
39
|
+
.strict(),
|
|
40
|
+
context: z
|
|
41
|
+
.object({
|
|
42
|
+
business_requirement: z.string(),
|
|
43
|
+
design_constraint: z.string(),
|
|
44
|
+
engineering_constraint: z.string(),
|
|
45
|
+
directive: NON_EMPTY,
|
|
46
|
+
})
|
|
47
|
+
.strict(),
|
|
48
|
+
acceptance_criteria: z.array(NON_EMPTY).min(1),
|
|
49
|
+
deliverables: z.array(z.string()),
|
|
50
|
+
verification: z
|
|
51
|
+
.object({
|
|
52
|
+
required_evidence: z.array(NON_EMPTY).min(1),
|
|
53
|
+
review_check: NON_EMPTY,
|
|
54
|
+
status: z.enum(["pending", "in_progress", "pass", "fail"]),
|
|
55
|
+
})
|
|
56
|
+
.strict(),
|
|
57
|
+
risks: z.array(z.string()),
|
|
58
|
+
open_questions: z.array(z.string()),
|
|
59
|
+
lessons_hook: z
|
|
60
|
+
.object({
|
|
61
|
+
on_correction_update: NON_EMPTY,
|
|
62
|
+
rule_format: NON_EMPTY,
|
|
63
|
+
})
|
|
64
|
+
.strict(),
|
|
65
|
+
return_payload_contract: z
|
|
66
|
+
.object({
|
|
67
|
+
must_include: z.array(NON_EMPTY).min(1),
|
|
68
|
+
})
|
|
69
|
+
.strict(),
|
|
70
|
+
})
|
|
71
|
+
.strict();
|
|
72
|
+
const agentStateHandoffSchema = z
|
|
73
|
+
.object({
|
|
74
|
+
meta: z
|
|
75
|
+
.object({
|
|
76
|
+
timestamp: z.string().datetime({ offset: true }),
|
|
77
|
+
iteration: z.number().int().min(1),
|
|
78
|
+
session_id: NON_EMPTY,
|
|
79
|
+
log_commit: z.string().regex(SHA256),
|
|
80
|
+
})
|
|
81
|
+
.strict(),
|
|
82
|
+
transition: z
|
|
83
|
+
.object({
|
|
84
|
+
from: z.string().regex(MODULE_ID),
|
|
85
|
+
to: z.string().regex(MODULE_ID),
|
|
86
|
+
status: z.enum(["READY", "READY_FOR_REVIEW", "BLOCKED", "DONE"]),
|
|
87
|
+
reason: NON_EMPTY,
|
|
88
|
+
})
|
|
89
|
+
.strict(),
|
|
90
|
+
payload: z
|
|
91
|
+
.object({
|
|
92
|
+
primary_artifact: NON_EMPTY,
|
|
93
|
+
interface_contract: NON_EMPTY,
|
|
94
|
+
evidence_pointer: NON_EMPTY,
|
|
95
|
+
known_issues: z.array(z.string()),
|
|
96
|
+
})
|
|
97
|
+
.strict(),
|
|
98
|
+
integrity: z
|
|
99
|
+
.object({
|
|
100
|
+
checksum: z.string().regex(SHA256),
|
|
101
|
+
file_count: z.number().int().min(0),
|
|
102
|
+
})
|
|
103
|
+
.strict(),
|
|
104
|
+
})
|
|
105
|
+
.strict();
|
|
106
|
+
const statusEventSchema = z
|
|
107
|
+
.object({
|
|
108
|
+
schema_version: z.literal("1.0.0"),
|
|
109
|
+
event_id: NON_EMPTY,
|
|
110
|
+
trace_id: NON_EMPTY,
|
|
111
|
+
timestamp: z.string().datetime({ offset: true }),
|
|
112
|
+
source_module: z.string().regex(MODULE_ID),
|
|
113
|
+
event_type: NON_EMPTY,
|
|
114
|
+
status: z.enum(["started", "in_progress", "pass", "fail", "blocked", "done"]),
|
|
115
|
+
objective_id: z.string().optional(),
|
|
116
|
+
decision_id: z.string().optional(),
|
|
117
|
+
payload: z
|
|
118
|
+
.object({
|
|
119
|
+
summary: NON_EMPTY,
|
|
120
|
+
gate_id: z.string().optional(),
|
|
121
|
+
evidence_ref: z.string().optional(),
|
|
122
|
+
artifact_delta: z.array(z.string()).optional(),
|
|
123
|
+
})
|
|
124
|
+
.passthrough(),
|
|
125
|
+
})
|
|
126
|
+
.strict();
|
|
127
|
+
/**
|
|
128
|
+
* Stricter schema for provenance-critical events: objective_id or decision_id
|
|
129
|
+
* or evidence_ref MUST be present (fail-closed autonomy gate).
|
|
130
|
+
*/
|
|
131
|
+
const provenanceCriticalEventSchema = statusEventSchema
|
|
132
|
+
.refine((ev) => {
|
|
133
|
+
const hasObj = typeof ev.objective_id === "string" && ev.objective_id.length > 0;
|
|
134
|
+
const hasDec = typeof ev.decision_id === "string" && ev.decision_id.length > 0;
|
|
135
|
+
const hasEv = typeof ev.payload.evidence_ref === "string" && ev.payload.evidence_ref.length > 0;
|
|
136
|
+
return hasObj || hasDec || hasEv;
|
|
137
|
+
}, {
|
|
138
|
+
message: "Provenance-critical event MUST include at least one of: objective_id, decision_id, or payload.evidence_ref",
|
|
139
|
+
});
|
|
140
|
+
const artifactManifestEntrySchema = z
|
|
141
|
+
.object({
|
|
142
|
+
artifact_id: z.string().min(4),
|
|
143
|
+
artifact_path: NON_EMPTY,
|
|
144
|
+
producer_module: z.string().regex(MODULE_ID),
|
|
145
|
+
spec_version: NON_EMPTY,
|
|
146
|
+
req_ids: z.array(NON_EMPTY).min(1),
|
|
147
|
+
timestamp: z.string().datetime({ offset: true }),
|
|
148
|
+
checksum: z.string().regex(SHA256),
|
|
149
|
+
confidence_level: z.enum(["low", "medium", "high", "WIP", "Draft", "Verified"]),
|
|
150
|
+
evidence_ref: NON_EMPTY,
|
|
151
|
+
dependencies: z.array(z.string()).optional(),
|
|
152
|
+
evidence_refs: z.array(NON_EMPTY).min(1).optional(),
|
|
153
|
+
})
|
|
154
|
+
.strict()
|
|
155
|
+
.superRefine((entry, ctx) => {
|
|
156
|
+
if (entry.evidence_refs && !entry.evidence_refs.includes(entry.evidence_ref)) {
|
|
157
|
+
ctx.addIssue({
|
|
158
|
+
code: z.ZodIssueCode.custom,
|
|
159
|
+
path: ["evidence_refs"],
|
|
160
|
+
message: "evidence_refs must include evidence_ref when provided",
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
const artifactManifestFileSchema = z
|
|
165
|
+
.object({
|
|
166
|
+
schema_version: z.literal("1.1.0"),
|
|
167
|
+
updated_at: z.string().datetime({ offset: true }),
|
|
168
|
+
artifacts: z.array(artifactManifestEntrySchema),
|
|
169
|
+
})
|
|
170
|
+
.strict();
|
|
171
|
+
const workspaceHookStateSchema = z
|
|
172
|
+
.object({
|
|
173
|
+
status: z.enum(["not_run", "ok", "failed"]),
|
|
174
|
+
detail: z.string().optional(),
|
|
175
|
+
})
|
|
176
|
+
.strict();
|
|
177
|
+
const workspaceSessionRecordSchema = z
|
|
178
|
+
.object({
|
|
179
|
+
session_id: NON_EMPTY,
|
|
180
|
+
workspace_path: NON_EMPTY,
|
|
181
|
+
root_path: NON_EMPTY,
|
|
182
|
+
status: z.enum(["active", "archived", "removed", "failed"]),
|
|
183
|
+
source: z.enum(["manual", "executor", "test"]),
|
|
184
|
+
objective_id: z.string().optional(),
|
|
185
|
+
tracker_item_id: z.string().optional(),
|
|
186
|
+
last_error: z.string().optional(),
|
|
187
|
+
created_at: z.string().datetime({ offset: true }),
|
|
188
|
+
updated_at: z.string().datetime({ offset: true }),
|
|
189
|
+
hooks: z
|
|
190
|
+
.object({
|
|
191
|
+
after_create: workspaceHookStateSchema,
|
|
192
|
+
before_run: workspaceHookStateSchema,
|
|
193
|
+
after_run: workspaceHookStateSchema,
|
|
194
|
+
before_remove: workspaceHookStateSchema,
|
|
195
|
+
})
|
|
196
|
+
.strict(),
|
|
197
|
+
})
|
|
198
|
+
.strict();
|
|
199
|
+
const workspaceSessionRegistrySchema = z
|
|
200
|
+
.object({
|
|
201
|
+
version: z.literal(1),
|
|
202
|
+
updated_at: z.string().datetime({ offset: true }),
|
|
203
|
+
sessions: z.array(workspaceSessionRecordSchema),
|
|
204
|
+
})
|
|
205
|
+
.strict();
|
|
206
|
+
const trackerMetadataSchema = z.record(z.string(), z.unknown());
|
|
207
|
+
const trackerItemSchema = z
|
|
208
|
+
.object({
|
|
209
|
+
item_id: NON_EMPTY,
|
|
210
|
+
external_id: z.string().optional(),
|
|
211
|
+
title: NON_EMPTY,
|
|
212
|
+
body: z.string().optional(),
|
|
213
|
+
state: NON_EMPTY,
|
|
214
|
+
labels: z.array(z.string()),
|
|
215
|
+
assignee: z.string().optional(),
|
|
216
|
+
url: z.string().optional(),
|
|
217
|
+
updated_at: z.string().datetime({ offset: true }),
|
|
218
|
+
metadata: trackerMetadataSchema,
|
|
219
|
+
})
|
|
220
|
+
.strict();
|
|
221
|
+
const trackerCommentSchema = z
|
|
222
|
+
.object({
|
|
223
|
+
comment_id: NON_EMPTY,
|
|
224
|
+
item_id: NON_EMPTY,
|
|
225
|
+
body: NON_EMPTY,
|
|
226
|
+
author: NON_EMPTY,
|
|
227
|
+
created_at: z.string().datetime({ offset: true }),
|
|
228
|
+
metadata: trackerMetadataSchema,
|
|
229
|
+
})
|
|
230
|
+
.strict();
|
|
231
|
+
const trackerSnapshotSchema = z
|
|
232
|
+
.object({
|
|
233
|
+
version: z.literal(1),
|
|
234
|
+
adapter_kind: z.enum(["none", "memory", "external"]),
|
|
235
|
+
updated_at: z.string().datetime({ offset: true }),
|
|
236
|
+
items: z.array(trackerItemSchema),
|
|
237
|
+
comments: z.array(trackerCommentSchema),
|
|
238
|
+
})
|
|
239
|
+
.strict();
|
|
240
|
+
const runtimeToolSchemaScalarSchema = z.union([
|
|
241
|
+
z.string(),
|
|
242
|
+
z.number(),
|
|
243
|
+
z.boolean(),
|
|
244
|
+
z.null(),
|
|
245
|
+
]);
|
|
246
|
+
const runtimeToolSchemaNodeSchema = z.lazy(() => z
|
|
247
|
+
.object({
|
|
248
|
+
type: z.enum(["object", "array", "string", "number", "integer", "boolean", "null"]),
|
|
249
|
+
description: z.string().optional(),
|
|
250
|
+
enum: z.array(runtimeToolSchemaScalarSchema).optional(),
|
|
251
|
+
properties: z.record(z.string(), runtimeToolSchemaNodeSchema).optional(),
|
|
252
|
+
required: z.array(z.string()).optional(),
|
|
253
|
+
additionalProperties: z.boolean().optional(),
|
|
254
|
+
items: runtimeToolSchemaNodeSchema.optional(),
|
|
255
|
+
})
|
|
256
|
+
.strict()
|
|
257
|
+
.superRefine((value, ctx) => {
|
|
258
|
+
if (value.type === "object" && value.items) {
|
|
259
|
+
ctx.addIssue({
|
|
260
|
+
code: z.ZodIssueCode.custom,
|
|
261
|
+
path: ["items"],
|
|
262
|
+
message: "object schemas must not define items",
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
if (value.type !== "object" && (value.properties || value.required)) {
|
|
266
|
+
ctx.addIssue({
|
|
267
|
+
code: z.ZodIssueCode.custom,
|
|
268
|
+
path: ["properties"],
|
|
269
|
+
message: "only object schemas may define properties or required",
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
if (value.type === "array" && !value.items) {
|
|
273
|
+
ctx.addIssue({
|
|
274
|
+
code: z.ZodIssueCode.custom,
|
|
275
|
+
path: ["items"],
|
|
276
|
+
message: "array schemas must define items",
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
if (value.type !== "array" && value.items) {
|
|
280
|
+
ctx.addIssue({
|
|
281
|
+
code: z.ZodIssueCode.custom,
|
|
282
|
+
path: ["items"],
|
|
283
|
+
message: "only array schemas may define items",
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}));
|
|
287
|
+
const runtimeToolExecutorSchema = z
|
|
288
|
+
.object({
|
|
289
|
+
command: NON_EMPTY,
|
|
290
|
+
cwd: z.string().optional(),
|
|
291
|
+
timeout_ms: z.number().int().positive().optional(),
|
|
292
|
+
env: z.record(z.string(), z.string()).optional(),
|
|
293
|
+
})
|
|
294
|
+
.strict();
|
|
295
|
+
const runtimeToolSpecSchema = z
|
|
296
|
+
.object({
|
|
297
|
+
name: NON_EMPTY,
|
|
298
|
+
description: NON_EMPTY,
|
|
299
|
+
input_schema: runtimeToolSchemaNodeSchema,
|
|
300
|
+
success_schema: runtimeToolSchemaNodeSchema.optional(),
|
|
301
|
+
failure_schema: runtimeToolSchemaNodeSchema.optional(),
|
|
302
|
+
executor: runtimeToolExecutorSchema,
|
|
303
|
+
})
|
|
304
|
+
.strict();
|
|
305
|
+
const runtimeToolSpecRegistrySchema = z
|
|
306
|
+
.object({
|
|
307
|
+
version: z.literal(1),
|
|
308
|
+
updated_at: z.string().datetime({ offset: true }),
|
|
309
|
+
tools: z.array(runtimeToolSpecSchema),
|
|
310
|
+
})
|
|
311
|
+
.strict()
|
|
312
|
+
.superRefine((value, ctx) => {
|
|
313
|
+
const names = new Set();
|
|
314
|
+
for (const [index, tool] of value.tools.entries()) {
|
|
315
|
+
if (names.has(tool.name)) {
|
|
316
|
+
ctx.addIssue({
|
|
317
|
+
code: z.ZodIssueCode.custom,
|
|
318
|
+
path: ["tools", index, "name"],
|
|
319
|
+
message: `duplicate tool name "${tool.name}"`,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
names.add(tool.name);
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
const unattendedToolCallRecordSchema = z
|
|
326
|
+
.object({
|
|
327
|
+
tool_name: NON_EMPTY,
|
|
328
|
+
ok: z.boolean(),
|
|
329
|
+
summary: NON_EMPTY,
|
|
330
|
+
request_path: NON_EMPTY,
|
|
331
|
+
response_path: NON_EMPTY,
|
|
332
|
+
started_at: z.string().datetime({ offset: true }),
|
|
333
|
+
ended_at: z.string().datetime({ offset: true }),
|
|
334
|
+
output: z.unknown().optional(),
|
|
335
|
+
error: z.unknown().optional(),
|
|
336
|
+
validation_errors: z.array(z.string()).optional(),
|
|
337
|
+
})
|
|
338
|
+
.strict();
|
|
339
|
+
const unattendedTurnRecordSchema = z
|
|
340
|
+
.object({
|
|
341
|
+
turn_number: z.number().int().positive(),
|
|
342
|
+
task: NON_EMPTY,
|
|
343
|
+
started_at: z.string().datetime({ offset: true }),
|
|
344
|
+
ended_at: z.string().datetime({ offset: true }),
|
|
345
|
+
status: z.enum(["completed", "failed", "blocked", "stopped"]),
|
|
346
|
+
response_status: z.enum(["continue", "done", "blocked", "failed"]),
|
|
347
|
+
summary: NON_EMPTY,
|
|
348
|
+
prompt_path: NON_EMPTY,
|
|
349
|
+
request_path: NON_EMPTY,
|
|
350
|
+
response_path: NON_EMPTY,
|
|
351
|
+
exit_code: z.number().int().nullable(),
|
|
352
|
+
stdout: z.string(),
|
|
353
|
+
stderr: z.string(),
|
|
354
|
+
tool_calls: z.array(unattendedToolCallRecordSchema),
|
|
355
|
+
})
|
|
356
|
+
.strict();
|
|
357
|
+
const runtimeExecutorSessionRecordSchema = z
|
|
358
|
+
.object({
|
|
359
|
+
session_id: NON_EMPTY,
|
|
360
|
+
status: z.enum(["starting", "running", "completed", "failed", "blocked", "stopped"]),
|
|
361
|
+
task: NON_EMPTY,
|
|
362
|
+
current_task: NON_EMPTY,
|
|
363
|
+
runtime_profile_path: NON_EMPTY,
|
|
364
|
+
workspace_session_id: NON_EMPTY,
|
|
365
|
+
workspace_path: NON_EMPTY,
|
|
366
|
+
objective_id: z.string().optional(),
|
|
367
|
+
tracker_item_id: z.string().optional(),
|
|
368
|
+
command: NON_EMPTY,
|
|
369
|
+
max_turns: z.number().int().positive(),
|
|
370
|
+
turn_timeout_ms: z.number().int().positive(),
|
|
371
|
+
turn_count: z.number().int().min(0),
|
|
372
|
+
created_at: z.string().datetime({ offset: true }),
|
|
373
|
+
updated_at: z.string().datetime({ offset: true }),
|
|
374
|
+
started_at: z.string().datetime({ offset: true }).optional(),
|
|
375
|
+
ended_at: z.string().datetime({ offset: true }).optional(),
|
|
376
|
+
result_summary: z.string().optional(),
|
|
377
|
+
last_error: z.string().optional(),
|
|
378
|
+
cleanup_error: z.string().optional(),
|
|
379
|
+
workspace_cleanup_status: z.enum(["pending", "removed", "archived", "failed"]),
|
|
380
|
+
turns: z.array(unattendedTurnRecordSchema),
|
|
381
|
+
})
|
|
382
|
+
.strict();
|
|
383
|
+
const runtimeExecutorSessionRegistrySchema = z
|
|
384
|
+
.object({
|
|
385
|
+
version: z.literal(1),
|
|
386
|
+
updated_at: z.string().datetime({ offset: true }),
|
|
387
|
+
sessions: z.array(runtimeExecutorSessionRecordSchema),
|
|
388
|
+
})
|
|
389
|
+
.strict();
|
|
390
|
+
const vericifyProcessPostSchema = z
|
|
391
|
+
.object({
|
|
392
|
+
process_post_id: NON_EMPTY,
|
|
393
|
+
run_id: NON_EMPTY,
|
|
394
|
+
branch_id: z.string().optional(),
|
|
395
|
+
lane_id: z.string().optional(),
|
|
396
|
+
agent_id: NON_EMPTY,
|
|
397
|
+
kind: z.enum(["intent", "progress", "blocker", "handoff_note", "stale_ack", "completion"]),
|
|
398
|
+
summary: NON_EMPTY,
|
|
399
|
+
tool_refs: z.array(z.string()),
|
|
400
|
+
evidence_refs: z.array(z.string()),
|
|
401
|
+
checkpoint_ref: z.string().optional(),
|
|
402
|
+
timestamp: z.string().datetime({ offset: true }),
|
|
403
|
+
})
|
|
404
|
+
.strict();
|
|
405
|
+
const vericifyProcessPostLogSchema = z
|
|
406
|
+
.object({
|
|
407
|
+
version: z.literal(1),
|
|
408
|
+
updated_at: z.string().datetime({ offset: true }),
|
|
409
|
+
posts: z.array(vericifyProcessPostSchema),
|
|
410
|
+
})
|
|
411
|
+
.strict();
|
|
412
|
+
const vericifyBridgeSourceStateSchema = z
|
|
413
|
+
.object({
|
|
414
|
+
path: NON_EMPTY,
|
|
415
|
+
exists: z.boolean(),
|
|
416
|
+
updated_at: z.string().datetime({ offset: true }).optional(),
|
|
417
|
+
record_count: z.number().int().min(0),
|
|
418
|
+
summary: NON_EMPTY,
|
|
419
|
+
})
|
|
420
|
+
.strict();
|
|
421
|
+
const vericifyBridgeActiveRunRefSchema = z
|
|
422
|
+
.object({
|
|
423
|
+
run_id: NON_EMPTY,
|
|
424
|
+
branch_id: NON_EMPTY,
|
|
425
|
+
lane_id: NON_EMPTY,
|
|
426
|
+
session_id: NON_EMPTY,
|
|
427
|
+
status: NON_EMPTY,
|
|
428
|
+
objective_id: z.string().optional(),
|
|
429
|
+
tracker_item_id: z.string().optional(),
|
|
430
|
+
workspace_path: NON_EMPTY,
|
|
431
|
+
updated_at: z.string().datetime({ offset: true }),
|
|
432
|
+
})
|
|
433
|
+
.strict();
|
|
434
|
+
const vericifyBridgeSnapshotSchema = z
|
|
435
|
+
.object({
|
|
436
|
+
version: z.literal(1),
|
|
437
|
+
generated_at: z.string().datetime({ offset: true }),
|
|
438
|
+
bridge_enabled: z.boolean(),
|
|
439
|
+
workspace_root: NON_EMPTY,
|
|
440
|
+
runtime_profile_path: NON_EMPTY,
|
|
441
|
+
bridge_path: NON_EMPTY,
|
|
442
|
+
process_post_path: NON_EMPTY,
|
|
443
|
+
sources: z
|
|
444
|
+
.object({
|
|
445
|
+
handoff_registry: vericifyBridgeSourceStateSchema,
|
|
446
|
+
todo_state: vericifyBridgeSourceStateSchema,
|
|
447
|
+
run_ledger: vericifyBridgeSourceStateSchema,
|
|
448
|
+
status_events: vericifyBridgeSourceStateSchema,
|
|
449
|
+
runtime_workspaces: vericifyBridgeSourceStateSchema,
|
|
450
|
+
runtime_executor_sessions: vericifyBridgeSourceStateSchema,
|
|
451
|
+
tracker_snapshot: vericifyBridgeSourceStateSchema,
|
|
452
|
+
process_posts: vericifyBridgeSourceStateSchema,
|
|
453
|
+
})
|
|
454
|
+
.strict(),
|
|
455
|
+
active_run_refs: z.array(vericifyBridgeActiveRunRefSchema),
|
|
456
|
+
})
|
|
457
|
+
.strict();
|
|
458
|
+
/**
|
|
459
|
+
* Event types that MUST carry provenance fields (autonomy gate – fail-closed).
|
|
460
|
+
* Exported so status-events.ts can use the same canonical set.
|
|
461
|
+
*/
|
|
462
|
+
export const PROVENANCE_CRITICAL_EVENT_TYPES = new Set([
|
|
463
|
+
"SAFE_EDIT_COMPLETED",
|
|
464
|
+
"SAFE_EDIT_FAILED",
|
|
465
|
+
"FRAMEWORK_VALIDATED",
|
|
466
|
+
"GIT_COMMITTED",
|
|
467
|
+
"CIRCUIT_BREAKER_OPENED",
|
|
468
|
+
"CIRCUIT_BREAKER_CLOSED",
|
|
469
|
+
"DISCOVERY_INDEX_READY",
|
|
470
|
+
]);
|
|
471
|
+
function formatZodErrors(error) {
|
|
472
|
+
return error.issues.map((issue) => {
|
|
473
|
+
const path = issue.path.length > 0 ? issue.path.join(".") : "(root)";
|
|
474
|
+
return `${path}: ${issue.message}`;
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
function validateWithSchema(schemaName, schema, payload) {
|
|
478
|
+
const result = schema.safeParse(payload);
|
|
479
|
+
if (result.success)
|
|
480
|
+
return { ok: true, schema: schemaName };
|
|
481
|
+
return {
|
|
482
|
+
ok: false,
|
|
483
|
+
schema: schemaName,
|
|
484
|
+
errors: formatZodErrors(result.error),
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
export function validateSwarmHandoffPayload(payload) {
|
|
488
|
+
return validateWithSchema("swarm-handoff@1.0.0", swarmHandoffSchema, payload);
|
|
489
|
+
}
|
|
490
|
+
export function validateAgentStateHandoffPayload(payload) {
|
|
491
|
+
return validateWithSchema("agent-state-handoff@1.0.0", agentStateHandoffSchema, payload);
|
|
492
|
+
}
|
|
493
|
+
export function validateArtifactManifestPayload(payload) {
|
|
494
|
+
const fileValidation = validateWithSchema("artifact-manifest@1.1.0", artifactManifestFileSchema, payload);
|
|
495
|
+
if (fileValidation.ok)
|
|
496
|
+
return fileValidation;
|
|
497
|
+
const entryValidation = validateWithSchema("artifact-manifest-entry@1.1.0", artifactManifestEntrySchema, payload);
|
|
498
|
+
if (entryValidation.ok)
|
|
499
|
+
return entryValidation;
|
|
500
|
+
return {
|
|
501
|
+
ok: false,
|
|
502
|
+
schema: "artifact-manifest@1.1.0",
|
|
503
|
+
errors: [
|
|
504
|
+
...fileValidation.errors.map((error) => `[manifest] ${error}`),
|
|
505
|
+
...entryValidation.errors.map((error) => `[entry] ${error}`),
|
|
506
|
+
],
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
export function validateWorkspaceSessionRegistryPayload(payload) {
|
|
510
|
+
return validateWithSchema("workspace-session-registry@1.0.0", workspaceSessionRegistrySchema, payload);
|
|
511
|
+
}
|
|
512
|
+
export function validateTrackerSnapshotPayload(payload) {
|
|
513
|
+
return validateWithSchema("tracker-snapshot@1.0.0", trackerSnapshotSchema, payload);
|
|
514
|
+
}
|
|
515
|
+
export function validateRuntimeToolSpecRegistryPayload(payload) {
|
|
516
|
+
return validateWithSchema("runtime-tool-spec-registry@1.0.0", runtimeToolSpecRegistrySchema, payload);
|
|
517
|
+
}
|
|
518
|
+
export function validateRuntimeExecutorSessionRegistryPayload(payload) {
|
|
519
|
+
return validateWithSchema("runtime-executor-session-registry@1.0.0", runtimeExecutorSessionRegistrySchema, payload);
|
|
520
|
+
}
|
|
521
|
+
export function validateVericifyProcessPostLogPayload(payload) {
|
|
522
|
+
return validateWithSchema("vericify-process-post-log@1.0.0", vericifyProcessPostLogSchema, payload);
|
|
523
|
+
}
|
|
524
|
+
export function validateVericifyBridgeSnapshotPayload(payload) {
|
|
525
|
+
return validateWithSchema("vericify-bridge-snapshot@1.0.0", vericifyBridgeSnapshotSchema, payload);
|
|
526
|
+
}
|
|
527
|
+
export function validateStatusEventPayload(payload, options) {
|
|
528
|
+
if (options?.provenanceCritical) {
|
|
529
|
+
return validateWithSchema("status-event-provenance@1.0.0", provenanceCriticalEventSchema, payload);
|
|
530
|
+
}
|
|
531
|
+
return validateWithSchema("status-event@1.0.0", statusEventSchema, payload);
|
|
532
|
+
}
|
|
533
|
+
export function validateStatusEventsNdjsonContent(content) {
|
|
534
|
+
const lines = content
|
|
535
|
+
.split(/\r?\n/)
|
|
536
|
+
.map((line) => line.trim())
|
|
537
|
+
.filter(Boolean);
|
|
538
|
+
if (lines.length === 0) {
|
|
539
|
+
return {
|
|
540
|
+
ok: false,
|
|
541
|
+
schema: "status-event-ndjson@1.0.0",
|
|
542
|
+
errors: ["NDJSON content is empty"],
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
const errors = [];
|
|
546
|
+
lines.forEach((line, idx) => {
|
|
547
|
+
let parsed;
|
|
548
|
+
try {
|
|
549
|
+
parsed = JSON.parse(line);
|
|
550
|
+
}
|
|
551
|
+
catch {
|
|
552
|
+
errors.push(`line ${idx + 1}: invalid JSON`);
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
const validation = validateStatusEventPayload(parsed);
|
|
556
|
+
if (!validation.ok) {
|
|
557
|
+
errors.push(...validation.errors.map((error) => `line ${idx + 1}: ${error}`));
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
if (errors.length > 0) {
|
|
561
|
+
return {
|
|
562
|
+
ok: false,
|
|
563
|
+
schema: "status-event-ndjson@1.0.0",
|
|
564
|
+
errors,
|
|
565
|
+
};
|
|
566
|
+
}
|
|
567
|
+
return { ok: true, schema: "status-event-ndjson@1.0.0" };
|
|
568
|
+
}
|
|
569
|
+
export function validateTealConfigContent(content) {
|
|
570
|
+
const errors = [];
|
|
571
|
+
const fenceCount = (content.match(/```/g) ?? []).length;
|
|
572
|
+
const fencedBlocks = [...content.matchAll(/```([^\n]*)\n([\s\S]*?)```/g)];
|
|
573
|
+
if (fenceCount !== 2 || fencedBlocks.length !== 1) {
|
|
574
|
+
errors.push(`TEAL_CONFIG.md must contain exactly one fenced code block; found ${fencedBlocks.length}`);
|
|
575
|
+
}
|
|
576
|
+
const block = fencedBlocks[0];
|
|
577
|
+
if (block) {
|
|
578
|
+
const language = block[1].trim().toLowerCase();
|
|
579
|
+
const yamlBody = block[2].trim();
|
|
580
|
+
if (language !== "yaml") {
|
|
581
|
+
errors.push(`TEAL_CONFIG.md active config block must be fenced as \`\`\`yaml, found "${block[1].trim() || "(none)"}"`);
|
|
582
|
+
}
|
|
583
|
+
if (!yamlBody) {
|
|
584
|
+
errors.push("TEAL_CONFIG.md YAML block is empty");
|
|
585
|
+
}
|
|
586
|
+
else {
|
|
587
|
+
for (const section of ["modules", "pipelines"]) {
|
|
588
|
+
if (!new RegExp(`^\\s*${section}:`, "m").test(yamlBody)) {
|
|
589
|
+
errors.push(`TEAL_CONFIG.md YAML block is missing required top-level section "${section}:"`);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
if (errors.length > 0) {
|
|
595
|
+
return {
|
|
596
|
+
ok: false,
|
|
597
|
+
schema: "teal-config-markdown@1.0.0",
|
|
598
|
+
errors,
|
|
599
|
+
};
|
|
600
|
+
}
|
|
601
|
+
return { ok: true, schema: "teal-config-markdown@1.0.0" };
|
|
602
|
+
}
|
|
603
|
+
export function validateProvenanceLogContent(content) {
|
|
604
|
+
const errors = [];
|
|
605
|
+
const normalized = content.toLowerCase();
|
|
606
|
+
if (!content.trim()) {
|
|
607
|
+
errors.push("PROVENANCE_LOG.md is empty");
|
|
608
|
+
}
|
|
609
|
+
if (!normalized.includes("# provenance log")) {
|
|
610
|
+
errors.push('PROVENANCE_LOG.md must start with a "# PROVENANCE LOG" heading');
|
|
611
|
+
}
|
|
612
|
+
const missingFields = REQUIRED_PROVENANCE_FIELDS.filter((field) => !normalized.includes(field.toLowerCase()));
|
|
613
|
+
if (missingFields.length > 0) {
|
|
614
|
+
errors.push(`PROVENANCE_LOG.md is missing required provenance fields: ${missingFields.join(", ")}`);
|
|
615
|
+
}
|
|
616
|
+
if (errors.length > 0) {
|
|
617
|
+
return {
|
|
618
|
+
ok: false,
|
|
619
|
+
schema: "provenance-log-markdown@1.0.0",
|
|
620
|
+
errors,
|
|
621
|
+
};
|
|
622
|
+
}
|
|
623
|
+
return { ok: true, schema: "provenance-log-markdown@1.0.0" };
|
|
624
|
+
}
|
|
625
|
+
export function validateHandoffPayload(payload, mode = "auto") {
|
|
626
|
+
if (mode === "swarm")
|
|
627
|
+
return validateSwarmHandoffPayload(payload);
|
|
628
|
+
if (mode === "agent-state")
|
|
629
|
+
return validateAgentStateHandoffPayload(payload);
|
|
630
|
+
const swarm = validateSwarmHandoffPayload(payload);
|
|
631
|
+
if (swarm.ok)
|
|
632
|
+
return swarm;
|
|
633
|
+
const agentState = validateAgentStateHandoffPayload(payload);
|
|
634
|
+
if (agentState.ok)
|
|
635
|
+
return agentState;
|
|
636
|
+
return {
|
|
637
|
+
ok: false,
|
|
638
|
+
schema: "handoff-auto",
|
|
639
|
+
errors: [
|
|
640
|
+
...swarm.errors.map((error) => `[swarm] ${error}`),
|
|
641
|
+
...agentState.errors.map((error) => `[agent-state] ${error}`),
|
|
642
|
+
],
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
// ────────────────────────────────────────────────────────────────────
|
|
646
|
+
// Deep handoff lint — route legitimacy + evidence existence checks
|
|
647
|
+
// ────────────────────────────────────────────────────────────────────
|
|
648
|
+
/** Known legitimate ACE role prefixes (matches ROLE_ENUM in shared.ts). */
|
|
649
|
+
const KNOWN_ROLES = new Set([
|
|
650
|
+
"orchestrator", "vos", "ui", "coders", "astgrep", "skeptic",
|
|
651
|
+
"ops", "research", "spec", "builder", "qa", "docs",
|
|
652
|
+
"memory", "security", "observability", "eval", "release",
|
|
653
|
+
]);
|
|
654
|
+
function extractRole(agentLabel) {
|
|
655
|
+
return agentLabel.replace(/^ACE-/i, "").toLowerCase();
|
|
656
|
+
}
|
|
657
|
+
const HANDOFF_LINK_FALLBACK_ROOTS = [
|
|
658
|
+
"agent-state",
|
|
659
|
+
"global-state",
|
|
660
|
+
"tasks",
|
|
661
|
+
"venture-state",
|
|
662
|
+
"brand-state",
|
|
663
|
+
"business-state",
|
|
664
|
+
"engineering-state",
|
|
665
|
+
];
|
|
666
|
+
const ACE_HANDOFF_MANAGED_PREFIXES = [
|
|
667
|
+
"tasks",
|
|
668
|
+
"scripts",
|
|
669
|
+
".github",
|
|
670
|
+
".claude",
|
|
671
|
+
".cursor",
|
|
672
|
+
".vscode",
|
|
673
|
+
".mcp-config",
|
|
674
|
+
];
|
|
675
|
+
const ACE_HANDOFF_MANAGED_FILES = new Set([
|
|
676
|
+
"AGENTS.md",
|
|
677
|
+
"CLAUDE.md",
|
|
678
|
+
".cursorrules",
|
|
679
|
+
]);
|
|
680
|
+
function mapHandoffLinkWorkspaceRelativePath(relPath) {
|
|
681
|
+
const normalized = relPath.trim().replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
682
|
+
if (!normalized)
|
|
683
|
+
return normalized;
|
|
684
|
+
if (ACE_HANDOFF_MANAGED_FILES.has(normalized)) {
|
|
685
|
+
return `.agents/ACE/${normalized}`;
|
|
686
|
+
}
|
|
687
|
+
for (const prefix of ACE_HANDOFF_MANAGED_PREFIXES) {
|
|
688
|
+
if (normalized === prefix || normalized.startsWith(`${prefix}/`)) {
|
|
689
|
+
return `.agents/ACE/${normalized}`;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
return mapAceWorkspaceRelativePath(normalized);
|
|
693
|
+
}
|
|
694
|
+
function resolveLinkedWorkspacePath(workspaceRoot, filePath, preferredRoots = []) {
|
|
695
|
+
const normalized = filePath.trim().replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
696
|
+
if (!normalized)
|
|
697
|
+
return undefined;
|
|
698
|
+
if (isAbsolute(normalized)) {
|
|
699
|
+
return isInside(workspaceRoot, normalized) && existsSync(normalized)
|
|
700
|
+
? normalized
|
|
701
|
+
: undefined;
|
|
702
|
+
}
|
|
703
|
+
const candidates = new Set();
|
|
704
|
+
const pushCandidate = (candidate) => {
|
|
705
|
+
const cleaned = candidate.trim().replace(/\\/g, "/").replace(/^\.\/+/, "");
|
|
706
|
+
if (!cleaned)
|
|
707
|
+
return;
|
|
708
|
+
candidates.add(mapHandoffLinkWorkspaceRelativePath(cleaned));
|
|
709
|
+
};
|
|
710
|
+
pushCandidate(normalized);
|
|
711
|
+
if (!normalized.includes("/")) {
|
|
712
|
+
for (const root of [...preferredRoots, ...HANDOFF_LINK_FALLBACK_ROOTS]) {
|
|
713
|
+
pushCandidate(`${root}/${normalized}`);
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
for (const candidate of candidates) {
|
|
717
|
+
const absPath = resolve(workspaceRoot, candidate);
|
|
718
|
+
if (isInside(workspaceRoot, absPath) && existsSync(absPath)) {
|
|
719
|
+
return absPath;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
return undefined;
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Deep lint beyond schema validation:
|
|
726
|
+
* - Route legitimacy (from/to must be known roles)
|
|
727
|
+
* - Evidence freshness (context_pointers must reference existing files)
|
|
728
|
+
* - Acceptance criteria must be non-trivial
|
|
729
|
+
* - Required evidence array must be non-empty
|
|
730
|
+
*/
|
|
731
|
+
export function lintHandoffPayload(payload, workspaceRoot) {
|
|
732
|
+
const warnings = [];
|
|
733
|
+
const errors = [];
|
|
734
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
|
|
735
|
+
errors.push("Payload is not an object");
|
|
736
|
+
return { ok: false, warnings, errors };
|
|
737
|
+
}
|
|
738
|
+
const obj = payload;
|
|
739
|
+
// ── Route legitimacy ────────────────────────────────────────────
|
|
740
|
+
const router = obj.router;
|
|
741
|
+
if (router && typeof router === "object") {
|
|
742
|
+
for (const field of ["from", "to"]) {
|
|
743
|
+
const val = router[field];
|
|
744
|
+
if (typeof val === "string") {
|
|
745
|
+
const role = extractRole(val);
|
|
746
|
+
if (!KNOWN_ROLES.has(role)) {
|
|
747
|
+
errors.push(`router.${field} references unknown role: "${val}" (resolved: "${role}")`);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
// Self-routing check
|
|
752
|
+
if (typeof router.from === "string" &&
|
|
753
|
+
typeof router.to === "string" &&
|
|
754
|
+
extractRole(router.from) === extractRole(router.to)) {
|
|
755
|
+
warnings.push(`Self-routing detected: from and to resolve to same role "${extractRole(router.from)}"`);
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
// ── Transition (agent-state handoff) ────────────────────────────
|
|
759
|
+
const transition = obj.transition;
|
|
760
|
+
if (transition && typeof transition === "object") {
|
|
761
|
+
for (const field of ["from", "to"]) {
|
|
762
|
+
const val = transition[field];
|
|
763
|
+
if (typeof val === "string" && !/^(capability|agent)-[a-z0-9-]+$/.test(val)) {
|
|
764
|
+
errors.push(`transition.${field} doesn't match MODULE_ID pattern: "${val}"`);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
// ── Evidence / context pointer existence (HARD FAIL) ────────────
|
|
769
|
+
// Helper: extract file path from evidence pointers that may contain
|
|
770
|
+
// #anchor (including ISO timestamps like #2026-03-06T17:43:28Z) or
|
|
771
|
+
// :line suffixes. Naive split(":") would truncate timestamps.
|
|
772
|
+
function extractFilePath(pointer) {
|
|
773
|
+
// Strip #anchor first (handles #line, #section, #timestamp)
|
|
774
|
+
const hashIdx = pointer.indexOf("#");
|
|
775
|
+
const withoutAnchor = hashIdx >= 0 ? pointer.slice(0, hashIdx) : pointer;
|
|
776
|
+
// Now strip any trailing :line-number reference (only numeric after colon)
|
|
777
|
+
const stripped = withoutAnchor.replace(/:(\d+)$/, "");
|
|
778
|
+
return stripped.trim();
|
|
779
|
+
}
|
|
780
|
+
const context = obj.context;
|
|
781
|
+
if (context && typeof context === "object") {
|
|
782
|
+
for (const [key, val] of Object.entries(context)) {
|
|
783
|
+
if (typeof val !== "string" || !val.trim())
|
|
784
|
+
continue;
|
|
785
|
+
// Check if value looks like a file reference (contains path separators or common extensions)
|
|
786
|
+
if (/\.(md|json|ts|js|yaml|yml|toml|txt|ndjson)/.test(val) || val.includes("/")) {
|
|
787
|
+
const filePath = extractFilePath(val);
|
|
788
|
+
const absPath = resolveLinkedWorkspacePath(workspaceRoot, filePath);
|
|
789
|
+
if (!absPath) {
|
|
790
|
+
errors.push(`context.${key} references non-existent file: "${filePath}"`);
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
// ── Payload evidence pointer (agent-state handoffs) — HARD FAIL ─
|
|
796
|
+
const agentPayload = obj.payload;
|
|
797
|
+
if (agentPayload && typeof agentPayload === "object") {
|
|
798
|
+
const evidencePointer = agentPayload.evidence_pointer;
|
|
799
|
+
if (typeof evidencePointer === "string" && evidencePointer.trim()) {
|
|
800
|
+
const filePath = extractFilePath(evidencePointer);
|
|
801
|
+
const absPath = resolveLinkedWorkspacePath(workspaceRoot, filePath, ["agent-state"]);
|
|
802
|
+
if (!absPath) {
|
|
803
|
+
errors.push(`payload.evidence_pointer references non-existent file: "${filePath}"`);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
// ── Acceptance criteria quality ─────────────────────────────────
|
|
808
|
+
const criteria = obj.acceptance_criteria;
|
|
809
|
+
if (Array.isArray(criteria)) {
|
|
810
|
+
if (criteria.length === 0) {
|
|
811
|
+
errors.push("acceptance_criteria is empty");
|
|
812
|
+
}
|
|
813
|
+
for (let i = 0; i < criteria.length; i++) {
|
|
814
|
+
const item = criteria[i];
|
|
815
|
+
if (typeof item === "string" && item.trim().length < 10) {
|
|
816
|
+
warnings.push(`acceptance_criteria[${i}] is trivially short: "${item}"`);
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
// ── Verification required_evidence ──────────────────────────────
|
|
821
|
+
const verification = obj.verification;
|
|
822
|
+
if (verification && typeof verification === "object") {
|
|
823
|
+
const requiredEvidence = verification.required_evidence;
|
|
824
|
+
if (Array.isArray(requiredEvidence) && requiredEvidence.length === 0) {
|
|
825
|
+
errors.push("verification.required_evidence is empty");
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
return { ok: errors.length === 0, warnings, errors };
|
|
829
|
+
}
|
|
830
|
+
//# sourceMappingURL=schemas.js.map
|