@williambeto/ai-workflow 2.6.7 โ†’ 2.7.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 CHANGED
@@ -1,8 +1,53 @@
1
1
  ## [unreleased]
2
2
 
3
+ ### ๐Ÿš€ Features
4
+
5
+ - *(adapters)* Add copilot-instructions.md for maximum Codex compatibility
6
+
7
+ ### ๐Ÿ› Bug Fixes
8
+
9
+ - *(codex)* Ensure root instructions and proper runtime detection
10
+
11
+ ### ๐Ÿ’ผ Other
12
+
13
+ - Merge pull request #123 from williambeto/feat/codex-compatibility
14
+
15
+ feat: native codex runtime support
16
+
17
+ ### ๐Ÿ“š Documentation
18
+
19
+ - Update CHANGELOG for v2.6.6 and v2.6.7
20
+ - Save publish qa checklist
21
+ - *(qa)* Enforce markdown pattern on github releases
22
+ - Promote Codex to Supported and update assets list
23
+ ## [2.6.7] - 2026-07-04
24
+
25
+ ### ๐Ÿ› Bug Fixes
26
+
27
+ - *(fidelity)* Skip HTML semantic check for non-page components (fixes #122)
28
+
29
+ ### โš™๏ธ Miscellaneous Tasks
30
+
31
+ - *(release)* 2.6.7
32
+ ## [2.6.6] - 2026-07-04
33
+
34
+ ### ๐Ÿšœ Refactor
35
+
36
+ - *(cli)* Reduce cyclomatic complexity in core commands
37
+
38
+ ### โš™๏ธ Miscellaneous Tasks
39
+
40
+ - Cleanup obsolete verification file and sync package-lock
41
+ - *(release)* 2.6.6
42
+ ## [2.6.5] - 2026-07-04
43
+
3
44
  ### ๐Ÿงช Testing
4
45
 
5
46
  - Align E2E assertions with updated requestedActor routing mechanics
47
+
48
+ ### โš™๏ธ Miscellaneous Tasks
49
+
50
+ - *(release)* V2.6.5
6
51
  ## [2.6.4] - 2026-07-04
7
52
 
8
53
  ### ๐Ÿ› Bug Fixes
@@ -193,13 +193,14 @@ function isValidProfile(profile) {
193
193
  function getTemplateFiles(profile = "standard") {
194
194
  return PROFILE_FILES[profile] ?? PROFILE_FILES.standard;
195
195
  }
196
- function buildAiWorkflowConfig({ profile }) {
196
+ function buildAiWorkflowConfig({ profile, runtimes = ["opencode"] }) {
197
197
  const version = getPackageVersion();
198
198
  const now = (/* @__PURE__ */ new Date()).toISOString();
199
+ const primaryRuntime = runtimes.join("+");
199
200
  return {
200
201
  package: "@williambeto/ai-workflow",
201
202
  version,
202
- runtime: "opencode",
203
+ runtime: primaryRuntime,
203
204
  profile,
204
205
  installMode: "project-local",
205
206
  generatedAt: now,
@@ -779,7 +780,7 @@ Every task completion MUST provide the following payload:
779
780
  * - Skills -> .agents/skills/
780
781
  * - Commands -> .codex/prompts/
781
782
  */
782
- async deploy(installRoot = ".ai-workflow") {
783
+ async deploy(installRoot = ".ai-workflow", force) {
783
784
  const sourceAgentsDir = path7.join(this.cwd, installRoot, "opencode/agents");
784
785
  const sourceSkillsDir = path7.join(this.cwd, installRoot, "opencode/skills");
785
786
  const sourceCommandsDir = path7.join(this.cwd, installRoot, "opencode/commands");
@@ -791,7 +792,7 @@ Every task completion MUST provide the following payload:
791
792
  const transformed = await this.transformAgent(path7.join(sourceAgentsDir, file));
792
793
  await fs5.writeFile(path7.join(codexAgentsDir, `${transformed.name}.md`), transformed.content);
793
794
  }
794
- const codexSkillsDir = path7.join(this.cwd, ".agents/skills");
795
+ const codexSkillsDir = path7.join(this.cwd, ".codex/skills");
795
796
  await fs5.mkdir(codexSkillsDir, { recursive: true });
796
797
  const skillFolders = await fs5.readdir(sourceSkillsDir).catch(() => []);
797
798
  for (const folder of skillFolders) {
@@ -812,7 +813,7 @@ Every task completion MUST provide the following payload:
812
813
  const content = await fs5.readFile(path7.join(sourceCommandsDir, file), "utf8");
813
814
  await fs5.writeFile(path7.join(codexPromptsDir, targetFileName), content);
814
815
  }
815
- const codexPoliciesDir = path7.join(this.cwd, ".agents", "docs", "policies");
816
+ const codexPoliciesDir = path7.join(this.cwd, ".codex", "docs", "policies");
816
817
  await fs5.mkdir(codexPoliciesDir, { recursive: true });
817
818
  const sourcePoliciesDir = path7.join(this.cwd, installRoot, "opencode", "docs", "policies");
818
819
  const policyFiles = await fs5.readdir(sourcePoliciesDir).catch(() => []);
@@ -821,6 +822,70 @@ Every task completion MUST provide the following payload:
821
822
  const policyContent = await fs5.readFile(path7.join(sourcePoliciesDir, file), "utf8");
822
823
  await fs5.writeFile(path7.join(codexPoliciesDir, file), policyContent);
823
824
  }
825
+ await this.deployRootCopilotInstructions();
826
+ await this.deployRootCodexMd(force);
827
+ await this.deployRootAgentsMd(force);
828
+ }
829
+ async deployRootCopilotInstructions() {
830
+ const githubDir = path7.join(this.cwd, ".github");
831
+ await fs5.mkdir(githubDir, { recursive: true });
832
+ const targetPath = path7.join(githubDir, "copilot-instructions.md");
833
+ const instructions = `# AI Workflow Kit Governance
834
+
835
+ This repository uses the **AI Workflow Kit** (OpenCode-first) workflow.
836
+
837
+ ## Mandate: Atlas Authority Protocol
838
+ All architectural changes must align with the specifications issued by the **Specification Authority**.
839
+
840
+ ## Rules & Personas
841
+ - Always follow the **Branch Gate** policy (never work on \`main\`).
842
+ - Always follow the **SDD Workflow** (Spec -> Plan -> PR -> Evidence).
843
+ - When acting as an agent, consult the instructions in \`.github/agents/\`.
844
+ - When utilizing skills, consult the files in \`.codex/skills/\`.
845
+
846
+ ## Completion Contract
847
+ Every task completion MUST follow the payload format defined in the individual agent files.
848
+ `;
849
+ await fs5.writeFile(targetPath, instructions);
850
+ }
851
+ async deployRootCodexMd(force) {
852
+ const targetPath = path7.join(this.cwd, "CODEX.md");
853
+ if (!force && await this.exists(targetPath)) return;
854
+ const templatePath = path7.join(this.cwd, ".ai-workflow", "templates", "CODEX.md.template");
855
+ if (await this.exists(templatePath)) {
856
+ const content = await fs5.readFile(templatePath, "utf8");
857
+ await fs5.writeFile(targetPath, content);
858
+ return;
859
+ }
860
+ const instructions = `# AI Workflow Kit Governance
861
+
862
+ This repository uses the **AI Workflow Kit** (OpenCode-first) workflow.
863
+
864
+ ## Mandate: Atlas Authority Protocol
865
+ All architectural changes must align with the specifications issued by the **Specification Authority**.
866
+
867
+ ## Rules & Personas
868
+ - Always follow the **Branch Gate** policy (never work on \`main\`).
869
+ - Always follow the **SDD Workflow** (Spec -> Plan -> PR -> Evidence).
870
+ - When acting as an agent, consult the instructions in \`.github/agents/\`.
871
+ - When utilizing skills, consult the files in \`.codex/skills/\`.
872
+
873
+ ## Completion Contract
874
+ Every task completion MUST follow the payload format defined in the individual agent files.
875
+ `;
876
+ await fs5.writeFile(targetPath, instructions);
877
+ }
878
+ async deployRootAgentsMd(force) {
879
+ const targetPath = path7.join(this.cwd, "AGENTS.md");
880
+ if (!force && await this.exists(targetPath)) return;
881
+ const templatePath = path7.join(this.cwd, ".ai-workflow", "AGENTS.md");
882
+ if (await this.exists(templatePath)) {
883
+ let content = await fs5.readFile(templatePath, "utf8");
884
+ content = content.replace(/\.agents\/skills/g, ".codex/skills");
885
+ content = content.replace(/opencode\/commands/g, ".codex/prompts");
886
+ content = content.replace(/opencode\/docs\/policies/g, ".codex/docs/policies");
887
+ await fs5.writeFile(targetPath, content);
888
+ }
824
889
  }
825
890
  async exists(p) {
826
891
  try {
@@ -1256,7 +1321,7 @@ function resolveProfile(profile) {
1256
1321
  }
1257
1322
  return selectedProfile;
1258
1323
  }
1259
- async function writeInstallFiles(cwd, actions, selectedProfile, force, noOverwrite, backupRoot = ".ai-workflow-backups") {
1324
+ async function writeInstallFiles(cwd, actions, selectedProfile, platforms, force, noOverwrite, backupRoot = ".ai-workflow-backups") {
1260
1325
  const skipped = [];
1261
1326
  const backups = [];
1262
1327
  for (const action of actions) {
@@ -1272,7 +1337,7 @@ async function writeInstallFiles(cwd, actions, selectedProfile, force, noOverwri
1272
1337
  });
1273
1338
  backups.push(backupPath);
1274
1339
  }
1275
- const content = action.relativePath === ".ai-workflow/config.json" ? `${JSON.stringify(buildAiWorkflowConfig({ profile: selectedProfile }), null, 2)}
1340
+ const content = action.relativePath === ".ai-workflow/config.json" ? `${JSON.stringify(buildAiWorkflowConfig({ profile: selectedProfile, runtimes: platforms.length > 0 ? platforms : ["opencode"] }), null, 2)}
1276
1341
  ` : action.content;
1277
1342
  await writeFileSafe(action.absolutePath, content || "");
1278
1343
  }
@@ -1319,7 +1384,7 @@ async function writeSymlinks(cwd, linkEntries, force, backupRoot = ".ai-workflow
1319
1384
  }
1320
1385
  return { linkBackups, linkCreated };
1321
1386
  }
1322
- async function executePlatformMigrations(cwd, installRoot, platforms, claude, codex, antigravity) {
1387
+ async function executePlatformMigrations(cwd, installRoot, platforms, claude, codex, antigravity, force) {
1323
1388
  if (platforms.length === 0) return;
1324
1389
  console.log("ai-workflow: migrating to native platforms...");
1325
1390
  const agentsDir = path9.join(cwd, installRoot, "opencode/agents");
@@ -1332,7 +1397,7 @@ async function executePlatformMigrations(cwd, installRoot, platforms, claude, co
1332
1397
  }
1333
1398
  if (codex) {
1334
1399
  const adapter = new CodexAdapter({ cwd });
1335
- await adapter.deploy(installRoot);
1400
+ await adapter.deploy(installRoot, force);
1336
1401
  console.log("- codex: deployed AI Workflow Kit agents to .agents/, .codex/, and .github/ (native discovery enabled)");
1337
1402
  }
1338
1403
  if (antigravity) {
@@ -1433,7 +1498,7 @@ async function runInit({
1433
1498
  }
1434
1499
  return;
1435
1500
  }
1436
- const { skipped, backups } = await writeInstallFiles(cwd, actions, selectedProfile, force, noOverwrite, backupRoot);
1501
+ const { skipped, backups } = await writeInstallFiles(cwd, actions, selectedProfile, platforms, force, noOverwrite, backupRoot);
1437
1502
  const { linkBackups, linkCreated } = await writeSymlinks(cwd, linkEntries, force, backupRoot);
1438
1503
  await setupInternalSymlinks(cwd, installRoot);
1439
1504
  const opencodeResult = await mergeOpencodeConfig(cwd, { force, backupRoot });
@@ -1457,7 +1522,7 @@ async function runInit({
1457
1522
  }
1458
1523
  const gitignoreResult = await upsertGitignoreBlock(cwd, generatedIgnoreEntries);
1459
1524
  const scriptInjected = await injectScripts(cwd);
1460
- await executePlatformMigrations(cwd, installRoot, platforms, claude, codex, antigravity);
1525
+ await executePlatformMigrations(cwd, installRoot, platforms, claude, codex, antigravity, force);
1461
1526
  printInstallationSummary({
1462
1527
  selectedProfile,
1463
1528
  opencodeResult,
@@ -1542,8 +1607,10 @@ async function checkAiWorkflowConfig(cwd, state) {
1542
1607
  }
1543
1608
  if (config.runtime) {
1544
1609
  console.log(`PASS runtime: ${config.runtime}`);
1610
+ state.runtimes = config.runtime.split("+");
1545
1611
  } else {
1546
1612
  console.log(`NOTE runtime field not present in ${basename}`);
1613
+ state.runtimes = ["opencode"];
1547
1614
  }
1548
1615
  if (Array.isArray(config.managedBlocks)) {
1549
1616
  state.managedBlocks = config.managedBlocks;
@@ -1640,17 +1707,50 @@ async function checkPackageJson(cwd, state) {
1640
1707
  }
1641
1708
  }
1642
1709
  }
1710
+ async function checkCodexRuntime(cwd, state) {
1711
+ const checks = [
1712
+ { name: "root AGENTS.md exists", path: "AGENTS.md" },
1713
+ { name: ".codex/skills exists", path: ".codex/skills" },
1714
+ { name: ".codex prompts detected", path: ".codex/prompts" },
1715
+ { name: ".codex policies detected", path: ".codex/docs/policies" }
1716
+ ];
1717
+ for (const check of checks) {
1718
+ const ok = await exists(path10.join(cwd, check.path));
1719
+ if (ok) {
1720
+ console.log(`PASS ${check.name}`);
1721
+ } else {
1722
+ state.hasFailure = true;
1723
+ console.log(`FAIL ${check.name}`);
1724
+ }
1725
+ }
1726
+ const codexMdOk = await exists(path10.join(cwd, "CODEX.md"));
1727
+ if (codexMdOk) {
1728
+ console.log(`PASS root CODEX.md exists`);
1729
+ }
1730
+ if (state.runtimes.includes("codex")) {
1731
+ console.log("PASS config runtime includes codex");
1732
+ } else {
1733
+ state.hasFailure = true;
1734
+ console.log("FAIL config runtime includes codex");
1735
+ }
1736
+ }
1643
1737
  async function runDoctor({ cwd }) {
1644
1738
  const state = {
1645
1739
  hasFailure: false,
1646
1740
  hasWarning: false,
1647
- managedBlocks: []
1741
+ managedBlocks: [],
1742
+ runtimes: ["opencode"]
1648
1743
  };
1649
1744
  console.log("Doctor report:");
1650
- await checkOpenCodeRuntime(cwd, state);
1651
1745
  await checkRequiredFiles(cwd, state);
1652
1746
  await checkAiWorkflowConfig(cwd, state);
1653
- await checkOpencodeJson(cwd, state);
1747
+ if (state.runtimes.includes("opencode")) {
1748
+ await checkOpenCodeRuntime(cwd, state);
1749
+ await checkOpencodeJson(cwd, state);
1750
+ }
1751
+ if (state.runtimes.includes("codex")) {
1752
+ await checkCodexRuntime(cwd, state);
1753
+ }
1654
1754
  await checkPackageJson(cwd, state);
1655
1755
  const finalStatus = state.hasFailure ? "FAIL" : state.hasWarning ? "PASS_WITH_NOTES" : "PASS";
1656
1756
  console.log(`Final status: ${finalStatus}`);