@williambeto/ai-workflow 2.4.9 → 2.6.3

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.
Files changed (104) hide show
  1. package/bin/ai-workflow.d.ts +3 -0
  2. package/bin/ai-workflow.js +2669 -1
  3. package/bin/ai-workflow.js.map +1 -0
  4. package/chunk-2AOV2ATY.js +749 -0
  5. package/chunk-5WRI5ZAA.js +31 -0
  6. package/chunk-6EMG6FAO.js +734 -0
  7. package/chunk-UHLZX2EG.js +1827 -0
  8. package/core/index.d.ts +440 -0
  9. package/core/index.js +32 -0
  10. package/core/index.js.map +1 -0
  11. package/dist-assets/AGENTS.md +23 -6
  12. package/dist-assets/agents/atlas.md +8 -8
  13. package/dist-assets/agents/nexus.md +4 -4
  14. package/dist-assets/agents/orion.md +1 -1
  15. package/dist-assets/agents/phoenix.md +1 -1
  16. package/dist-assets/agents/sage.md +1 -1
  17. package/dist-assets/commands/implement.md +1 -1
  18. package/dist-assets/docs/QUICKSTART.md +8 -8
  19. package/dist-assets/docs/cli-reference.md +7 -7
  20. package/dist-assets/docs/compatibility/provider-usage.md +1 -9
  21. package/dist-assets/docs/compatibility/runtime-matrix.md +5 -6
  22. package/dist-assets/docs/consumer-onboarding.md +2 -2
  23. package/dist-assets/docs/design-patterns-policy.md +1 -1
  24. package/dist-assets/docs/npm-consumer-quickstart.md +70 -109
  25. package/dist-assets/docs/policies/01-BRANCH_GATE.md +1 -1
  26. package/dist-assets/docs/policies/06-FINAL_EVIDENCE_CONTRACT.md +2 -2
  27. package/dist-assets/docs/policies/08-PRODUCT_TRUTHFULNESS_AND_PROJECT_DOCS.md +1 -1
  28. package/dist-assets/docs/policies/10-BEHAVIORAL_CONTRACT_HARDENING.md +1 -1
  29. package/dist-assets/docs/policies/ORCHESTRATION_PROTOCOL.md +8 -9
  30. package/dist-assets/docs/policies/PROCEDURE_DELIVERY_ARTIFACTS.md +4 -10
  31. package/dist-assets/docs/policies/SKILLS_COMMON_GOVERNANCE.md +1 -1
  32. package/dist-assets/docs/profiles/README.md +2 -2
  33. package/dist-assets/docs/specs/runtime-operational-contract.md +12 -12
  34. package/dist-assets/docs/troubleshooting-guide.md +2 -2
  35. package/dist-assets/docs/visual-validation-guide.md +3 -3
  36. package/dist-assets/schemas/evidence.schema.json +109 -0
  37. package/dist-assets/templates/ANTIGRAVITY.md.template +7 -5
  38. package/dist-assets/templates/CLAUDE.md.template +7 -5
  39. package/dist-assets/templates/CODEX.md.template +7 -5
  40. package/evidence-validator-76ZQQYDU.js +6661 -0
  41. package/package.json +7 -64
  42. package/{src/core/workspace/read-only-workspace.js → read-only-workspace-PZBE7KAX.js} +14 -31
  43. package/{src/commands/validate.js → validate-Q2NLLQ5G.js} +30 -22
  44. package/AGENTS.md +0 -34
  45. package/CHANGELOG.md +0 -259
  46. package/LICENSE +0 -21
  47. package/PUBLISH_MANIFEST.json +0 -34
  48. package/README.md +0 -129
  49. package/dist-assets/templates/.geminiignore.template +0 -8
  50. package/dist-assets/templates/GEMINI.md.template +0 -20
  51. package/docs/compatibility/provider-usage.md +0 -46
  52. package/docs/compatibility/runtime-matrix.md +0 -31
  53. package/docs/getting-started/DESKTOP_PROMPT.md +0 -52
  54. package/docs/getting-started/authoring-custom-skills.md +0 -80
  55. package/docs/getting-started/quickstart.md +0 -117
  56. package/docs/getting-started/troubleshooting.md +0 -123
  57. package/docs/getting-started/upgrading-to-v2.md +0 -62
  58. package/src/adapters/index.js +0 -4
  59. package/src/adapters/platforms/antigravity.js +0 -382
  60. package/src/adapters/platforms/claude.js +0 -126
  61. package/src/adapters/platforms/codex.js +0 -113
  62. package/src/adapters/platforms/gemini.js +0 -245
  63. package/src/cli.js +0 -155
  64. package/src/commands/clean.js +0 -106
  65. package/src/commands/collect-evidence.js +0 -25
  66. package/src/commands/doctor.js +0 -202
  67. package/src/commands/execute.js +0 -382
  68. package/src/commands/init.js +0 -359
  69. package/src/commands/run.js +0 -112
  70. package/src/core/backup.js +0 -65
  71. package/src/core/completion-contract.js +0 -35
  72. package/src/core/delegation-controller.js +0 -193
  73. package/src/core/evidence/evidence-ledger.js +0 -98
  74. package/src/core/execution-planner.js +0 -62
  75. package/src/core/filesystem.js +0 -141
  76. package/src/core/finalization/finalizer.js +0 -165
  77. package/src/core/finalization/workspace-snapshot.js +0 -110
  78. package/src/core/gates/branch-gate.js +0 -134
  79. package/src/core/gates/merge-gate.js +0 -74
  80. package/src/core/handoff/handoff-engine.js +0 -104
  81. package/src/core/healing/cli-remediation-executor.js +0 -153
  82. package/src/core/healing/healer-engine.js +0 -212
  83. package/src/core/healing/runtime-remediation-executor.js +0 -136
  84. package/src/core/identity.js +0 -43
  85. package/src/core/install-plan.js +0 -34
  86. package/src/core/opencode-merge.js +0 -150
  87. package/src/core/package-assets.js +0 -141
  88. package/src/core/request-classifier.js +0 -73
  89. package/src/core/request-router.js +0 -289
  90. package/src/core/runtime/opencode-adapter.js +0 -202
  91. package/src/core/sdd/validator.js +0 -67
  92. package/src/core/statuses.js +0 -29
  93. package/src/core/symlink-layout.js +0 -93
  94. package/src/core/templates.js +0 -229
  95. package/src/core/validation/artifact-fidelity-gate.js +0 -445
  96. package/src/core/validation/canonical-finalization.js +0 -43
  97. package/src/core/validation/delivery-decision-engine.js +0 -344
  98. package/src/core/validation/evidence-collector.js +0 -245
  99. package/src/core/validation/quality-guard.js +0 -251
  100. package/src/core/validation/stack-detector.js +0 -65
  101. package/src/core/validation/validation-planner.js +0 -134
  102. package/src/core/validation/visual-verifier.js +0 -175
  103. package/src/core/workflow-profiles.js +0 -107
  104. package/src/core/workflow-state-machine.js +0 -46
