5-phase-workflow 3.0.0 → 3.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.
Files changed (56) hide show
  1. package/README.md +31 -101
  2. package/bin/install.js +168 -176
  3. package/bin/sync-agents.js +59 -54
  4. package/docs/workflow-guide.md +35 -79
  5. package/package.json +2 -2
  6. package/src/agents/step-executor-agent.md +5 -4
  7. package/src/agents/step-orchestrator-agent.md +12 -12
  8. package/src/agents/verification-agent.md +7 -8
  9. package/src/codex-commands/plan.md +65 -0
  10. package/src/commands/5/address-review-findings.md +43 -52
  11. package/src/commands/5/analyze-feature.md +1 -1
  12. package/src/commands/5/configure.md +75 -179
  13. package/src/commands/5/eject.md +0 -1
  14. package/src/commands/5/implement.md +78 -68
  15. package/src/commands/5/lean-check.md +75 -0
  16. package/src/commands/5/reconfigure.md +48 -129
  17. package/src/commands/5/review.md +42 -14
  18. package/src/commands/5/synchronize-agents.md +1 -1
  19. package/src/commands/5/update.md +2 -2
  20. package/src/hooks/dependency-guard.js +150 -0
  21. package/src/hooks/statusline.js +5 -3
  22. package/src/references/configure-tables.md +0 -33
  23. package/src/settings.json +3 -4
  24. package/src/skills/baseline-conventions/SKILL.md +37 -0
  25. package/src/skills/cognitive-load/SKILL.md +52 -0
  26. package/src/skills/configure-agents-md/SKILL.md +72 -0
  27. package/src/skills/configure-rules/SKILL.md +146 -0
  28. package/src/skills/documentation-style/SKILL.md +32 -0
  29. package/src/skills/fowler-code-smells/SKILL.md +25 -0
  30. package/src/skills/review-style/SKILL.md +142 -0
  31. package/src/templates/AGENTS.md +31 -31
  32. package/src/templates/workflow/REVIEW-FINDINGS.md +2 -9
  33. package/src/workflows/5-implement.js +67 -92
  34. package/docs/findings.md +0 -361
  35. package/docs/progress.md +0 -102
  36. package/src/commands/5/apply-review-findings.md +0 -66
  37. package/src/commands/5/commit.md +0 -43
  38. package/src/commands/5/plan.md +0 -189
  39. package/src/commands/5/reply-pr-comments.md +0 -48
  40. package/src/commands/5/split.md +0 -86
  41. package/src/commands/5/triage-pr-comments.md +0 -70
  42. package/src/hooks/config-guard.js +0 -30
  43. package/src/skills/configure-docs-index/SKILL.md +0 -243
  44. package/src/skills/configure-skills/SKILL.md +0 -311
  45. package/src/skills/generate-readme/EXAMPLES.md +0 -168
  46. package/src/skills/generate-readme/SKILL.md +0 -122
  47. package/src/skills/generate-readme/TEMPLATE.md +0 -141
  48. package/src/skills/use-index/SKILL.md +0 -49
  49. package/src/templates/ARCHITECTURE.md +0 -33
  50. package/src/templates/CONCERNS.md +0 -33
  51. package/src/templates/CONVENTIONS.md +0 -74
  52. package/src/templates/TESTING.md +0 -24
  53. package/src/templates/workflow/FIX-PLAN.md +0 -55
  54. package/src/templates/workflow/PLAN-COMPACT.md +0 -42
  55. package/src/templates/workflow/PLAN.md +0 -76
  56. package/src/templates/workflow/REVIEW-SUMMARY.md +0 -53
package/bin/install.js CHANGED
@@ -323,27 +323,15 @@ function copyWorkflowHelperBins(targetPath) {
323
323
  }
324
324
  }
325
325
 
326
- // Remove directory recursively
326
+ // Remove a directory recursively. fs.rmSync removes a symlink itself and never follows it,
327
+ // so a link planted in a checkout cannot redirect the deletion outside the project.
327
328
  function removeDir(dir) {
328
- if (fs.existsSync(dir)) {
329
- const entries = fs.readdirSync(dir, { withFileTypes: true });
330
-
331
- for (const entry of entries) {
332
- const fullPath = path.join(dir, entry.name);
333
-
334
- if (entry.isDirectory()) {
335
- removeDir(fullPath);
336
- } else {
337
- fs.unlinkSync(fullPath);
338
- }
339
- }
340
-
341
- fs.rmdirSync(dir);
342
- }
329
+ fs.rmSync(dir, { recursive: true, force: true });
343
330
  }
344
331
 
