@williambeto/ai-workflow 2.4.9 → 2.6.4

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 (103) hide show
  1. package/CHANGELOG.md +1138 -168
  2. package/README.md +203 -77
  3. package/bin/ai-workflow.d.ts +3 -0
  4. package/bin/ai-workflow.js +2669 -1
  5. package/bin/ai-workflow.js.map +1 -0
  6. package/chunk-2AOV2ATY.js +749 -0
  7. package/chunk-5WRI5ZAA.js +31 -0
  8. package/chunk-6EMG6FAO.js +734 -0
  9. package/chunk-UHLZX2EG.js +1827 -0
  10. package/core/index.d.ts +440 -0
  11. package/core/index.js +32 -0
  12. package/core/index.js.map +1 -0
  13. package/dist-assets/AGENTS.md +23 -6
  14. package/dist-assets/agents/atlas.md +8 -8
  15. package/dist-assets/agents/nexus.md +4 -4
  16. package/dist-assets/agents/orion.md +1 -1
  17. package/dist-assets/agents/phoenix.md +1 -1
  18. package/dist-assets/agents/sage.md +1 -1
  19. package/dist-assets/commands/implement.md +1 -1
  20. package/dist-assets/docs/QUICKSTART.md +8 -8
  21. package/dist-assets/docs/cli-reference.md +7 -7
  22. package/dist-assets/docs/compatibility/provider-usage.md +1 -9
  23. package/dist-assets/docs/compatibility/runtime-matrix.md +5 -6
  24. package/dist-assets/docs/consumer-onboarding.md +2 -2
  25. package/dist-assets/docs/design-patterns-policy.md +1 -1
  26. package/dist-assets/docs/npm-consumer-quickstart.md +70 -109
  27. package/dist-assets/docs/policies/01-BRANCH_GATE.md +1 -1
  28. package/dist-assets/docs/policies/06-FINAL_EVIDENCE_CONTRACT.md +2 -2
  29. package/dist-assets/docs/policies/08-PRODUCT_TRUTHFULNESS_AND_PROJECT_DOCS.md +1 -1
  30. package/dist-assets/docs/policies/10-BEHAVIORAL_CONTRACT_HARDENING.md +1 -1
  31. package/dist-assets/docs/policies/ORCHESTRATION_PROTOCOL.md +8 -9
  32. package/dist-assets/docs/policies/PROCEDURE_DELIVERY_ARTIFACTS.md +4 -10
  33. package/dist-assets/docs/policies/SKILLS_COMMON_GOVERNANCE.md +1 -1
  34. package/dist-assets/docs/profiles/README.md +2 -2
  35. package/dist-assets/docs/specs/runtime-operational-contract.md +12 -12
  36. package/dist-assets/docs/troubleshooting-guide.md +2 -2
  37. package/dist-assets/docs/visual-validation-guide.md +3 -3
  38. package/dist-assets/schemas/evidence.schema.json +109 -0
  39. package/dist-assets/templates/ANTIGRAVITY.md.template +7 -5
  40. package/dist-assets/templates/CLAUDE.md.template +7 -5
  41. package/dist-assets/templates/CODEX.md.template +7 -5
  42. package/evidence-validator-76ZQQYDU.js +6661 -0
  43. package/package.json +7 -64
  44. package/{src/core/workspace/read-only-workspace.js → read-only-workspace-PZBE7KAX.js} +14 -31
  45. package/{src/commands/validate.js → validate-Q2NLLQ5G.js} +30 -22
  46. package/AGENTS.md +0 -34
  47. package/PUBLISH_MANIFEST.json +0 -34
  48. package/dist-assets/templates/.geminiignore.template +0 -8
  49. package/dist-assets/templates/GEMINI.md.template +0 -20
  50. package/docs/compatibility/provider-usage.md +0 -46
  51. package/docs/compatibility/runtime-matrix.md +0 -31
  52. package/docs/getting-started/DESKTOP_PROMPT.md +0 -52
  53. package/docs/getting-started/authoring-custom-skills.md +0 -80
  54. package/docs/getting-started/quickstart.md +0 -117
  55. package/docs/getting-started/troubleshooting.md +0 -123
  56. package/docs/getting-started/upgrading-to-v2.md +0 -62
  57. package/src/adapters/index.js +0 -4
  58. package/src/adapters/platforms/antigravity.js +0 -382
  59. package/src/adapters/platforms/claude.js +0 -126
  60. package/src/adapters/platforms/codex.js +0 -113
  61. package/src/adapters/platforms/gemini.js +0 -245
  62. package/src/cli.js +0 -155
  63. package/src/commands/clean.js +0 -106
  64. package/src/commands/collect-evidence.js +0 -25
  65. package/src/commands/doctor.js +0 -202
  66. package/src/commands/execute.js +0 -382
  67. package/src/commands/init.js +0 -359
  68. package/src/commands/run.js +0 -112
  69. package/src/core/backup.js +0 -65
  70. package/src/core/completion-contract.js +0 -35
  71. package/src/core/delegation-controller.js +0 -193
  72. package/src/core/evidence/evidence-ledger.js +0 -98
  73. package/src/core/execution-planner.js +0 -62
  74. package/src/core/filesystem.js +0 -141
  75. package/src/core/finalization/finalizer.js +0 -165
  76. package/src/core/finalization/workspace-snapshot.js +0 -110
  77. package/src/core/gates/branch-gate.js +0 -134
  78. package/src/core/gates/merge-gate.js +0 -74
  79. package/src/core/handoff/handoff-engine.js +0 -104
  80. package/src/core/healing/cli-remediation-executor.js +0 -153
  81. package/src/core/healing/healer-engine.js +0 -212
  82. package/src/core/healing/runtime-remediation-executor.js +0 -136
  83. package/src/core/identity.js +0 -43
  84. package/src/core/install-plan.js +0 -34
  85. package/src/core/opencode-merge.js +0 -150
  86. package/src/core/package-assets.js +0 -141
  87. package/src/core/request-classifier.js +0 -73
  88. package/src/core/request-router.js +0 -289
  89. package/src/core/runtime/opencode-adapter.js +0 -202
  90. package/src/core/sdd/validator.js +0 -67
  91. package/src/core/statuses.js +0 -29
  92. package/src/core/symlink-layout.js +0 -93
  93. package/src/core/templates.js +0 -229
  94. package/src/core/validation/artifact-fidelity-gate.js +0 -445
  95. package/src/core/validation/canonical-finalization.js +0 -43
  96. package/src/core/validation/delivery-decision-engine.js +0 -344
  97. package/src/core/validation/evidence-collector.js +0 -245
  98. package/src/core/validation/quality-guard.js +0 -251
  99. package/src/core/validation/stack-detector.js +0 -65
  100. package/src/core/validation/validation-planner.js +0 -134
  101. package/src/core/validation/visual-verifier.js +0 -175
  102. package/src/core/workflow-profiles.js +0 -107
  103. 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
- }