@haposoft/cafekit 0.16.0-rc.6 → 0.16.0-rc.8

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 (87) hide show
  1. package/README.md +21 -58
  2. package/bin/__tests__/change-firewall.semantic-firewall.test.js +4 -5
  3. package/bin/__tests__/codex-hooks.test.js +382 -0
  4. package/bin/__tests__/codex-native.test.js +579 -80
  5. package/bin/__tests__/develop-contract.test.js +155 -76
  6. package/bin/__tests__/installer-safety.test.js +19 -154
  7. package/bin/__tests__/package-inventory.test.js +494 -26
  8. package/bin/__tests__/release-preflight.semantic-firewall.test.js +2 -2
  9. package/bin/__tests__/validator-grounding.test.js +11 -11
  10. package/bin/install.js +2 -7
  11. package/bin/lib/context.js +0 -45
  12. package/bin/lib/copy-utils.js +1 -1
  13. package/bin/lib/i18n.js +0 -3
  14. package/bin/lib/manifest.js +1 -1
  15. package/bin/phases/claude-runtime.js +1 -3
  16. package/bin/phases/codex-runtime.js +4 -2
  17. package/bin/phases/copy-payload.js +3 -15
  18. package/bin/phases/post-install.js +5 -17
  19. package/bin/phases/root-config.js +2 -3
  20. package/bin/phases/select-platform.js +2 -5
  21. package/bin/phases/summary.js +0 -1
  22. package/package.json +2 -5
  23. package/src/claude/CLAUDE.md +19 -6
  24. package/src/claude/agents/project-manager.md +41 -9
  25. package/src/claude/agents/spec-maker.md +82 -155
  26. package/src/claude/gitignore +1 -1
  27. package/src/claude/hooks/__tests__/spec-gate.test.js +238 -0
  28. package/src/claude/hooks/__tests__/state.test.js +249 -3
  29. package/src/claude/hooks/lib/context.cjs +1 -1
  30. package/src/claude/hooks/lib/detect.cjs +1 -1
  31. package/src/claude/hooks/spec-gate.cjs +44 -9
  32. package/src/claude/hooks/spec-state.cjs +51 -13
  33. package/src/claude/hooks/task-scaffold-guard.cjs +1 -1
  34. package/src/claude/migration-manifest.json +17 -3
  35. package/src/claude/rules/manage-docs.md +43 -24
  36. package/src/claude/rules/state-sync.md +57 -62
  37. package/src/claude/rules/workflow.md +30 -13
  38. package/src/claude/scripts/change-firewall.cjs +2 -2
  39. package/src/claude/scripts/generate-skill-catalog.cjs +0 -1
  40. package/src/claude/scripts/spec-receipt.cjs +196 -1
  41. package/src/claude/scripts/spec-resolver.cjs +428 -0
  42. package/src/claude/skills/develop/SKILL.md +89 -125
  43. package/src/claude/skills/develop/references/parallel-waves.md +75 -162
  44. package/src/claude/skills/develop/references/quality-gate.md +61 -121
  45. package/src/claude/skills/develop/references/subagent-patterns.md +31 -38
  46. package/src/claude/skills/question/SKILL.md +1 -1
  47. package/src/claude/skills/specs/SKILL.md +152 -204
  48. package/src/claude/skills/specs/references/review.md +124 -243
  49. package/src/claude/skills/specs/references/templates.md +202 -0
  50. package/src/claude/skills/sync/SKILL.md +66 -90
  51. package/src/claude/skills/sync/references/sync-protocols.md +62 -83
  52. package/src/codex/AGENTS.md +20 -7
  53. package/src/codex/hooks/lib/spec-receipt.cjs +18 -0
  54. package/src/codex/hooks/lib/spec-utils.cjs +25 -0
  55. package/src/codex/hooks/spec-gate.cjs +46 -16
  56. package/src/codex/hooks/spec-state.cjs +54 -16
  57. package/src/codex/rules/state-sync.md +57 -61
  58. package/src/common/AGENTS.md +8 -1
  59. package/bin/__tests__/opencode-spec-gate.test.js +0 -799
  60. package/bin/lib/opencode-install.js +0 -899
  61. package/bin/phases/opencode-runtime.js +0 -38
  62. package/src/claude/skills/specs/references/archive-workflow.md +0 -74
  63. package/src/claude/skills/specs/references/ask-user-question-gates.md +0 -70
  64. package/src/claude/skills/specs/references/codebase-analysis.md +0 -102
  65. package/src/claude/skills/specs/references/cross-spec-dependency.md +0 -76
  66. package/src/claude/skills/specs/references/research-strategy.md +0 -107
  67. package/src/claude/skills/specs/references/scope-inquiry.md +0 -107
  68. package/src/claude/skills/specs/references/translation-mirror.md +0 -83
  69. package/src/claude/skills/specs/rules/design-discovery-full.md +0 -45
  70. package/src/claude/skills/specs/rules/design-discovery-light.md +0 -28
  71. package/src/claude/skills/specs/rules/design-principles.md +0 -138
  72. package/src/claude/skills/specs/rules/design-review.md +0 -55
  73. package/src/claude/skills/specs/rules/ears-format.md +0 -42
  74. package/src/claude/skills/specs/rules/phase-decision-matrix.md +0 -56
  75. package/src/claude/skills/specs/rules/task-scoring-rubric.md +0 -52
  76. package/src/claude/skills/specs/rules/tasks-generation.md +0 -189
  77. package/src/opencode/AGENTS.md +0 -41
  78. package/src/opencode/plugins/docs-sync.ts +0 -175
  79. package/src/opencode/plugins/inspect-block.ts +0 -164
  80. package/src/opencode/plugins/privacy-block.ts +0 -182
  81. package/src/opencode/plugins/rules.ts +0 -155
  82. package/src/opencode/plugins/session.ts +0 -179
  83. package/src/opencode/plugins/spec-gate.ts +0 -457
  84. package/src/opencode/plugins/spec-state.ts +0 -311
  85. package/src/opencode/plugins/state.ts +0 -253
  86. package/src/opencode/plugins/task-scaffold-guard.ts +0 -161
  87. package/src/opencode/plugins/usage.ts +0 -178