@@ -1,202 +0,0 @@
1
- import { spawn, spawnSync } from "node:child_process";
2
- import readline from "node:readline";
3
-
4
- /**
5
- * OpenCodeAdapter - Real runtime integration with the OpenCode CLI.
6
- */
7
- export class OpenCodeAdapter {
8
- constructor({ cwd = process.cwd() } = {}) {
9
- this.cwd = cwd;
10
- }
11
-
12
- /**
13
- * Inspects the availability and capability of the OpenCode CLI.
14
- * @returns {Promise<{available: boolean, supports: {run: boolean, formatJson: boolean, agent: boolean, model: boolean}}>}
15
- */
16
- async inspect() {
17
- try {
18
- const cliHelp = spawnSync("opencode", ["--help"], { encoding: "utf8" });
19
- const runHelp = spawnSync("opencode", ["run", "--help"], { encoding: "utf8" });
20
-
21
- const available = cliHelp.status === 0 && runHelp.status === 0;
22
- if (!available) {
23
- return {
24
- available: false,
25
- supports: { run: false, formatJson: false, agent: false, model: false }
26
- };
27
- }
28
-
29
- return {
30
- available: true,
31
- supports: {
32
- run: /\brun\b/.test(cliHelp.stdout),
33
- formatJson: /--format/.test(runHelp.stdout),
34
- agent: /--agent/.test(runHelp.stdout),
35
- model: /--model/.test(runHelp.stdout),
36
- }
37
- };
38
- } catch {
39
- return {
40
- available: false,
41
- supports: { run: false, formatJson: false, agent: false, model: false }
42
- };
43
- }
44
- }
45
-
46
- /**
47
- * Runs opencode with a prompt and options.
48
- * @param {string} message - The message prompt.
49
- * @param {Object} options - CLI options (e.g. agent, model, readOnly).
50
- * @returns {Promise<{success: boolean, commandsRun: string[], eventCount: number, error?: string}>}
51
- */
52
- async execute(message, { agent = null, model = null, readOnly = false } = {}) {
53
- const inspection = await this.inspect();
54
- const isSpecializedAgent = agent && ["Nexus", "Orion", "Astra", "Sage", "Phoenix"].includes(agent);
55
-
56
- if (!inspection.available) {
57
- return {
58
- success: false,
59
- status: isSpecializedAgent ? "BLOCKED" : "FAILED",
60
- commandsRun: [],
61
- eventCount: 0,
62
- error: "OpenCode CLI is not installed or not available in the system PATH.",
63
- runtimeAgentRequested: agent || null,
64
- runtimeAgentApplied: null,
65
- runtimeAgentSupported: false,
66
- runtimeAgentSelectionMode: isSpecializedAgent ? "explicit" : "default"
67
- };
68
- }
69
-
70
- if (isSpecializedAgent && !inspection.supports.agent) {
71
- return {
72
- success: false,
73
- status: "BLOCKED",
74
- error: `Requested runtime actor '${agent}' cannot be applied because this OpenCode runtime does not support --agent.`,
75
- runtimeAgentRequested: agent,
76
- runtimeAgentApplied: null,
77
- runtimeAgentSupported: false,
78
- runtimeAgentSelectionMode: "unsupported",
79
- commandsRun: [],
80
- eventCount: 0
81
- };
82
- }
83
-
84
- const runInWorkspace = async (targetCwd) => {
85
- return new Promise((resolve) => {
86
- const args = ["run", message];
87
- if (inspection.supports.formatJson) {
88
- args.push("--format", "json");
89
- }
90
- if (isSpecializedAgent && inspection.supports.agent) {
91
- args.push("--agent", agent);
92
- }
93
- if (model && inspection.supports.model) {
94
- args.push("--model", model);
95
- }
96
-
97
- console.log(`[RUNTIME] Delegating to OpenCode: opencode ${args.map(a => a.includes(" ") ? `"${a}"` : a).join(" ")}`);
98
-
99
- const child = spawn("opencode", args, {
100
- cwd: targetCwd,
101
- stdio: ["ignore", "pipe", "inherit"] // Inherit stderr to show warnings directly
102
- });
103
-
104
- const rl = readline.createInterface({
105
- input: child.stdout,
106
- terminal: false
107
- });
108
-
109
- const commandsRun = [];
110
- let eventCount = 0;
111
-
112
- rl.on("line", (line) => {
113
- const trimmed = line.trim();
114
- if (!trimmed) return;
115
-
116
- try {
117
- const event = JSON.parse(trimmed);
118
- eventCount++;
119
-
120
- // 1. Stream agent output text in real-time to user
121
- if (event.type === "text" && event.part?.text) {
122
- process.stdout.write(event.part.text);
123
- }
124
-
125
- // 2. Capture tool executions/commands
126
- if (event.type === "step_start" && event.part?.toolCalls) {
127
- for (const call of event.part.toolCalls) {
128
- if (call.name === "run_command" && call.args?.CommandLine) {
129
- commandsRun.push(call.args.CommandLine);
130
- }
131
- if (readOnly) {
132
- const name = call.name || "";
133
- const isWriteTool = name.startsWith("write_") || name.includes("write") || name.includes("replace") || name.includes("edit") || name.includes("delete") || name.includes("remove");
134
- let isDestructiveGit = false;
135
- if (name === "run_command" && call.args?.CommandLine) {
136
- const cmd = call.args.CommandLine;
137
- const destPattern = /\b(git\s+(commit|add|push|merge|reset|rm|branch|checkout|switch|stash|init)|touch|rm|mkdir|cp|mv|chmod|chown|tee|sed|awk)\b|>>|>/;
138
- if (destPattern.test(cmd)) {
139
- isDestructiveGit = true;
140
- }
141
- }
142
- if (isWriteTool || isDestructiveGit) {
143
- console.error(`\n[SECURITY WARNING] Read-only execution blocked attempt to write/modify workspace: tool '${name}' or command detected.`);
144
- child.kill();
145
- resolve({
146
- success: false,
147
- commandsRun,
148
- eventCount,
149
- error: `Read-only confinement violation: tool '${name}' or command attempted write/modify operation during read-only task.`,
150
- runtimeAgentRequested: agent || null,
151
- runtimeAgentApplied: null,
152
- runtimeAgentSupported: inspection.supports.agent,
153
- runtimeAgentSelectionMode: isSpecializedAgent ? "explicit" : "default"
154
- });
155
- return;
156
- }
157
- }
158
- }
159
- }
160
- } catch {
161
- // If a line is not valid JSON (e.g. starting/finishing logs), print it directly
162
- console.log(trimmed);
163
- }
164
- });
165
-
166
- child.on("close", (code) => {
167
- console.log("\n[RUNTIME] OpenCode finished execution.");
168
- resolve({
169
- success: code === 0,
170
- commandsRun,
171
- eventCount,
172
- runtimeAgentRequested: agent || null,
173
- runtimeAgentApplied: isSpecializedAgent ? agent : null,
174
- runtimeAgentSupported: inspection.supports.agent,
175
- runtimeAgentSelectionMode: isSpecializedAgent ? "explicit" : "default"
176
- });
177
- });
178
-
179
- child.on("error", (err) => {
180
- console.error(`\n[RUNTIME] Failed to launch opencode: ${err.message}`);
181
- resolve({
182
- success: false,
183
- commandsRun,
184
- eventCount: 0,
185
- error: err.message,
186
- runtimeAgentRequested: agent || null,
187
- runtimeAgentApplied: null,
188
- runtimeAgentSupported: inspection.supports.agent,
189
- runtimeAgentSelectionMode: isSpecializedAgent ? "explicit" : "default"
190
- });
191
- });
192
- });
193
- };
194
-
195
- if (readOnly) {
196
- const { runInReadOnlyWorkspace } = await import("../workspace/read-only-workspace.js");
197
- return runInReadOnlyWorkspace(this.cwd, runInWorkspace);
198
- } else {
199
- return runInWorkspace(this.cwd);
200
- }
201
- }
202
- }
@@ -1,67 +0,0 @@
1
- import fs from "node:fs/promises";
2
-
3
- /**
4
- * SpecValidator - Enforces "No Spec, No Code" rule.
5
- * Validates existence, structure, and approval status of specifications.
6
- */
7
- export class SpecValidator {
8
- /**
9
- * Validates a specification file.
10
- * @param {string} filePath - Path to the .md specification file.
11
- * @returns {Promise<{valid: boolean, reason?: string, tier?: string}>}
12
- */
13
- async validate(filePath) {
14
- try {
15
- const content = await fs.readFile(filePath, "utf8");
16
-
17
- // Check for tiered tier identification
18
- let tier = "unknown";
19
- if (content.includes("[DEEP]")) tier = "deep";
20
- else if (content.includes("[STANDARD]")) tier = "standard";
21
- else if (content.includes("[TINY]")) tier = "tiny";
22
-
23
- if (tier === "unknown") {
24
- return { valid: false, reason: "Specification tier [DEEP|STANDARD|TINY] not identified in title." };
25
- }
26
-
27
- // Check for Metadata section
28
- if (!content.includes("## Metadata")) {
29
- return { valid: false, reason: "Missing '## Metadata' section.", tier };
30
- }
31
-
32
- // Check for Acceptance Criteria section
33
- if (!content.includes("## Acceptance Criteria")) {
34
- return { valid: false, reason: "Missing '## Acceptance Criteria' section.", tier };
35
- }
36
-
37
- // Check for Approved status
38
- const lines = content.split("\n");
39
- const statusLine = lines.find(l => l.includes("Status:"));
40
-
41
- if (!statusLine) {
42
- return { valid: false, reason: "Missing Status field in Metadata section.", tier };
43
- }
44
-
45
- const statusPart = statusLine.split(":")[1]
46
- .replace(/[\*_]/g, "") // Remove bold/italic markers
47
- .trim()
48
- .toUpperCase();
49
-
50
- // If it contains multiple options separated by |, it's not approved yet
51
- if (statusPart.includes("|")) {
52
- return { valid: false, reason: "Specification status is a template list. Must be explicitly set to 'APPROVED'.", tier };
53
- }
54
-
55
- if (statusPart !== "APPROVED") {
56
- return { valid: false, reason: `Specification status is '${statusPart}', but must be 'APPROVED' to proceed.`, tier };
57
- }
58
-
59
- return { valid: true, tier };
60
- } catch (error) {
61
- if (error.code === "ENOENT") {
62
- return { valid: false, reason: `Specification file not found: ${filePath}` };
63
- }
64
- return { valid: false, reason: `Error reading specification: ${error.message}` };
65
- }
66
- }
67
- }
@@ -1,29 +0,0 @@
1
- export const COMPLETION_STATUSES = Object.freeze([
2
- "PASS",
3
- "PASS_WITH_NOTES",
4
- "FAIL_DELEGATION_GATE",
5
- "FAIL_QUALITY_GATE",
6
- "FAIL",
7
- "BLOCKED",
8
- "NOT_RUN"
9
- ]);
10
-
11
- export const RECOVERABLE_GATE_STATUSES = Object.freeze([
12
- "FAIL_DELEGATION_GATE",
13
- "FAIL_QUALITY_GATE"
14
- ]);
15
-
16
- export const TERMINAL_FAILURE_STATUSES = Object.freeze([
17
- "FAIL",
18
- "BLOCKED"
19
- ]);
20
-
21
- export function isRecoverableGateFailure(status) {
22
- return RECOVERABLE_GATE_STATUSES.includes(status);
23
- }
24
-
25
- export function isTerminalFailure(status) {
26
- return TERMINAL_FAILURE_STATUSES.includes(status);
27
- }
28
-
29
- export const COMPLETION_STATUS_TEXT = COMPLETION_STATUSES.join(" | ");
@@ -1,93 +0,0 @@
1
- import fs from "node:fs/promises";
2
- import path from "node:path";
3
-
4
- function normalize(p) {
5
- return p.split(path.sep).join("/");
6
- }
7
-
8
- /**
9
- * For v3.0.0 "Elite Governance", we want an ULTRA-CLEAN root.
10
- * Only "opencode" is symlinked to the root (required for OpenCode discovery).
11
- * All other assets stay inside .ai-workflow/.
12
- */
13
- const LINKABLE_ROOTS = new Set([
14
- "opencode",
15
- ".agents"
16
- ]);
17
-
18
- const LINKABLE_FILES = new Set([]);
19
-
20
- export function buildSymlinkEntries({ templateFiles, installRoot = ".ai-workflow" }) {
21
- const entries = new Map();
22
-
23
- for (const relativePath of Object.keys(templateFiles)) {
24
- if (relativePath === "opencode.jsonc") continue;
25
-
26
- const normalized = normalize(relativePath);
27
-
28
- if (LINKABLE_FILES.has(normalized)) {
29
- entries.set(normalized, `${installRoot}/${normalized}`);
30
- continue;
31
- }
32
-
33
- // Match composite paths in LINKABLE_ROOTS (e.g., "docs/policies")
34
- for (const rootPath of LINKABLE_ROOTS) {
35
- if (normalized === rootPath || normalized.startsWith(`${rootPath}/`)) {
36
- entries.set(rootPath, `${installRoot}/${rootPath}`);
37
- break;
38
- }
39
- }
40
- }
41
-
42
- return Array.from(entries.entries()).map(([linkPath, targetPath]) => ({ linkPath, targetPath }));
43
- }
44
-
45
- export async function isSymlinkTo(absoluteLinkPath, absoluteTargetPath) {
46
- try {
47
- const stat = await fs.lstat(absoluteLinkPath);
48
- if (!stat.isSymbolicLink()) return false;
49
- const currentTarget = await fs.readlink(absoluteLinkPath);
50
- const resolved = path.resolve(path.dirname(absoluteLinkPath), currentTarget);
51
- return resolved === absoluteTargetPath;
52
- } catch {
53
- return false;
54
- }
55
- }
56
-
57
- /**
58
- * Internal symlink to satisfy opencode.jsonc paths without polluting the root.
59
- * Creates .ai-workflow/opencode/skills -> ../.agents/skills
60
- */
61
- export async function setupInternalSymlinks(cwd, installRoot = ".ai-workflow") {
62
- const skillsLink = path.join(cwd, installRoot, "opencode/skills");
63
- const skillsTarget = path.join(cwd, installRoot, ".agents/skills");
64
-
65
- if (!(await exists(skillsTarget))) return;
66
-
67
- try {
68
- const stat = await fs.lstat(skillsLink).catch(() => null);
69
- if (stat) {
70
- if (stat.isSymbolicLink()) {
71
- const current = await fs.readlink(skillsLink);
72
- if (current === "../.agents/skills") return;
73
- await fs.unlink(skillsLink);
74
- } else {
75
- return; // File exists, skip
76
- }
77
- }
78
-
79
- const type = process.platform === "win32" ? "junction" : "dir";
80
- await fs.symlink("../.agents/skills", skillsLink, type);
81
- } catch {
82
- // Silent fail for internal symlink
83
- }
84
- }
85
-
86
- async function exists(p) {
87
- try {
88
- await fs.access(p);
89
- return true;
90
- } catch {
91
- return false;
92
- }
93
- }
@@ -1,229 +0,0 @@
1
- import { getFullAgentContent, getFullSkillFiles, discoverPackageFiles, readPackageFile, getPackageVersion } from "./package-assets.js";
2
- import { getCanonicalAgentName } from "./identity.js";
3
-
4
- const COMMON_FILES = {
5
- "opencode/README.md": `# OpenCode Setup\n\nThis directory is managed by \`ai-workflow\` init.\nAdd agent and command files required by your project workflow.\n`
6
- };
7
-
8
- const FULL_PRIMARY_AGENTS = [
9
- "atlas",
10
- "nexus",
11
- "orion",
12
- "astra",
13
- "sage",
14
- "phoenix"
15
- ];
16
-
17
- const FULL_SKILLS = [
18
- "project-memory",
19
- "optimize-tokens",
20
- "documentation",
21
- "architecture",
22
- "technical-leadership",
23
- "product-discovery",
24
- "product-planning",
25
- "spec-driven-development",
26
- "pr-workflow",
27
- "qa-workflow",
28
- "release-workflow",
29
- "deployment",
30
- "ui-ux-design",
31
- "design-principles",
32
- "frontend-development",
33
- "backend-development",
34
- "full-stack-development",
35
- "refactoring",
36
- "prompt-engineer"
37
- ];
38
-
39
- const KIT_VERSION = getPackageVersion() ?? "unknown";
40
-
41
- function buildRuntimeFiles({ includeFormalEvidence = false } = {}) {
42
- const files = {};
43
-
44
- for (const agent of FULL_PRIMARY_AGENTS) {
45
- const content = getFullAgentContent(agent);
46
- if (content === null) {
47
- throw new Error(`CRITICAL FAILURE: Missing required agent asset: dist-assets/agents/${agent}.md`);
48
- }
49
- files[`opencode/agents/${agent}.md`] = content;
50
- }
51
-
52
- for (const skill of FULL_SKILLS) {
53
- const skillFiles = getFullSkillFiles(skill);
54
- if (Object.keys(skillFiles).length === 0) {
55
- continue;
56
- }
57
- for (const [relPath, content] of Object.entries(skillFiles)) {
58
- const targetPath = relPath.replace(/^dist-assets\//, "opencode/");
59
- if (!files[targetPath]) {
60
- files[targetPath] = content;
61
- }
62
- }
63
- }
64
-
65
- // Copy governance policy into opencode/docs/policies/ so the relative link
66
- // ../../docs/policies/SKILLS_COMMON_GOVERNANCE.md resolves correctly from
67
- // opencode/skills/{skill}/SKILL.md for OpenCode and all platform adapters.
68
- const opencodeGovernancePolicy = readPackageFile("dist-assets/docs/policies/SKILLS_COMMON_GOVERNANCE.md");
69
- if (opencodeGovernancePolicy !== null) {
70
- files["opencode/docs/policies/SKILLS_COMMON_GOVERNANCE.md"] = opencodeGovernancePolicy;
71
- }
72
-
73
- const commandFiles = discoverPackageFiles("dist-assets/commands");
74
- for (const [relPath, content] of Object.entries(commandFiles)) {
75
- const targetPath = relPath.replace(/^dist-assets\//, "opencode/");
76
- if (!files[targetPath]) {
77
- files[targetPath] = content;
78
- }
79
- }
80
-
81
- const opencodeSkillFiles = discoverPackageFiles("dist-assets/skills");
82
- for (const [relPath, content] of Object.entries(opencodeSkillFiles)) {
83
- const targetPath = relPath.replace(/^dist-assets\//, "opencode/");
84
- if (!files[targetPath]) {
85
- files[targetPath] = content;
86
- }
87
- }
88
-
89
- const harnessWorkflowFiles = discoverPackageFiles("dist-assets/harness/workflows");
90
- for (const [relPath, content] of Object.entries(harnessWorkflowFiles)) {
91
- const targetPath = relPath.replace(/^dist-assets\//, "");
92
- files[targetPath] = content;
93
- }
94
-
95
- const harnessHandoffFiles = discoverPackageFiles("dist-assets/harness/handoffs");
96
- for (const [relPath, content] of Object.entries(harnessHandoffFiles)) {
97
- const targetPath = relPath.replace(/^dist-assets\//, "");
98
- files[targetPath] = content;
99
- }
100
-
101
- const agentsContent = readPackageFile("dist-assets/AGENTS.md");
102
- if (agentsContent !== null) files["AGENTS.md"] = agentsContent;
103
-
104
- const consumerQuickstart = readPackageFile("dist-assets/docs/QUICKSTART.md");
105
- if (consumerQuickstart !== null) files["QUICKSTART.md"] = consumerQuickstart;
106
-
107
- const policyContent = readPackageFile("dist-assets/docs/architecture-policy.md");
108
- if (policyContent !== null) files["opencode/docs/architecture-policy.md"] = policyContent;
109
-
110
- const dpContent = readPackageFile("dist-assets/docs/design-patterns-policy.md");
111
- if (dpContent !== null) files["opencode/docs/design-patterns-policy.md"] = dpContent;
112
-
113
- const visualValidationGuide = readPackageFile("dist-assets/docs/visual-validation-guide.md");
114
- if (visualValidationGuide !== null) files["opencode/docs/visual-validation-guide.md"] = visualValidationGuide;
115
-
116
- const governancePolicies = discoverPackageFiles("dist-assets/docs/policies");
117
- for (const [relPath, content] of Object.entries(governancePolicies)) {
118
- const targetPath = relPath.replace(/^dist-assets\//, "opencode/");
119
- files[targetPath] = content;
120
- }
121
-
122
- const compatibilityDocs = discoverPackageFiles("dist-assets/docs/compatibility");
123
- for (const [relPath, content] of Object.entries(compatibilityDocs)) {
124
- const targetPath = relPath.replace(/^dist-assets\//, "opencode/");
125
- files[targetPath] = content;
126
- }
127
-
128
- const qualityReferenceFiles = discoverPackageFiles("dist-assets/docs/references");
129
- for (const [relPath, content] of Object.entries(qualityReferenceFiles)) {
130
- const targetPath = relPath.replace(/^dist-assets\//, "opencode/");
131
- files[targetPath] = content;
132
- }
133
-
134
- const workflowProfileFiles = discoverPackageFiles("dist-assets/docs/profiles");
135
- for (const [relPath, content] of Object.entries(workflowProfileFiles)) {
136
- const targetPath = relPath.replace(/^dist-assets\//, "opencode/");
137
- files[targetPath] = content;
138
- }
139
-
140
- const templateFiles = discoverPackageFiles("dist-assets/templates");
141
- for (const [relPath, content] of Object.entries(templateFiles)) {
142
- if (!includeFormalEvidence && relPath.includes("/owner-evidence/")) continue;
143
- const targetPath = relPath.replace(/^dist-assets\//, "");
144
- files[targetPath] = content;
145
- }
146
-
147
- const schemaFiles = discoverPackageFiles("dist-assets/schemas");
148
- for (const [relPath, content] of Object.entries(schemaFiles)) {
149
- const targetPath = relPath.replace(/^dist-assets\//, "");
150
- files[targetPath] = content;
151
- }
152
-
153
- return files;
154
- }
155
-
156
- function buildExtraFiles() {
157
- const files = {};
158
- const exampleFiles = discoverPackageFiles("dist-assets/examples");
159
- for (const [relPath, content] of Object.entries(exampleFiles)) {
160
- const targetPath = relPath.replace(/^dist-assets\//, "");
161
- files[targetPath] = content;
162
- }
163
- return files;
164
- }
165
-
166
- const STANDARD_FILES = buildRuntimeFiles();
167
- const FULL_FILES = { ...buildRuntimeFiles({ includeFormalEvidence: true }), ...buildExtraFiles() };
168
-
169
- export const PROFILE_FILES = {
170
- standard: {
171
- ...COMMON_FILES,
172
- ...STANDARD_FILES
173
- },
174
- full: {
175
- ...COMMON_FILES,
176
- ...FULL_FILES
177
- }
178
- };
179
-
180
- export function isValidProfile(profile) {
181
- return profile === "standard" || profile === "full";
182
- }
183
-
184
- export function getTemplateFiles(profile = "standard") {
185
- return PROFILE_FILES[profile] ?? PROFILE_FILES.standard;
186
- }
187
-
188
- export function getManagedBlocks() {
189
- return [
190
- ...FULL_PRIMARY_AGENTS.map((agent) => `opencode.jsonc:agent.${getCanonicalAgentName(agent)}`),
191
- ...FULL_SKILLS.map((skill) => `opencode.jsonc:agent.${getCanonicalAgentName(skill)}`),
192
- "opencode.jsonc:command.atlas",
193
- "opencode.jsonc:command.run",
194
- "opencode.jsonc:command.discover",
195
- "opencode.jsonc:command.spec-create",
196
- "opencode.jsonc:command.spec-review",
197
- "opencode.jsonc:command.spec-implement",
198
- "opencode.jsonc:command.plan",
199
- "opencode.jsonc:command.implement",
200
- "opencode.jsonc:command.validate",
201
- "opencode.jsonc:command.audit",
202
- "opencode.jsonc:command.optimize-tokens",
203
- "opencode.jsonc:command.update-memory",
204
- "opencode.jsonc:command.release",
205
- "opencode.jsonc:command.deploy"
206
- ];
207
- }
208
-
209
- export function buildAiWorkflowConfig({ profile, managedFiles, managedLinks = [] }) {
210
- const version = getPackageVersion();
211
- const now = new Date().toISOString();
212
-
213
- return {
214
- package: "@williambeto/ai-workflow",
215
- version,
216
- runtime: "opencode",
217
- profile,
218
- installMode: "project-local",
219
- generatedAt: now,
220
- paths: {
221
- agents: ".ai-workflow/opencode/agents",
222
- commands: ".ai-workflow/opencode/commands",
223
- skills: ".ai-workflow/opencode/skills",
224
- policies: ".ai-workflow/opencode/docs/policies",
225
- harness: ".ai-workflow/harness",
226
- schemas: ".ai-workflow/schemas"
227
- }
228
- };
229
- }