345
- // Files removed from the package before manifest tracking existed.
346
- // This list is frozen — future removals are handled by manifest diffing.
332
+ // Files removed from the package over time. Upgrades from installs with a manifest find
333
+ // removals by manifest diffing; this list covers installs that predate the manifest, and
334
+ // uninstall uses it to clear leftovers.
347
335
  const LEGACY_REMOVED_FILES = [
348
336
  'agents/feature-planner.md',
349
337
  'agents/implementation-planner.md',
@@ -379,7 +367,35 @@ const LEGACY_REMOVED_FILES = [
379
367
  'commands/5/discuss-feature.md',
380
368
  'templates/workflow/STATE.json',
381
369
  'skills/5-unlock',
382
- 'skills/5-discuss-feature'
370
+ 'skills/5-discuss-feature',
371
+ // Plans live in .5/planning/; no codebase index, scan cache, generated docs, or split
372
+ 'commands/5/split.md',
373
+ 'skills/5-split',
374
+ 'skills/use-index',
375
+ 'skills/configure-docs-index',
376
+ 'templates/ARCHITECTURE.md',
377
+ 'templates/CONCERNS.md',
378
+ 'templates/CONVENTIONS.md',
379
+ 'templates/TESTING.md',
380
+ // Lean core: Claude Code covers commits, READMEs, PR replies, and per-pattern skills natively
381
+ 'commands/5/commit.md',
382
+ // Claude Code plans in native plan mode under the AGENTS.md Planning rules; $5-plan stays for Codex
383
+ 'commands/5/plan.md',
384
+ 'commands/5/apply-review-findings.md',
385
+ 'commands/5/triage-pr-comments.md',
386
+ 'commands/5/reply-pr-comments.md',
387
+ 'skills/5-commit',
388
+ 'skills/5-apply-review-findings',
389
+ 'skills/5-triage-pr-comments',
390
+ 'skills/5-reply-pr-comments',
391
+ 'skills/generate-readme',
392
+ 'skills/configure-skills',
393
+ 'hooks/config-guard.js',
394
+ 'templates/workflow/FIX-PLAN.md',
395
+ // Plans have no fixed shape; plan mode and $5-plan decide it
396
+ 'templates/workflow/PLAN.md',
397
+ 'templates/workflow/PLAN-COMPACT.md',
398
+ 'templates/workflow/REVIEW-SUMMARY.md'
383
399
  ];
384
400
 
385
401
  // Get list of workflow-owned files/directories (not user-created)
@@ -388,6 +404,9 @@ function getWorkflowManagedFiles() {
388
404
  // Commands: only the 5/ namespace
389
405
  commands: ['5'],
390
406
 
407
+ // Codex-only commands, installed as skills/5-{name}: Claude Code covers them natively
408
+ codexCommands: ['plan.md'],
409
+
391
410
  // Agents: separate agent files referenced by commands via agent: frontmatter
392
411
  agents: [
393
412
  'step-executor-agent.md',
@@ -402,10 +421,14 @@ function getWorkflowManagedFiles() {
402
421
 
403
422
  // Skills: specific skill directories
404
423
  skills: [
405
- 'configure-docs-index',
406
- 'configure-skills',
407
- 'generate-readme',
408
- 'use-index'
424
+ 'configure-agents-md',
425
+ 'configure-rules',
426
+ // Review styles: review-style runs one reviewer per style listed in its SKILL.md
427
+ 'review-style',
428
+ 'fowler-code-smells',
429
+ 'cognitive-load',
430
+ 'documentation-style',
431
+ 'baseline-conventions'
409
432
  ],
410
433
 
411
434
  // Hooks: specific hook files
@@ -413,7 +436,7 @@ function getWorkflowManagedFiles() {
413
436
  'statusline.js',
414
437
  'check-updates.js',
415
438
  'check-reconfig.js',
416
- 'config-guard.js'
439
+ 'dependency-guard.js'
417
440
  ],
418
441
 
419
442
  // References: lookup tables and schemas read on-demand by commands
@@ -428,18 +451,10 @@ function getWorkflowManagedFiles() {
428
451
 
429
452
  // Templates: specific template files
430
453
  templates: [
431
- // Project documentation templates
454
+ // Project instructions template
432
455
  'AGENTS.md',
433
- 'ARCHITECTURE.md',
434
- 'CONCERNS.md',
435
- 'CONVENTIONS.md',
436
- 'TESTING.md',
437
456
  // Workflow output templates
438
- 'workflow/PLAN.md',
439
- 'workflow/PLAN-COMPACT.md',
440
- 'workflow/REVIEW-FINDINGS.md',
441
- 'workflow/REVIEW-SUMMARY.md',
442
- 'workflow/FIX-PLAN.md'
457
+ 'workflow/REVIEW-FINDINGS.md'
443
458
  ]
444
459
  };
445
460
  }
@@ -478,7 +493,7 @@ function getFileManifest() {
478
493
  manifest.push(`hooks/${hook}`);
479
494
  }
480
495
 
481
- // Templates are files (may include nested paths like workflow/PLAN.md)
496
+ // Templates are files (may include nested paths like workflow/REVIEW-FINDINGS.md)
482
497
  for (const template of managed.templates) {
483
498
  manifest.push(`templates/${template}`);
484
499
  }
@@ -538,14 +553,6 @@ function convertClaudeSetupCommandsToCodexNotes(content) {
538
553
  .replace(
539
554
  /- If user selects "Install now": execute the install command/g,
540
555
  '- If user selects "Install now": explain that Codex cannot run the Claude Code installer command; leave `tools.context7.available = false` unless Context7 is already detected'
541
- )
542
- .replace(
543
- /1\. "Install now \(recommended\)" — run `claude plugin install skill-creator@claude-plugins-official` via Bash/g,
544
- '1. "Install now" — not supported automatically in Codex; install an equivalent skill authoring workflow outside this command, then rerun configuration'
545
- )
546
- .replace(
547
- /- If user selects "Install now": execute the install command, then set `tools\.skillCreator\.available = true` in the config/g,
548
- '- If user selects "Install now": explain that Codex cannot run the Claude Code plugin installer; leave `tools.skillCreator.available = false` unless an equivalent tool is already detected'
549
556
  );
550
557
  }
551
558
 
@@ -566,6 +573,7 @@ This skill was authored for Claude Code. Map these tool references:
566
573
  | \`Agent(subagent_type="Explore")\` | \`spawn_agent(agent_type="explorer", model="gpt-5.4-mini", reasoning_effort="low", message="...")\` |
567
574
  | \`Agent(prompt="...", model="haiku")\` | \`spawn_agent(model="gpt-5.4-mini", reasoning_effort="low", message="...")\` |
568
575
  | \`Agent(prompt="...", model="sonnet")\` | \`spawn_agent(model="gpt-5.4", reasoning_effort="medium", message="...")\` |
576
+ | \`Agent(prompt="...", model="opus", effort="medium")\` | \`spawn_agent(model="gpt-5.4", reasoning_effort="high", message="...")\` |
569
577
  | \`Agent(prompt="...")\` | \`spawn_agent(model="gpt-5.4-mini", reasoning_effort="low", message="...")\` unless the prompt explicitly requires complex reasoning |
570
578
  | \`Read\` | \`read_file\` |
571
579
  | \`Write\` | \`write_file\` |
@@ -573,9 +581,10 @@ This skill was authored for Claude Code. Map these tool references:
573
581
  | \`Bash\` | \`shell\` |
574
582
  | \`Glob\` | \`glob\` / \`list_directory\` |
575
583
  | \`Grep\` | \`grep\` / \`search\` |
576
- | \`TaskCreate/TaskUpdate\` | Track progress internally |
577
584
  | \`Workflow\` | Not available — run the command's prose fallback loop instead |
578
585
  | \`Skill(skill="code-review")\` | Not available — run the command's prose fallback loop instead |
586
+ | \`Skill(skill="security-review")\` | Not available — skip it; the prose review fallback of \`$5-review\` covers security |
587
+ | \`Skill(skill="review-style", args="...")\` | Read \`.codex/skills/review-style/SKILL.md\` and follow it with the same arguments |
579
588
  | \`EnterPlanMode\` | Not available — run the command's prose fallback loop instead |
580
589
 
581
590
  ## Model Mapping (single source of truth)
@@ -585,28 +594,30 @@ When a skill, plan, or execution-graph component names a model, map it to Codex
585
594
  |-------------|-------------|------------------|
586
595
  | \`haiku\` (or unset) | \`gpt-5.4-mini\` | \`low\` |
587
596
  | \`sonnet\` | \`gpt-5.4\` | \`medium\` |
597
+ | \`opus\` | \`gpt-5.4\` | \`high\` |
588
598
  | Explore / explorer agent | \`gpt-5.4-mini\` (\`agent_type: explorer\`) | \`low\` |
589
599
 
590
600
  This table is authoritative — skill bodies do not repeat per-call model mappings.
591
601
 
592
602
  ## Codex Token Budget
593
603
  - Default to \`gpt-5.4-mini\` with \`reasoning_effort: low\` for exploration, orchestration, simple implementation, and mechanical file edits.
594
- - Use \`gpt-5.4\` with \`reasoning_effort: medium\` only for complex logic, cross-module behavior, security-sensitive changes, data migrations, final verification with meaningful logic review, or retries after failure.
604
+ - Use \`gpt-5.4\` with \`reasoning_effort: medium\` for ordinary logic and final verification with meaningful logic review.
605
+ - Use \`gpt-5.4\` with \`reasoning_effort: high\` only for complex logic, cross-module behavior, security-sensitive changes, data migrations, public API contracts, or retries after failure.
595
606
  - Use stronger models only when a previous cheaper attempt failed for reasoning reasons.
596
607
  - Keep the parent skill context lean: delegate read-heavy exploration to explorer agents and pass only compact findings, target paths, pattern references, and command summaries between agents.
597
608
 
598
609
  ## Guard Rules (Codex has no plan mode)
599
610
  Claude Code enforces these at the harness level via native plan mode. Codex has no equivalent, so honour them yourself while running \`$5-plan\`, **until the user approves the plan**:
600
- - Do NOT write to any file outside \`.5/\`
601
- - Do NOT write source code — only the unified plan and scan cache
611
+ - Do NOT write any file — the plan is written only after approval
612
+ - Do NOT write source code
602
613
  - Do NOT spawn implementation agents — only Explore/research agents
603
614
 
604
- After approval, \`$5-plan\` implements compact plans inline and hands larger ones to \`$5-implement\`.
615
+ After approval, \`$5-plan\` saves the plan in \`.5/planning/\` and hands it to \`$5-implement\`.
605
616
 
606
617
  ## Update & Migration Notices (replaces statusline hooks)
607
618
  At the very start of this skill, before doing anything else, read these two files if they exist:
608
619
  - \`.5/.update-cache.json\` — if \`latestAvailableVersion\` is set, compare it to \`packageVersion\` in \`.5/version.json\`. If a newer version is available, tell the user: "foifi update available: <version> — run \`npx foifi --codex --upgrade\` to update."
609
- - \`.5/.migration-v2\` — if this file exists, tell the user: "You upgraded from foifi v1 to v2. Run \`$5-reconfigure\` to update your project configuration."
620
+ - \`.5/.migration-v*\` — if a file such as \`.5/.migration-v4\` exists, tell the user: "You upgraded foifi to a new major version. Run \`$5-reconfigure\` to update your project configuration."
610
621
 
611
622
  Show each applicable notice once at the top of your response, then continue with the skill normally. Do not abort the skill because of a notice.
612
623
  </codex_skill_adapter>`;
@@ -644,20 +655,29 @@ function convertClaudeSkillToCodexSkill(content) {
644
655
  return convertClaudeToCodexMarkdown(content);
645
656
  }
646
657
 
658
+ // Command files that become Codex skills: the shared commands/5/ plus the Codex-only codex-commands/
659
+ // (Claude Code covers those natively, e.g. plan mode replaces /5:plan).
660
+ function getCodexCommandFiles(sourcePath) {
661
+ const toEntry = (dir, file) => ({ name: file.replace('.md', ''), file: path.join(dir, file) });
662
+ const sharedDir = path.join(sourcePath, 'commands', '5');
663
+ const shared = fs.existsSync(sharedDir)
664
+ ? fs.readdirSync(sharedDir).filter(f => f.endsWith('.md')).map(f => toEntry(sharedDir, f))
665
+ : [];
666
+ const codexDir = path.join(sourcePath, 'codex-commands');
667
+ const codexOnly = getWorkflowManagedFiles().codexCommands
668
+ .filter(f => fs.existsSync(path.join(codexDir, f)))
669
+ .map(f => toEntry(codexDir, f));
670
+ return [...shared, ...codexOnly];
671
+ }
672
+
647
673
  // Get file manifest for Codex installs (skills-based structure)
648
674
  function getCodexFileManifest() {
649
675
  const managed = getWorkflowManagedFiles();
650
676
  const manifest = [];
651
677
 
652
- // Commands become skills
653
- // Each command file in commands/5/ becomes skills/5-{name}/SKILL.md
654
- const commandsSrc = path.join(getSourcePath(), 'commands', '5');
655
- if (fs.existsSync(commandsSrc)) {
656
- const files = fs.readdirSync(commandsSrc).filter(f => f.endsWith('.md'));
657
- for (const file of files) {
658
- const name = file.replace('.md', '');
659
- manifest.push(`skills/5-${name}`);
660
- }
678
+ // Commands become skills: each command file becomes skills/5-{name}/SKILL.md
679
+ for (const { name } of getCodexCommandFiles(getSourcePath())) {
680
+ manifest.push(`skills/5-${name}`);
661
681
  }
662
682
 
663
683
  // Original skills also become Codex skills
@@ -688,9 +708,6 @@ function getCodexFileManifest() {
688
708
  }
689
709
  }
690
710
 
691
- // Instructions file
692
- manifest.push('instructions.md');
693
-
694
711
  return manifest;
695
712
  }
696
713
 
@@ -790,7 +807,7 @@ function selectiveUpdate(targetPath, sourcePath) {
790
807
  const src = path.join(templatesSrc, template);
791
808
  const dest = path.join(templatesDest, template);
792
809
  if (fs.existsSync(src)) {
793
- // Ensure parent directory exists for nested paths (e.g., workflow/PLAN.md)
810
+ // Ensure parent directory exists for nested paths (e.g., workflow/REVIEW-FINDINGS.md)
794
811
  const destDir = path.dirname(dest);
795
812
  if (!fs.existsSync(destDir)) {
796
813
  fs.mkdirSync(destDir, { recursive: true });
@@ -856,9 +873,12 @@ function cleanupOrphanedFiles(targetPath, dataDir) {
856
873
 
857
874
  if (oldManifest) {
858
875
  // Manifest exists: diff old vs current, delete orphans
876
+ const installRoot = path.resolve(targetPath) + path.sep;
859
877
  for (const entry of oldManifest) {
860
878
  if (!currentSet.has(entry)) {
861
- const fullPath = path.join(targetPath, entry);
879
+ const fullPath = path.resolve(targetPath, entry);
880
+ // version.json may come from the checkout, so an entry must stay inside the install dir
881
+ if (!fullPath.startsWith(installRoot)) continue;
862
882
  if (fs.existsSync(fullPath)) {
863
883
  const stat = fs.statSync(fullPath);
864
884
  if (stat.isDirectory()) {
@@ -890,7 +910,7 @@ function cleanupOrphanedFiles(targetPath, dataDir) {
890
910
  // Ensure .5/.gitignore exists and contains transient runtime files
891
911
  function ensureDotFiveGitignore(dataDir) {
892
912
  const gitignorePath = path.join(dataDir, '.gitignore');
893
- const entries = ['.update-cache.json', '.migration-v*', '.reconfig-reminder'];
913
+ const entries = ['.update-cache.json', '.migration-v*', '.reconfig-reminder', '.dependency-guard.json'];
894
914
  if (fs.existsSync(gitignorePath)) {
895
915
  let content = fs.readFileSync(gitignorePath, 'utf8');
896
916
  for (const entry of entries) {
@@ -1009,7 +1029,7 @@ function mergeHookArrays(targetArr, sourceArr) {
1009
1029
  // Hook event keys that contain arrays of hook entries
1010
1030
  const HOOK_ARRAY_KEYS = new Set([
1011
1031
  'PreToolUse', 'PostToolUse', 'SessionStart', 'SessionEnd',
1012
- 'PreCompact', 'PostCompact'
1032
+ 'PreCompact', 'PostCompact', 'Stop', 'SubagentStop', 'UserPromptSubmit'
1013
1033
  ]);
1014
1034
 
1015
1035
  // Deep merge for settings.json
@@ -1047,7 +1067,7 @@ function mergeSettings(targetPath, sourcePath) {
1047
1067
 
1048
1068
  if (fs.existsSync(targetSettings)) {
1049
1069
  const existingSettings = JSON.parse(fs.readFileSync(targetSettings, 'utf8'));
1050
- const merged = deepMerge(newSettings, existingSettings);
1070
+ const merged = deepMerge(existingSettings, newSettings);
1051
1071
  fs.writeFileSync(targetSettings, JSON.stringify(merged, null, 2));
1052
1072
  log.info('Merged settings with existing configuration');
1053
1073
  } else {
@@ -1064,35 +1084,35 @@ function checkExistingInstallation(targetPath) {
1064
1084
  const legacyMarkerFile = path.join(targetPath, 'skills', '5-plan-feature', 'SKILL.md');
1065
1085
  return fs.existsSync(markerFile) || fs.existsSync(legacyMarkerFile);
1066
1086
  }
1067
- const markerFile = path.join(targetPath, 'commands', '5', 'plan.md');
1068
- const legacyMarkerFile = path.join(targetPath, 'commands', '5', 'plan-feature.md');
1069
- return fs.existsSync(markerFile) || fs.existsSync(legacyMarkerFile);
1087
+ // plan.md and plan-feature.md mark installs from before plan mode replaced /5:plan
1088
+ return ['implement.md', 'plan.md', 'plan-feature.md']
1089
+ .some(file => fs.existsSync(path.join(targetPath, 'commands', '5', file)));
1070
1090
  }
1071
1091
 
1072
1092
  // Helper to show commands
1073
1093
  function showCommandsHelp(isGlobal) {
1074
1094
  if (activeRuntime === 'codex') {
1075
1095
  log.info('Available skills (invoke with $ prefix in Codex):');
1076
- log.info(' $5-plan - Create or refine a unified plan');
1077
- log.info(' $5-split - Split plan into smaller plans');
1096
+ log.info(' $5-plan - Create or refine a plan');
1078
1097
  log.info(' $5-implement - Execute implementation + verification');
1079
- log.info(' $5-review - Code review');
1080
- log.info(' $5-commit - Create a templated git commit');
1081
- log.info(' $5-address-review-findings - Decide review findings & PR comments');
1098
+ log.info(' $5-review - Code and standards review');
1099
+ log.info(' $5-lean-check - Check a diff for scope drift/over-engineering');
1100
+ log.info(' $5-address-review-findings - Decide on review findings, apply the fixes');
1101
+ log.info(' $5-analyze-feature - Document a feature with mermaid diagrams');
1082
1102
  log.info(' $5-configure - Interactive project setup');
1083
- log.info(' $5-reconfigure - Refresh docs/skills (no Q&A)');
1103
+ log.info(' $5-reconfigure - Refresh the AGENTS.md block and rules (no Q&A)');
1084
1104
  log.info(' $5-eject - Eject from update mechanism');
1085
1105
  log.info(' $5-synchronize-agents - Sync user content between runtimes');
1086
1106
  } else {
1107
+ log.info('Plan in native plan mode (shift+tab); AGENTS.md shapes the plan.');
1087
1108
  log.info('Available commands:');
1088
- log.info(' /5:plan - Create or refine a unified plan');
1089
- log.info(' /5:split - Split plan into smaller plans');
1090
1109
  log.info(' /5:implement - Execute implementation + verification');
1091
- log.info(' /5:review - Code review');
1092
- log.info(' /5:commit - Create a templated git commit');
1093
- log.info(' /5:address-review-findings - Decide review findings & PR comments');
1110
+ log.info(' /5:review - Code and standards review');
1111
+ log.info(' /5:lean-check - Check a diff for scope drift/over-engineering');
1112
+ log.info(' /5:address-review-findings - Decide on review findings, apply the fixes');
1113
+ log.info(' /5:analyze-feature - Document a feature with mermaid diagrams');
1094
1114
  log.info(' /5:configure - Interactive project setup');
1095
- log.info(' /5:reconfigure - Refresh docs/skills (no Q&A)');
1115
+ log.info(' /5:reconfigure - Refresh the AGENTS.md block and rules (no Q&A)');
1096
1116
  log.info(' /5:eject - Eject from update mechanism');
1097
1117
  log.info(' /5:synchronize-agents - Sync user content between runtimes');
1098
1118
  }
@@ -1138,10 +1158,8 @@ function performFreshInstall(targetPath, sourcePath, isGlobal) {
1138
1158
  log.info('This will:');
1139
1159
  log.info(' • Detect your project type and build commands');
1140
1160
  log.info(' • Set up ticket tracking conventions');
1141
- log.info(' • Generate comprehensive documentation (CLAUDE.md)');
1142
- log.info(' • Create project-specific skills');
1143
- log.info('');
1144
- log.info('Tip: Configure will offer to install helpful plugins like skill-creator');
1161
+ log.info(' • Add the workflow rules to AGENTS.md as one marked block, linking your repository standards');
1162
+ log.info(' • Create file-scoped rules from your conventions');
1145
1163
 
1146
1164
  showCommandsHelp(isGlobal);
1147
1165
  }
@@ -1192,24 +1210,31 @@ function removeContextForkFromSkills(targetPath) {
1192
1210
  } catch (e) {}
1193
1211
  }
1194
1212
 
1195
- // Remove the plan-guard PreToolUse hook entry from an existing settings.json.
1196
- // Native plan mode enforces read-only planning at the harness level, so the hook
1197
- // is gone. Claude Code only — Codex never had a settings.json.
1198
- function removePlanGuardHook(targetPath) {
1213
+ // Remove retired PreToolUse hook entries from an existing settings.json. Native plan mode
1214
+ // replaced plan-guard; config-guard blocked every Agent call in sessions outside the workflow.
1215
+ // Claude Code only — Codex never had a settings.json.
1216
+ const RETIRED_HOOKS = ['plan-guard.js', 'config-guard.js'];
1217
+
1218
+ function removeRetiredHooks(targetPath) {
1199
1219
  const settingsFile = path.join(targetPath, 'settings.json');
1200
1220
  if (!fs.existsSync(settingsFile)) return;
1201
1221
  try {
1202
1222
  const settings = JSON.parse(fs.readFileSync(settingsFile, 'utf8'));
1203
1223
  const pre = settings.hooks && settings.hooks.PreToolUse;
1204
1224
  if (!Array.isArray(pre)) return;
1205
- const kept = pre.filter(entry =>
1206
- !(entry.hooks || []).some(h => typeof h.command === 'string' && h.command.includes('plan-guard.js')));
1207
- if (kept.length === pre.length) return;
1225
+ const isRetired = h => typeof h.command === 'string' && RETIRED_HOOKS.some(hook => h.command.includes(hook));
1226
+ if (!pre.some(entry => (entry.hooks || []).some(isRetired))) return;
1227
+ // Drop only the retired hooks; an entry survives while it still holds the user's own hooks
1228
+ const kept = pre
1229
+ .map(entry => (entry.hooks || []).some(isRetired)
1230
+ ? { ...entry, hooks: entry.hooks.filter(h => !isRetired(h)) }
1231
+ : entry)
1232
+ .filter(entry => !Array.isArray(entry.hooks) || entry.hooks.length);
1208
1233
  if (kept.length) settings.hooks.PreToolUse = kept;
1209
1234
  else delete settings.hooks.PreToolUse;
1210
1235
  if (settings.hooks && !Object.keys(settings.hooks).length) delete settings.hooks;
1211
1236
  fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2));
1212
- log.info('Removed plan-guard hook from settings.json (native plan mode replaces it)');
1237
+ log.info('Removed retired guard hooks from settings.json');
1213
1238
  } catch (e) {}
1214
1239
  }
1215
1240
 
@@ -1224,6 +1249,25 @@ function removePlanningActiveMarker(dataDir) {
1224
1249
  } catch (e) {}
1225
1250
  }
1226
1251
 
1252
+ // Move .5/features/{name}/plan.md to .5/planning/{name}.md. Plans now live where native plan
1253
+ // mode saves them, and /5:implement finds them by their `feature` frontmatter. The .5/ data
1254
+ // is shared, so performUpdate() and performCodexUpdate() both run this.
1255
+ function movePlansToPlanningDir(dataDir) {
1256
+ const featuresDir = path.join(dataDir, 'features');
1257
+ if (!fs.existsSync(featuresDir)) return;
1258
+ const planningDir = path.join(dataDir, 'planning');
1259
+ try {
1260
+ for (const feature of fs.readdirSync(featuresDir)) {
1261
+ const planFile = path.join(featuresDir, feature, 'plan.md');
1262
+ const target = path.join(planningDir, `${feature}.md`);
1263
+ if (!fs.existsSync(planFile) || fs.existsSync(target)) continue;
1264
+ fs.mkdirSync(planningDir, { recursive: true });
1265
+ fs.renameSync(planFile, target);
1266
+ log.info(`Moved plan: features/${feature}/plan.md → planning/${feature}.md`);
1267
+ }
1268
+ } catch (e) {}
1269
+ }
1270
+
1227
1271
  // Perform update (preserves user-created files, updates .5/ data directory)
1228
1272
  function performUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
1229
1273
  log.header(`Updating from ${versionInfo.installed || 'legacy'} to ${versionInfo.available}`);
@@ -1245,10 +1289,13 @@ function performUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
1245
1289
  // Strip `context: fork` from generated skills — caused infinite loops
1246
1290
  removeContextForkFromSkills(targetPath);
1247
1291
 
1248
- // Native plan mode replaces the plan-guard hook and its marker file
1249
- removePlanGuardHook(targetPath);
1292
+ // Native plan mode replaces the plan-guard hook and its marker file; config-guard is retired
1293
+ removeRetiredHooks(targetPath);
1250
1294
  removePlanningActiveMarker(dataDir);
1251
1295
 
1296
+ // Plans moved from .5/features/{name}/plan.md to .5/planning/{name}.md
1297
+ movePlansToPlanningDir(dataDir);
1298
+
1252
1299
  // Flag v1 → v2 major upgrade so statusline can prompt for reconfigure
1253
1300
  const prevMajor = versionInfo.installed ? parseInt(versionInfo.installed.split('.')[0], 10) : 0;
1254
1301
  const newMajor = versionInfo.available ? parseInt(versionInfo.available.split('.')[0], 10) : 0;
@@ -1278,65 +1325,15 @@ function performUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
1278
1325
 
1279
1326
  // ── Codex install/update/uninstall ──────────────────────────────────────────
1280
1327
 
1281
- // Generate instructions.md for Codex (replaces hooks + settings.json)
1282
- function generateCodexInstructions(targetPath) {
1283
- const content = `# dev-workflow — Codex Instructions
1284
-
1285
- This file is managed by the dev-workflow installer. It provides Codex with
1286
- the context it needs to run the workflow skills correctly.
1287
-
1288
- ## Workflow Overview
1289
-
1290
- The workflow provides structured feature development:
1291
-
1292
- 1. **Plan** (\`$5-plan\`) — Requirements, discovery, and unified plan
1293
- 2. **Implement** (\`$5-implement\`) — Orchestrated implementation with inline verification
1294
- 3. **Review** (\`$5-review\`) — Code review
1295
-
1296
- ## Data Directory
1297
-
1298
- All workflow state lives in \`.5/\` at the project root:
1299
- - \`.5/config.json\` — Project configuration
1300
- - \`.5/features/{name}/plan.md\` — Unified plan
1301
- - \`.5/features/{name}/state.json\` — Implementation resume state
1302
-
1303
- ## Guard Rules
1304
-
1305
- During the planning phase ($5-plan), until the user approves the plan:
1306
- - Do NOT write files outside \`.5/\`
1307
- - Do NOT write source code — only the unified plan and scan cache
1308
-
1309
- ## Configuration
1310
-
1311
- Run \`$5-configure\` after installation to set up your project.
1312
-
1313
- ## Codex Token Budget
1314
-
1315
- Workflow skills use \`gpt-5.4-mini\` with low reasoning for exploration, orchestration, and simple executors by default. They escalate to \`gpt-5.4\` with medium reasoning only for complex logic, security-sensitive work, data migrations, public API changes, final verification that needs logic review, or retries after a cheaper attempt fails.
1316
-
1317
- ## Templates & References
1318
-
1319
- Templates are in \`.codex/templates/\` and references in \`.codex/references/\`.
1320
- Skills reference these paths for output formatting.
1321
- `;
1322
-
1323
- fs.writeFileSync(path.join(targetPath, 'instructions.md'), content);
1324
- log.success('Generated instructions.md');
1325
- }
1326
-
1327
1328
  // Install commands as Codex skills
1328
1329
  function installCodexSkills(targetPath, sourcePath) {
1329
- const commandsSrc = path.join(sourcePath, 'commands', '5');
1330
1330
  const skillsDest = path.join(targetPath, 'skills');
1331
+ const files = getCodexCommandFiles(sourcePath);
1332
+ if (files.length === 0) return;
1331
1333
 
1332
- if (!fs.existsSync(commandsSrc)) return;
1333
-
1334
- const files = fs.readdirSync(commandsSrc).filter(f => f.endsWith('.md'));
1335
-
1336
- for (const file of files) {
1337
- const name = file.replace('.md', '');
1334
+ for (const { name, file } of files) {
1338
1335
  const skillName = `5-${name}`;
1339
- const content = fs.readFileSync(path.join(commandsSrc, file), 'utf8');
1336
+ const content = fs.readFileSync(file, 'utf8');
1340
1337
  const converted = convertClaudeCommandToCodexSkill(content, skillName);
1341
1338
 
1342
1339
  const skillDir = path.join(skillsDest, skillName);
@@ -1347,7 +1344,7 @@ function installCodexSkills(targetPath, sourcePath) {
1347
1344
  }
1348
1345
  log.success(`Installed ${files.length} workflow skills`);
1349
1346
 
1350
- // Also convert and install original workflow skills (configure-docs-index, configure-skills, generate-readme)
1347
+ // Also convert and install the workflow's own skills (configure-*, review styles)
1351
1348
  const managed = getWorkflowManagedFiles();
1352
1349
  for (const skill of managed.skills) {
1353
1350
  const skillSrc = path.join(sourcePath, 'skills', skill);
@@ -1421,9 +1418,6 @@ function performCodexFreshInstall(targetPath, sourcePath, isGlobal) {
1421
1418
  copyWorkflowHelperBins(targetPath);
1422
1419
  log.success('Installed bin/ (workflow helper binaries)');
1423
1420
 
1424
- // Generate instructions.md (replaces hooks + settings.json)
1425
- generateCodexInstructions(targetPath);
1426
-
1427
1421
  // Initialize version tracking (shared .5/ directory)
1428
1422
  initializeVersionJson(isGlobal);
1429
1423
 
@@ -1435,8 +1429,7 @@ function performCodexFreshInstall(targetPath, sourcePath, isGlobal) {
1435
1429
  log.info('This will:');
1436
1430
  log.info(' • Detect your project type and build commands');
1437
1431
  log.info(' • Set up ticket tracking conventions');
1438
- log.info(' • Generate comprehensive documentation');
1439
- log.info(' • Create project-specific skills');
1432
+ log.info(' • Add the workflow rules to AGENTS.md as one marked block, linking your repository standards');
1440
1433
 
1441
1434
  showCommandsHelp(isGlobal);
1442
1435
  }
@@ -1448,14 +1441,9 @@ function codexSelectiveUpdate(targetPath, sourcePath) {
1448
1441
  const skillsDest = path.join(targetPath, 'skills');
1449
1442
 
1450
1443
  // Remove workflow command skills (5-*)
1451
- const commandsSrc = path.join(sourcePath, 'commands', '5');
1452
- if (fs.existsSync(commandsSrc)) {
1453
- const files = fs.readdirSync(commandsSrc).filter(f => f.endsWith('.md'));
1454
- for (const file of files) {
1455
- const name = file.replace('.md', '');
1456
- const skillDir = path.join(skillsDest, `5-${name}`);
1457
- if (fs.existsSync(skillDir)) removeDir(skillDir);
1458
- }
1444
+ for (const { name } of getCodexCommandFiles(sourcePath)) {
1445
+ const skillDir = path.join(skillsDest, `5-${name}`);
1446
+ if (fs.existsSync(skillDir)) removeDir(skillDir);
1459
1447
  }
1460
1448
 
1461
1449
  // Remove utility skills
@@ -1482,9 +1470,6 @@ function codexSelectiveUpdate(targetPath, sourcePath) {
1482
1470
  // Update helper binaries used by runtime commands
1483
1471
  copyWorkflowHelperBins(targetPath);
1484
1472
  log.success('Updated bin/ helper binaries');
1485
-
1486
- // Regenerate instructions.md
1487
- generateCodexInstructions(targetPath);
1488
1473
  }
1489
1474
 
1490
1475
  // Codex update
@@ -1504,6 +1489,9 @@ function performCodexUpdate(targetPath, sourcePath, isGlobal, versionInfo) {
1504
1489
  // The plan-guard marker is shared .5/ state; Codex has no settings.json hook to remove
1505
1490
  removePlanningActiveMarker(dataDir);
1506
1491
 
1492
+ // Plans moved from .5/features/{name}/plan.md to .5/planning/{name}.md
1493
+ movePlansToPlanningDir(dataDir);
1494
+
1507
1495
  // Flag v1 → v2 major upgrade so skills can prompt for reconfigure
1508
1496
  const prevMajor = versionInfo.installed ? parseInt(versionInfo.installed.split('.')[0], 10) : 0;
1509
1497
  const newMajor = versionInfo.available ? parseInt(versionInfo.available.split('.')[0], 10) : 0;
@@ -1540,17 +1528,21 @@ function codexUninstall() {
1540
1528
  return;
1541
1529
  }
1542
1530
 
1531
+ // Remove workflow files retired from the package, which the current source no longer lists
1532
+ for (const entry of LEGACY_REMOVED_FILES) {
1533
+ const fullPath = path.join(targetPath, entry);
1534
+ if (!fs.existsSync(fullPath)) continue;
1535
+ if (fs.statSync(fullPath).isDirectory()) removeDir(fullPath);
1536
+ else fs.unlinkSync(fullPath);
1537
+ log.info(`Removed legacy orphan: ${entry}`);
1538
+ }
1539
+
1543
1540
  // Remove workflow command skills (5-*)
1544
- const commandsSrc = path.join(getSourcePath(), 'commands', '5');
1545
- if (fs.existsSync(commandsSrc)) {
1546
- const files = fs.readdirSync(commandsSrc).filter(f => f.endsWith('.md'));
1547
- for (const file of files) {
1548
- const name = file.replace('.md', '');
1549
- const skillDir = path.join(targetPath, 'skills', `5-${name}`);
1550
- if (fs.existsSync(skillDir)) removeDir(skillDir);
1551
- }
1552
- log.success('Removed workflow skills');
1541
+ for (const { name } of getCodexCommandFiles(getSourcePath())) {
1542
+ const skillDir = path.join(targetPath, 'skills', `5-${name}`);
1543
+ if (fs.existsSync(skillDir)) removeDir(skillDir);
1553
1544
  }
1545
+ log.success('Removed workflow skills');
1554
1546
 
1555
1547
  // Remove utility skills
1556
1548
  const managed = getWorkflowManagedFiles();
@@ -1596,7 +1588,7 @@ function codexUninstall() {
1596
1588
  log.success('Removed workflow helper binaries');
1597
1589
  }
1598
1590
 
1599
- // Remove instructions.md
1591
+ // Remove instructions.md left by earlier versions (Codex never read it; AGENTS.md carries the rules)
1600
1592
  const instructionsPath = path.join(targetPath, 'instructions.md');
1601
1593
  if (fs.existsSync(instructionsPath)) {
1602
1594
  fs.unlinkSync(instructionsPath);