@@ -525,9 +525,8 @@ The transition records success, failure, and recovery states.
525
525
  test('Codex installer transform preserves all owned spec assets with idempotent runtime parity', () => {
526
526
  for (const relative of [
527
527
  'src/claude/skills/specs/SKILL.md',
528
- 'src/claude/skills/specs/rules/tasks-generation.md',
529
- 'src/claude/skills/specs/rules/design-principles.md',
530
528
  'src/claude/skills/specs/references/review.md',
529
+ 'src/claude/skills/specs/references/templates.md',
531
530
  'src/claude/skills/specs/templates/design.md',
532
531
  'src/claude/skills/specs/templates/task.md',
533
532
  'src/claude/scripts/spec-scaffold.cjs',
@@ -548,14 +547,15 @@ test('Codex installer transform preserves all owned spec assets with idempotent
548
547
 
549
548
  const skill = fs.readFileSync(path.join(ROOT, 'src/claude/skills/specs/SKILL.md'), 'utf8');
550
549
  const review = fs.readFileSync(path.join(ROOT, 'src/claude/skills/specs/references/review.md'), 'utf8');
551
- const designRules = fs.readFileSync(path.join(ROOT, 'src/claude/skills/specs/rules/design-principles.md'), 'utf8');
552
- const taskRules = fs.readFileSync(path.join(ROOT, 'src/claude/skills/specs/rules/tasks-generation.md'), 'utf8');
553
- assert.match(skill, /\| `Compact` \| `spec\.json`, `requirements\.md`, `design\.md` \| only on a research trigger \| only on a typed topology trigger \|/);
554
- assert.match(skill, /\| `Full` \| `spec\.json`, `requirements\.md`, `design\.md` \| only on a research trigger \| only on a typed topology trigger \|/);
555
- assert.doesNotMatch(review, /Standard[^\n]{0,100}(?:must not|forbidden|never)[^\n]{0,60}tasks?/i);
556
- assert.match(designRules, /## Conditional detail[\s\S]*Migration:[\s\S]*only when existing state or public contracts change/);
557
- assert.match(taskRules, /distinct ownership, a durable[\s\S]{0,180}parallel coordination/);
558
- assert.match(taskRules, /receipts\/<task-basename>\.md|execution closeout/);
550
+ const templates = fs.readFileSync(path.join(ROOT, 'src/claude/skills/specs/references/templates.md'), 'utf8');
551
+ assert.match(skill, /specs\/<feature>\/[\s\S]{0,160}plan\.md[\s\S]{0,160}task-01-<slug>\.md/);
552
+ assert.match(skill, /C1 — Scope[\s\S]*C2 — Findings[\s\S]*C3 — Done/);
553
+ assert.doesNotMatch(skill, /--(?:status|validate|archive)\b/);
554
+ assert.match(review, /path:line/);
555
+ assert.match(review, /Cap the presented[\s\S]{0,40}list at 15/);
556
+ assert.match(review, /Round three requires runtime evidence/);
557
+ assert.match(templates, /\| ID \| EARS criterion \| Proof \|/);
558
+ assert.match(templates, /## Canonical inline Receipt[\s\S]*Verification: PASS[\s\S]*Exit: 0[\s\S]*Base:[\s\S]*Head:/);
559
559
 
560
560
  const parityRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'cafekit-codex-validator-parity-'));
561
561
  try {
@@ -3201,7 +3201,7 @@ test('D11/R1.14: the legacy-bridge precondition artifact is reachable and change
3201
3201
  // resolves its own production root the same way, via git from its own file
3202
3202
  // location) -- ROOT here is packages/spec, one level below that root.
3203
3203
  const MONOREPO_ROOT = path.resolve(ROOT, '..', '..');
3204
- const bridgePath = path.join(MONOREPO_ROOT, 'specs/cafekit-semantic-eval-firewall/reports/bootstrap-legacy-bridge-review.json');
3204
+ const bridgePath = path.join(MONOREPO_ROOT, 'specs/archive/cafekit-semantic-eval-firewall/reports/bootstrap-legacy-bridge-review.json');
3205
3205
  assert.ok(fs.existsSync(bridgePath), 'the legacy-bridge artifact must exist before any R0-01 change-firewall assertion runs');
3206
3206
  const parsed = CHANGE_FIREWALL.assertLegacyBridgeArtifact();
3207
3207
  assert.equal(parsed.schema_version, '1');
package/bin/install.js CHANGED
@@ -33,7 +33,6 @@ const {
33
33
  removeObsoleteAgents
34
34
  } = require('./phases/claude-runtime');
35
35
  const { mergeClaudeSettings } = require('./phases/claude-settings');
36
- const { installOpenCodeRuntime } = require('./phases/opencode-runtime');
37
36
  const { installCodexRuntime } = require('./phases/codex-runtime');
38
37
  const { writePlatformVersionMetadata } = require('./phases/write-metadata');
39
38
  const { checkVersions } = require('./lib/version-check');
@@ -70,10 +69,6 @@ function installPlatform(ctx, platformKey) {
70
69
  copyRulesDirectory(ctx, platformKey);
71
70
  }
72
71
 
73
- if (platformKey === 'opencode') {
74
- installOpenCodeRuntime(ctx, platformKey);
75
- }
76
-
77
72
  if (platformKey === 'codex') {
78
73
  installCodexRuntime(ctx, platformKey);
79
74
  }
@@ -95,11 +90,11 @@ function printHelp() {
95
90
  Usage: npx @haposoft/cafekit [options]
96
91
 
97
92
  Installs CafeKit skills, agents, rules and runtime into the current project
98
- for Claude Code, OpenCode, and/or Codex CLI. Re-runs are selective: managed files are updated,
93
+ for Claude Code and/or Codex CLI. Re-runs are selective: managed files are updated,
99
94
  your edits are preserved.
100
95
 
101
96
  Options:
102
- --platform <id[,id]> Select claude, opencode, or codex explicitly
97
+ --platform <id[,id]> Select claude or codex explicitly
103
98
  --dry-run Preview changes; write nothing
104
99
  --force-overwrite Overwrite user-modified managed files (backup kept)
105
100
  -u, --upgrade, -f, --force Alias of --force-overwrite
@@ -13,7 +13,6 @@
13
13
  const fs = require('fs');
14
14
  const path = require('path');
15
15
  const packageJson = require('../../package.json');
16
- const { getOpenCodeCopyOptions } = require('./opencode-install');
17
16
  const { isInteractive, createUI } = require('./ui');
18
17
  const { resolveLang, createTranslator } = require('./i18n');
19
18
  const { normalizeSourcePaths } = require('./copy-utils');
@@ -57,12 +56,10 @@ function loadClaudeMigrationManifest() {
57
56
  const DEPENDENCY_TEMPLATES = {
58
57
  commands: {
59
58
  claude: {},
60
- opencode: {},
61
59
  codex: {}
62
60
  },
63
61
  agents: {
64
62
  claude: {},
65
- opencode: {},
66
63
  codex: {}
67
64
  }
68
65
  };
@@ -93,29 +90,6 @@ const PLATFORMS = {
93
90
  commands: true
94
91
  }
95
92
  },
96
- opencode: {
97
- id: 'opencode',
98
- name: 'OpenCode',
99
- description: 'OpenCode terminal AI coding agent',
100
- folder: '.opencode',
101
- detectFiles: ['.opencode', 'opencode.json', 'opencode.jsonc'],
102
- commandsDir: '.opencode/commands',
103
- skillsDir: '.opencode/skills',
104
- agentsDir: '.opencode/agents',
105
- skillsRef: '.opencode/skills',
106
- commandPrefix: '/',
107
- sourceDir: 'claude',
108
- sourceSubdir: 'commands', // Dead config (manifest commands.core is []); kept for shape parity
109
- backupTargets: ['.opencode', 'AGENTS.md', 'opencode.json', 'opencode.jsonc'],
110
- capabilities: {
111
- skills: true,
112
- agents: true,
113
- references: true,
114
- scripts: true,
115
- rules: true,
116
- commands: false
117
- }
118
- },
119
93
  codex: {
120
94
  id: 'codex',
121
95
  name: 'Codex CLI',
@@ -192,26 +166,8 @@ function getRuntimeSupportTargetDir(platformKey, subdir) {
192
166
  return path.join(PLATFORMS[platformKey].folder, subdir);
193
167
  }
194
168
 
195
- // Warn opencode-only installs when a legacy .claude/ folder remains from
196
- // pre-0.9.0 installs (when OpenCode shared the .claude/ runtime). We do not
197
- // delete anything; user must remove it explicitly to opt in.
198
- function warnLegacyClaudeFolder(platforms) {
199
- if (!platforms.includes('opencode')) return;
200
- if (platforms.includes('claude')) return;
201
- if (!fs.existsSync('.claude')) return;
202
-
203
- console.log('');
204
- console.log('⚠ Legacy .claude/ folder detected.');
205
- console.log(' As of CafeKit 0.9.0, OpenCode installs are self-contained under .opencode/.');
206
- console.log(' The .claude/ folder from older installs is no longer used by OpenCode.');
207
- console.log(' After this install finishes you can remove it: rm -rf .claude');
208
- console.log('');
209
- }
210
169
 
211
170
  function getCopyOptions(platformKey, baseOptions = {}) {
212
- if (platformKey === 'opencode') {
213
- return getOpenCodeCopyOptions(baseOptions);
214
- }
215
171
  if (platformKey === 'codex') {
216
172
  // Lazy require avoids coupling the shared registry to a runtime adapter
217
173
  // during module initialization.
@@ -358,7 +314,6 @@ module.exports = {
358
314
  getPlatformKeys,
359
315
  hasPlatformCapability,
360
316
  getRuntimeSupportTargetDir,
361
- warnLegacyClaudeFolder,
362
317
  getCopyOptions,
363
318
  parseInstallerArgs,
364
319
  createResults,
@@ -13,7 +13,7 @@ function isTextAsset(filePath) {
13
13
 
14
14
  // Generated artifacts never ship as runtime payload: the coverage db, the
15
15
  // Python bytecode cache directory, and bytecode files. Skipping them here keeps
16
- // both copyRecursive and copyManagedTree (and the OpenCode plugin copy path
16
+ // both copyRecursive and copyManagedTree
17
17
  // built on copyRecursive) from ever copying build residue.
18
18
  function isGeneratedArtifact(name) {
19
19
  const base = String(name || '');
package/bin/lib/i18n.js CHANGED
@@ -107,7 +107,6 @@ const MESSAGES = {
107
107
  // Next steps
108
108
  nextStepsTitle: 'Next steps',
109
109
  nsClaude: 'Start coding: /hapo:specs <feature>',
110
- nsOpencode: 'Start coding: ask the agent to begin a new feature or brainstorm',
111
110
  nsCodex: 'Start with `$hapo-specs <feature>`; review and trust project hooks with `/hooks`',
112
111
  nsKeys: 'Some skills need API keys: {skills}\n Copy <skill>/.env.example → .env and fill in the values',
113
112
  nsForce: 'To force-refresh managed files: npx @haposoft/cafekit --force-overwrite',
@@ -228,7 +227,6 @@ const MESSAGES = {
228
227
 
229
228
  nextStepsTitle: '次のステップ',
230
229
  nsClaude: 'コーディング開始: /hapo:specs <機能名>',
231
- nsOpencode: 'コーディング開始: エージェントに新機能の開始またはブレストを依頼',
232
230
  nsCodex: '`$hapo-specs <機能名>` で開始し、`/hooks` でプロジェクトフックを確認・信頼',
233
231
  nsKeys: '一部のスキルに API キーが必要です: {skills}\n <skill>/.env.example を .env にコピーし、値を入力してください',
234
232
  nsForce: '管理ファイルを強制更新: npx @haposoft/cafekit --force-overwrite',
@@ -348,7 +346,6 @@ const MESSAGES = {
348
346
 
349
347
  nextStepsTitle: 'Bước tiếp theo',
350
348
  nsClaude: 'Bắt đầu code: /hapo:specs <mô-tả-tính-năng>',
351
- nsOpencode: 'Bắt đầu code: yêu cầu agent khởi động tính năng mới hoặc brainstorm',
352
349
  nsCodex: 'Bắt đầu bằng `$hapo-specs <tính-năng>`; kiểm tra và trust project hooks bằng `/hooks`',
353
350
  nsKeys: 'Một số skill cần API key: {skills}\n Sao chép <skill>/.env.example → .env rồi điền giá trị',
354
351
  nsForce: 'Làm mới file được quản lý: npx @haposoft/cafekit --force-overwrite',
@@ -169,7 +169,7 @@ function createTracker(platformFolder, version, options = {}) {
169
169
  * Classify a managed file against the recorded baseline + the incoming payload.
170
170
  *
171
171
  * @param {string} absPath destination path on disk
172
- * @param {string} platformFolder root of the platform install (.claude/.opencode)
172
+ * @param {string} platformFolder root of the platform install (e.g. .claude)
173
173
  * @param {object} manifest result of read(platformFolder)
174
174
  * @param {string} payloadHash sha256 of the content about to be written
175
175
  * @returns {{state: string, diskHash: string|null, recordedHash: string|null, changed: boolean}}
@@ -18,7 +18,6 @@ const {
18
18
  const { sha256 } = require('../lib/manifest');
19
19
  const { writeManagedFile, copyManagedTree } = require('../lib/managed-writer');
20
20
  const { report, treeAction } = require('./report');
21
- const { normalizeOpenCodeBody } = require('../lib/opencode-install');
22
21
  const {
23
22
  upsertManagedCoreBlock,
24
23
  managedRange,
@@ -120,7 +119,7 @@ function copyClaudeAgentsMdFile(ctx, platformKey) {
120
119
  ensureSharedAgentsMdCore(ctx);
121
120
  }
122
121
 
123
- /** Copy ROUTING.md (SKILLS_DIR substituted; OpenCode body normalized). */
122
+ /** Copy ROUTING.md (SKILLS_DIR substituted). */
124
123
  function copyRoutingFile(ctx, platformKey) {
125
124
  const platform = PLATFORMS[platformKey];
126
125
  const src = path.join(SRC, platform.sourceDir, 'ROUTING.md');
@@ -129,7 +128,6 @@ function copyRoutingFile(ctx, platformKey) {
129
128
 
130
129
  const transform = (content) => {
131
130
  let c = content.replace(/\{\{SKILLS_DIR\}\}/g, platform.skillsRef);
132
- if (platformKey === 'opencode') c = normalizeOpenCodeBody(c);
133
131
  return c;
134
132
  };
135
133
  const { action } = writeManagedFile({
@@ -7,7 +7,6 @@ const { writeManagedFile, copyManagedTree } = require('../lib/managed-writer');
7
7
  const { report, treeAction } = require('./report');
8
8
  const { copyRulesDirectory } = require('./claude-runtime');
9
9
  const {
10
- normalizeCodexBody,
11
10
  managedRange,
12
11
  upsertManagedCodexBlock
13
12
  } = require('../lib/codex-install');
@@ -138,7 +137,10 @@ function installManagedAgentsMd(ctx) {
138
137
  ctx.results.errors++;
139
138
  return;
140
139
  }
141
- const block = normalizeCodexBody(fs.readFileSync(runtimeSource, 'utf8'));
140
+ // This template is already Codex-native. Running it through the generic
141
+ // Claude-to-Codex converter corrupts intentional cross-runtime wording such
142
+ // as the fail-safe instruction for Claude Code to ignore this block.
143
+ const block = fs.readFileSync(runtimeSource, 'utf8');
142
144
  const next = upsertManagedCodexBlock(existing, block);
143
145
  const action = !exists ? 'created' : next === existing ? 'unchanged' : 'updated';
144
146
 
@@ -17,10 +17,6 @@ const {
17
17
  } = require('../lib/context');
18
18
  const { writeManagedFile, copyManagedTree } = require('../lib/managed-writer');
19
19
  const { report, treeAction } = require('./report');
20
- const {
21
- convertOpenCodeAgentContent,
22
- convertOpenCodeCommandContent
23
- } = require('../lib/opencode-install');
24
20
  const {
25
21
  codexAgentName,
26
22
  convertCodexAgentContent
@@ -29,8 +25,7 @@ const {
29
25
  const SRC = path.join(__dirname, '../../src');
30
26
 
31
27
  /**
32
- * Spec command files installed for a platform. Claude ships spec-* commands;
33
- * OpenCode generates its own command wrappers elsewhere.
28
+ * Spec command files installed for a platform. Claude ships spec-* commands.
34
29
  */
35
30
  function getPlatformSpecFiles(platformKey, ctx) {
36
31
  if (platformKey === 'claude') {
@@ -76,7 +71,6 @@ function copyPlatformFiles(ctx, platformKey) {
76
71
  const tracker = ctx.trackers[platformKey];
77
72
  const platformFolder = platform.folder;
78
73
 
79
- // For OpenCode, text bodies are path-normalized (.claude → .opencode, etc.).
80
74
  const bodyTransform = getCopyOptions(platformKey, {}).transform;
81
75
 
82
76
  const skillsSourceDir = path.join(SRC, 'claude/skills');
@@ -162,9 +156,7 @@ function copyPlatformFiles(ctx, platformKey) {
162
156
  'tester.md', 'code-reviewer.md', 'fullstack-developer.md', 'debugger.md'
163
157
  ];
164
158
  let agentTransform;
165
- if (platformKey === 'opencode') {
166
- agentTransform = (content, src) => convertOpenCodeAgentContent(content, path.basename(src));
167
- } else if (platformKey === 'codex') {
159
+ if (platformKey === 'codex') {
168
160
  agentTransform = (content, src) => convertCodexAgentContent(content, path.basename(src));
169
161
  }
170
162
 
@@ -222,11 +214,7 @@ function copyPlatformFiles(ctx, platformKey) {
222
214
  return;
223
215
  }
224
216
  const cmdTransform = (content, s) => {
225
- let c = content.replace(/\{\{SKILLS_DIR\}\}/g, platform.skillsRef);
226
- if (platformKey === 'opencode') {
227
- c = convertOpenCodeCommandContent(c, path.basename(s));
228
- }
229
- return c;
217
+ return content.replace(/\{\{SKILLS_DIR\}\}/g, platform.skillsRef);
230
218
  };
231
219
  const { action } = writeManagedFile({
232
220
  src, dest, platformFolder, ctx, tracker, transform: cmdTransform
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Phase: post-install runtime configuration.
3
3
  *
4
- * OpenCode model + addressing config. Interactive prompts use ctx.ui (clack);
4
+ * Addressing config. Interactive prompts use ctx.ui (clack);
5
5
  * in non-interactive/dry-run they are skipped via fallbacks so spawned/CI runs
6
6
  * never hang.
7
7
  *
@@ -15,14 +15,12 @@ const fs = require('fs');
15
15
  const path = require('path');
16
16
  const { PLATFORMS } = require('../lib/context');
17
17
  const { LANGUAGE_LABELS } = require('../lib/i18n');
18
- const { setupOpenCodeModel, transformManagedOpenCodeContent } = require('../lib/opencode-install');
19
18
  const { transformManagedCodexContent } = require('../lib/codex-install');
20
19
  const { transformManagedClaudeContent } = require('./claude-runtime');
21
20
  const { transformManagedCoreContent } = require('../lib/instruction-blocks');
22
21
  const ASSISTANT_NAMES = {
23
22
  claude: 'Claude Code',
24
- codex: 'Codex CLI',
25
- opencode: 'OpenCode'
23
+ codex: 'Codex CLI'
26
24
  };
27
25
  const LANGUAGE_LABEL_BY_CODE = {
28
26
  vi: 'Vietnamese',
@@ -50,10 +48,6 @@ function instructionTargets(ctx) {
50
48
  file: path.join(process.cwd(), 'AGENTS.md'),
51
49
  transform: transformManagedCodexContent
52
50
  },
53
- opencode: {
54
- file: path.join(process.cwd(), 'AGENTS.md'),
55
- transform: transformManagedOpenCodeContent
56
- }
57
51
  };
58
52
  return Object.keys(targets)
59
53
  .filter((key) => ctx.platforms.includes(key))
@@ -161,7 +155,7 @@ function patchRuntimeLocale(ctx) {
161
155
 
162
156
  /** Human assistant name for the active platform(s). */
163
157
  function assistantName(platformKey) {
164
- return ASSISTANT_NAMES[platformKey] || ASSISTANT_NAMES.opencode;
158
+ return ASSISTANT_NAMES[platformKey] || platformKey;
165
159
  }
166
160
 
167
161
  function configureAddressing(ctx, userAddress) {
@@ -188,7 +182,7 @@ ${name} always addresses the user as "${userAddress}" throughout the conversatio
188
182
  }
189
183
 
190
184
  async function setupAddressing(ctx) {
191
- if (!ctx.platforms.some((key) => key === 'claude' || key === 'codex' || key === 'opencode')) return;
185
+ if (!ctx.platforms.some((key) => key === 'claude' || key === 'codex')) return;
192
186
 
193
187
  let existingName = null;
194
188
  for (const target of instructionTargets(ctx)) {
@@ -237,16 +231,10 @@ async function setupAddressing(ctx) {
237
231
  /** Run the post-install configuration sequence. */
238
232
  async function runPostInstall(ctx) {
239
233
  if (ctx.dryRun) {
240
- ctx.ui.info('[dry-run] Skipping OpenCode model / addressing setup');
234
+ ctx.ui.info('[dry-run] Skipping addressing setup');
241
235
  return ctx;
242
236
  }
243
237
 
244
- // OpenCode model uses its own readline; only run it when it won't block:
245
- // interactive, or an env override is present (which it reads without prompting).
246
- const hasModelEnv = Boolean(process.env.OPENCODE_MODEL || process.env.OPENCODE_DEFAULT_MODEL);
247
- if (ctx.platforms.includes('opencode') && (ctx.interactive || hasModelEnv)) {
248
- await setupOpenCodeModel(ctx.platforms, ctx.results);
249
- }
250
238
 
251
239
  await setupAddressing(ctx);
252
240
 
@@ -4,11 +4,11 @@
4
4
  * Ensures the root .gitignore carries CafeKit-managed patterns:
5
5
  * - workflow dirs (plans, shared research)
6
6
  * - install safety artifacts (backup, lock)
7
- * - runtime folders (.claude/, .opencode/, .codex/, .agents/) — reinstall via
7
+ * - runtime folders (.claude/, .codex/, .agents/) — reinstall via
8
8
  * `npx @haposoft/cafekit`; do not commit the local payload
9
9
  *
10
10
  * Layered with the in-folder `.claude/.gitignore` /
11
- * `.opencode/.gitignore` templates (secrets, skill deps, session
11
+ * runtime `.gitignore` templates (secrets, skill deps, session
12
12
  * state) so force-adds and partial un-ignores stay safe.
13
13
  *
14
14
  * Honors dry-run.
@@ -109,7 +109,6 @@ function ensureGitignore(ctx) {
109
109
  '.cafekit.lock',
110
110
  // Local runtime payload — reinstall with npx; keep out of git
111
111
  '.claude/',
112
- '.opencode/',
113
112
  '.codex/',
114
113
  '.agents/'
115
114
  ];
@@ -11,8 +11,7 @@ const path = require('path');
11
11
  const {
12
12
  PLATFORMS,
13
13
  detectPlatforms,
14
- getPlatformKeys,
15
- warnLegacyClaudeFolder
14
+ getPlatformKeys
16
15
  } = require('../lib/context');
17
16
  const { SUPPORTED, LANGUAGE_LABELS, OTHER_LABEL } = require('../lib/i18n');
18
17
 
@@ -162,7 +161,6 @@ async function resolvePlatforms(ctx) {
162
161
  ctx.ui.info(ctx.t('installingFor', {
163
162
  names: platformNames(requested)
164
163
  }));
165
- warnLegacyClaudeFolder(requested);
166
164
  reportInstallMode(ctx);
167
165
  return ctx;
168
166
  }
@@ -216,7 +214,6 @@ async function resolvePlatforms(ctx) {
216
214
  ctx.platforms = platforms;
217
215
 
218
216
  ctx.ui.info(ctx.t('installingFor', { names: platformNames(platforms) }));
219
- warnLegacyClaudeFolder(platforms);
220
217
 
221
218
  reportInstallMode(ctx);
222
219
 
@@ -225,7 +222,7 @@ async function resolvePlatforms(ctx) {
225
222
 
226
223
  /**
227
224
  * Get the installed platform from cafekit.json files.
228
- * Returns the platform key (e.g. 'claude', 'opencode') or null.
225
+ * Returns the platform key (e.g. 'claude', 'codex') or null.
229
226
  */
230
227
  function getInstalledPlatforms() {
231
228
  const installed = [];
@@ -55,7 +55,6 @@ function printSummary(ctx) {
55
55
  for (const key of platforms) {
56
56
  const messageKey = {
57
57
  claude: 'nsClaude',
58
- opencode: 'nsOpencode',
59
58
  codex: 'nsCodex'
60
59
  }[key];
61
60
  if (messageKey) lines.push(t(messageKey));
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@haposoft/cafekit",
3
- "version": "0.16.0-rc.6",
4
- "description": "Native spec-driven workflows for Claude Code, Codex CLI, and OpenCode. Bundles CafeKit skills, runtime hooks, agents, and installer scaffolding.",
3
+ "version": "0.16.0-rc.8",
4
+ "description": "Native spec-driven workflows for Claude Code and Codex CLI. Bundles CafeKit skills, runtime hooks, agents, and installer scaffolding.",
5
5
  "author": "Haposoft <nghialt@haposoft.com>",
6
6
  "license": "MIT",
7
7
  "private": false,
@@ -56,9 +56,6 @@
56
56
  "engines": {
57
57
  "node": ">=18.0.0"
58
58
  },
59
- "devDependencies": {
60
- "@opencode-ai/plugin": "1.15.11"
61
- },
62
59
  "dependencies": {
63
60
  "@clack/prompts": "0.11.0",
64
61
  "picocolors": "^1.1.1"
@@ -12,9 +12,22 @@
12
12
  - macOS/Linux: `.claude/skills/.venv/bin/python3 scripts/<script>.py`
13
13
  - Windows: `.claude\skills\.venv\Scripts\python.exe scripts\<script>.py`
14
14
  - Consult `.claude/rules/state-sync.md`, `.claude/rules/hook-protocols.md`, and `.claude/rules/skill-workflow-routing.md` when their topics apply.
15
- - Specs v2 keeps `planning_depth` (`None`/`Compact`/`Full`) independent from `assurance_level` (`Routine`/`Elevated`/`Strict`). Any risk has an Elevated automatic floor; Strict is opt-in only for an explicit user/project independent-audit requirement or a user-confirmed scope-specific audit decision, never a keyword or severity label. Run the artifact router before discovery: None has no durable spec; Compact/Full share the bounded `spec.json` + `requirements.md` + `design.md` core. Research requires material unresolved uncertainty, an external-current fact, or an explicit request; tasks require typed coordination topology. Full/Strict never create either automatically.
16
- - In v2.1, `spec.json` is machine authority and Markdown is a human projection. Task plans have exactly seven sections: `Outcome`, `Scope`, `Anchors and Ownership`, `Changes`, `Acceptance`, `Dependencies`, `Verification Plan`; the only ownership table is `ID | Type | Target | Role | Access | Action`.
17
- - Promote canonical `semantic_model` only through the explicit installed machine semantic-sync step. A semantic Markdown edit requires resynchronization and round-trip validation; never hand-author the machine shape.
18
- - `coordination.boundaries` typed as ownership/dependency/transition/proof/parallel is topology authority. Legacy trigger fields, priority markers, related-file lists, approval fields, and prose are inert compatibility inputs, never canonical authoring.
19
- - Canonical lifecycle is exactly `in_progress`, `paused`, `blocked`, or `done`. Technical readiness differs from closeout; authors cannot self-declare readiness, review authority, execution proof, or final `done`.
20
- - Validator exit 0 proves implemented structural checks only, not semantic quality or execution PASS.
15
+ - New Specs work uses the process-first flow. `/hapo:specs` opens C1, writes
16
+ `specs/<feature>/plan.md` with flat `task-NN-*.md` files beside it, then opens
17
+ C2 after adversarial review. It never starts implementation.
18
+ - Start implementation only through a new explicit `/hapo:develop` invocation.
19
+ Execute one unblocked task at a time; each task has exactly one `Status:`
20
+ field and the controller is its sole state-and-proof writer.
21
+ - Use `/hapo:sync` for surgical updates to observed file state. A done task
22
+ requires a canonical final inline `## Receipt` with the exact command,
23
+ `Exit: 0`, `Verification: PASS`, runtime-derived Base and Head values, and
24
+ non-empty fenced current output.
25
+ - At C3, show current receipts and unresolved limitations. The user decides
26
+ completion; no command, review, or host state may invent approval or proof.
27
+
28
+ ### Legacy Specs compatibility
29
+
30
+ Existing packets containing `spec.json`, nested tasks, or legacy kernel
31
+ artifacts keep their installed adapter, `task_registry`, `semantic_model`,
32
+ `planning_depth`, lane, `execution_tier`, machine authority, separate receipts,
33
+ and closeout contract. Do not migrate them during unrelated process-first work.
@@ -7,33 +7,65 @@ tools: Glob, Grep, Read, Edit, Write, NotebookEdit, Bash, WebFetch, TaskCreate,
7
7
 
8
8
  # Project Manager — Ecosystem Orchestrator
9
9
 
10
- You are the authoritative **Project Manager** within the ecosystem. Your mandate is to track verifiable engineering progress by strictly parsing metric data across the `specs/` and `docs/` directory matrix, eliminating guesswork, and unblocking development flows.
10
+ You are the **Project Manager** for evidence-backed aggregation. Track progress
11
+ from each feature's `plan.md`, flat `task-NN-*.md` files, current command
12
+ output, and affected docs. Conversational summaries are leads, never proof.
11
13
 
12
14
  ## Operational Mandate
13
15
 
14
- Unlike typical managers who report on "feelings" or conversational summaries, you operate solely on hard data extracted from technical specifications:
15
- 1. **Spec Syncing:** You validate if the output produced by sub-agents matches the `spec.json` requirements and the `design.md` architectural constraints.
16
- 2. **Blocker Assassination:** You identify task stagnation (e.g., a spec stuck in 'in-progress' across multiple sessions) and force the immediate assignment of next-step actions.
17
- 3. **Agile Aggregation:** When parallel sub-agents (like `implementer` and `test-runner`) report completion, you sweep their logs, consolidate the facts, and generate a single authoritative **Feature Release Report**.
16
+ Operate only on current, reproducible data:
17
+
18
+ 1. **Packet reconciliation:** Compare the plan task table with every flat task
19
+ filename, acceptance mapping, ownership boundary, dependency, and Status.
20
+ 2. **Proof validation:** Require exactly one Status per task. Treat `done` as
21
+ valid only when the task's final inline `## Receipt` contains the exact
22
+ command, `Exit: 0`, `Verification: PASS`, runtime-derived Base and Head, and
23
+ non-empty fenced current output.
24
+ 3. **Process-first aggregation:** Consolidate worker reports, test output,
25
+ review findings, receipts, docs impact, and unresolved limitations without
26
+ borrowing one owner's evidence for another boundary.
27
+ 4. **Blocker routing:** Identify stalled or contradictory tasks and assign the
28
+ smallest concrete next action. Never force a state transition without proof.
18
29
 
19
30
 
20
31
  ## Execution Constraints
21
32
 
22
33
  Before you declare any phase complete or issue a final status report, you must internally trace:
23
- - **Scope Viability:** Are we building exactly what is listed in `requirements.md`? Flag any undocumented "scope expansions" immediately.
24
- - **Dependency Graph:** Ensure no task starts if its prerequisites (tracked via `cross-spec-dependency`) are still red.
25
- - **Actionable Exits:** Never end a report with vague conclusions. Assign discrete, actionable tasks to a specific sub-agent (or prompt the user for a definitive GO/NO-GO decision).
34
+ - **C1 scope:** Compare implemented bytes with the chosen scope, exclusions, and
35
+ acceptance criteria in the plan. New scope evidence returns to C1.
36
+ - **C2 findings:** Confirm every accepted or revised finding appears once in
37
+ the plan or its task; rejected findings do not silently return.
38
+ - **Dependencies:** A task starts only when each named dependency is done with a
39
+ valid current Receipt. Serialize overlapping write ownership.
40
+ - **Execution authority:** Specs completion never starts implementation. Wait
41
+ for an explicit Develop invocation and aggregate only its requested boundary.
42
+ - **C3 decision:** Show current proof and limitations. The user, not the
43
+ manager, decides whether the feature is complete.
44
+ - **Actionable exits:** Assign a discrete next task or request a definitive user
45
+ decision; never end with a vague conclusion.
26
46
 
27
47
  ## Format & Output Constraints
28
48
  - **Sacrifice Grammar for Concision:** Do not write flowery prose. Your reports must be highly mechanical, bulleted, and brutally concise.
29
49
  - **Naming Hooks:** Always use the precise naming pattern and file path locations defined by project hooks for your reports.
50
+ - **Minimum report:** Include C1 scope drift, accepted C2 finding coverage,
51
+ task/receipt status, executed command results, blockers, docs impact, and the
52
+ pending or recorded C3 decision.
30
53
  - **Unresolved Inquiries:** If any architectural ambiguity remains unresolved, list it prominently at the exact bottom of the report.
31
54
 
32
55
  ## Collaborative Interlocking (Swarm Protocol)
33
56
 
34
- - You govern the final phase of `/specs`. If a spec is prematurely abandoned by `brainstormer`, you drag it back to alignment.
57
+ - You aggregate after C2 and during explicitly invoked execution. An incomplete
58
+ packet returns to the planning owner; do not expand it yourself.
35
59
  - When triggered as an active teammate within multi-agent swarms:
36
60
  1. **Init:** Execute `TaskList` immediately, then claim idle aggregation blocks via `TaskUpdate`.
37
61
  2. **Context Intake:** Pull strict operational boundaries using `TaskGet`.
38
62
  3. **Routing Coordination:** Communicate with other agents or the lead via `SendMessage` and enforce strict completion parameters via `TaskUpdate(status: "completed")`.
39
63
  4. **Shutdown Mandate:** If you intercept a `shutdown_request` payload, you MUST yield gracefully by broadcasting `SendMessage(type: "shutdown_response")` unless interrupted mid-critical analysis.
64
+
65
+ ## Legacy compatibility
66
+
67
+ For an existing packet containing `spec.json`, nested task files, or legacy
68
+ kernel artifacts, use its installed adapter and preserve `task_registry`,
69
+ `semantic_model`, `planning_depth`, lane, `execution_tier`, machine authority,
70
+ separate receipts, and feature closeout contract. Keep that aggregation path
71
+ separate from process-first files.