@duypham93/openkit 0.2.4 → 0.2.5

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 (35) hide show
  1. package/agents/architect-agent.md +10 -9
  2. package/agents/ba-agent.md +8 -7
  3. package/agents/code-reviewer.md +4 -3
  4. package/agents/fullstack-agent.md +5 -4
  5. package/agents/master-orchestrator.md +15 -15
  6. package/agents/pm-agent.md +8 -7
  7. package/agents/qa-agent.md +9 -8
  8. package/agents/tech-lead-agent.md +9 -8
  9. package/assets/install-bundle/opencode/agents/ArchitectAgent.md +13 -7
  10. package/assets/install-bundle/opencode/agents/BAAgent.md +11 -5
  11. package/assets/install-bundle/opencode/agents/CodeReviewer.md +7 -1
  12. package/assets/install-bundle/opencode/agents/FullstackAgent.md +9 -2
  13. package/assets/install-bundle/opencode/agents/MasterOrchestrator.md +19 -11
  14. package/assets/install-bundle/opencode/agents/PMAgent.md +11 -5
  15. package/assets/install-bundle/opencode/agents/QAAgent.md +13 -6
  16. package/assets/install-bundle/opencode/agents/TechLeadAgent.md +12 -6
  17. package/assets/install-bundle/opencode/commands/brainstorm.md +13 -6
  18. package/assets/install-bundle/opencode/commands/delivery.md +15 -8
  19. package/assets/install-bundle/opencode/commands/execute-plan.md +15 -8
  20. package/assets/install-bundle/opencode/commands/migrate.md +16 -9
  21. package/assets/install-bundle/opencode/commands/quick-task.md +14 -7
  22. package/assets/install-bundle/opencode/commands/task.md +16 -8
  23. package/assets/install-bundle/opencode/commands/write-plan.md +15 -8
  24. package/commands/brainstorm.md +10 -9
  25. package/commands/delivery.md +12 -12
  26. package/commands/execute-plan.md +12 -11
  27. package/commands/migrate.md +13 -13
  28. package/commands/quick-task.md +11 -11
  29. package/commands/task.md +12 -12
  30. package/commands/write-plan.md +12 -11
  31. package/package.json +1 -1
  32. package/src/global/paths.js +6 -0
  33. package/src/global/workspace-shim.js +104 -0
  34. package/src/global/workspace-state.js +3 -0
  35. package/tests/cli/openkit-cli.test.js +5 -0
@@ -8,9 +8,10 @@ Use `/write-plan` to create an implementation plan for work currently in `Full D
8
8
 
9
9
  ## Global OpenKit path rule
10
10
 
11
- - In globally installed OpenKit sessions, resolve OpenKit-owned docs and templates from `OPENKIT_KIT_ROOT` instead of assuming the target repository contains `AGENTS.md`, `context/`, `docs/templates/`, or `.opencode/`.
12
- - Resolve resumable workflow state from `OPENKIT_WORKFLOW_STATE`.
13
- - Use `node "${OPENKIT_KIT_ROOT}/.opencode/workflow-state.js" --state "${OPENKIT_WORKFLOW_STATE}" <command>` for workflow-state checks in global mode.
11
+ - In globally installed OpenKit sessions, treat `.opencode/openkit/` as the repo-local compatibility surface for OpenKit-owned docs, templates, and workflow tools.
12
+ - Read canonical OpenKit docs from `.opencode/openkit/...`, not from repo-root `context/`, repo-root `AGENTS.md`, or repo-root `.opencode/`.
13
+ - Use `.opencode/openkit/workflow-state.json` for resumable workflow state.
14
+ - Use `node .opencode/openkit/workflow-state.js <command>` for workflow-state checks in global mode.
14
15
 
15
16
  ## Preconditions
16
17
 
@@ -21,13 +22,13 @@ Use `/write-plan` to create an implementation plan for work currently in `Full D
21
22
 
22
23
  ## Canonical docs to load
23
24
 
24
- - `AGENTS.md`
25
- - `context/navigation.md`
26
- - `context/core/workflow.md`
27
- - `context/core/project-config.md`
28
- - `.opencode/workflow-state.json`
29
- - `docs/templates/implementation-plan-template.md`
30
- - `docs/templates/migration-report-template.md` when migration work benefits from one running artifact
25
+ - `.opencode/openkit/AGENTS.md`
26
+ - `.opencode/openkit/context/navigation.md`
27
+ - `.opencode/openkit/context/core/workflow.md`
28
+ - `.opencode/openkit/context/core/project-config.md`
29
+ - `.opencode/openkit/workflow-state.json`
30
+ - `.opencode/openkit/docs/templates/implementation-plan-template.md`
31
+ - `.opencode/openkit/docs/templates/migration-report-template.md` when migration work benefits from one running artifact
31
32
  - skill `writing-plans`
32
33
 
33
34
  For operator checks, use the current workflow-state utility surface: `status`, `doctor`, `show`, and `validate`.
@@ -53,4 +54,4 @@ For operator checks, use the current workflow-state utility surface: `status`, `
53
54
  - The plan should name the strongest real validation path available in the repository
54
55
  - In migration mode, use `migration_report` when handoffs would benefit from a single running narrative instead of scattered notes
55
56
  - If no repo-native app build, lint, or test command exists, say that explicitly in the plan instead of guessing a stack command
56
- - Use the workflow-state utility against `OPENKIT_WORKFLOW_STATE` only to confirm workflow state, not to stand in for implementation verification
57
+ - Use `node .opencode/openkit/workflow-state.js validate` only to confirm workflow state, not to stand in for implementation verification
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duypham93/openkit",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "type": "module",
5
5
  "files": [
6
6
  ".opencode/",
@@ -82,5 +82,11 @@ export function getWorkspacePaths({ projectRoot, env = process.env, platform = p
82
82
  legacyRuntimeDir: path.join(resolvedProjectRoot, '.opencode'),
83
83
  legacyWorkflowStatePath: path.join(resolvedProjectRoot, '.opencode', 'workflow-state.json'),
84
84
  legacyWorkItemsDir: path.join(resolvedProjectRoot, '.opencode', 'work-items'),
85
+ workspaceShimDir: path.join(resolvedProjectRoot, '.opencode', 'openkit'),
86
+ workspaceShimContextDir: path.join(resolvedProjectRoot, '.opencode', 'openkit', 'context'),
87
+ workspaceShimTemplatesDir: path.join(resolvedProjectRoot, '.opencode', 'openkit', 'docs', 'templates'),
88
+ workspaceShimAgentsPath: path.join(resolvedProjectRoot, '.opencode', 'openkit', 'AGENTS.md'),
89
+ workspaceShimWorkflowStatePath: path.join(resolvedProjectRoot, '.opencode', 'openkit', 'workflow-state.json'),
90
+ workspaceShimWorkflowCliPath: path.join(resolvedProjectRoot, '.opencode', 'openkit', 'workflow-state.js'),
85
91
  };
86
92
  }
@@ -0,0 +1,104 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ function ensureParent(filePath) {
5
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
6
+ }
7
+
8
+ function writeFile(filePath, content, mode) {
9
+ ensureParent(filePath);
10
+ fs.writeFileSync(filePath, content, 'utf8');
11
+ if (typeof mode === 'number') {
12
+ fs.chmodSync(filePath, mode);
13
+ }
14
+ }
15
+
16
+ function relativeTarget(fromPath, toPath) {
17
+ return path.relative(path.dirname(fromPath), toPath) || '.';
18
+ }
19
+
20
+ function createSymlinkOrCopy({ linkPath, targetPath, type = 'file' }) {
21
+ ensureParent(linkPath);
22
+
23
+ try {
24
+ if (fs.existsSync(linkPath) || fs.lstatSync(linkPath)) {
25
+ fs.rmSync(linkPath, { recursive: true, force: true });
26
+ }
27
+ } catch {
28
+ // ignore cleanup misses
29
+ }
30
+
31
+ try {
32
+ fs.symlinkSync(relativeTarget(linkPath, targetPath), linkPath, type);
33
+ return 'symlink';
34
+ } catch {
35
+ const stats = fs.statSync(targetPath);
36
+ if (stats.isDirectory()) {
37
+ fs.cpSync(targetPath, linkPath, { recursive: true });
38
+ } else {
39
+ fs.copyFileSync(targetPath, linkPath);
40
+ }
41
+ return 'copy';
42
+ }
43
+ }
44
+
45
+ export function ensureWorkspaceShim(paths) {
46
+ fs.mkdirSync(paths.workspaceShimDir, { recursive: true });
47
+
48
+ createSymlinkOrCopy({
49
+ linkPath: paths.workspaceShimAgentsPath,
50
+ targetPath: path.join(paths.kitRoot, 'AGENTS.md'),
51
+ type: 'file',
52
+ });
53
+
54
+ createSymlinkOrCopy({
55
+ linkPath: paths.workspaceShimContextDir,
56
+ targetPath: path.join(paths.kitRoot, 'context'),
57
+ type: 'dir',
58
+ });
59
+
60
+ createSymlinkOrCopy({
61
+ linkPath: paths.workspaceShimTemplatesDir,
62
+ targetPath: path.join(paths.kitRoot, 'docs', 'templates'),
63
+ type: 'dir',
64
+ });
65
+
66
+ createSymlinkOrCopy({
67
+ linkPath: paths.workspaceShimWorkflowStatePath,
68
+ targetPath: paths.workflowStatePath,
69
+ type: 'file',
70
+ });
71
+
72
+ const workflowCli = `#!/usr/bin/env node
73
+ import { spawnSync } from 'node:child_process';
74
+
75
+ const args = process.argv.slice(2);
76
+ const result = spawnSync(process.execPath, [${JSON.stringify(path.join(paths.kitRoot, '.opencode', 'workflow-state.js'))}, '--state', ${JSON.stringify(paths.workflowStatePath)}, ...args], {
77
+ stdio: 'inherit',
78
+ env: process.env,
79
+ });
80
+
81
+ if (result.error) {
82
+ throw result.error;
83
+ }
84
+
85
+ process.exit(typeof result.status === 'number' ? result.status : 1);
86
+ `;
87
+
88
+ writeFile(paths.workspaceShimWorkflowCliPath, workflowCli, 0o755);
89
+
90
+ const gitDir = path.join(paths.projectRoot, '.git');
91
+ if (fs.existsSync(gitDir)) {
92
+ const excludePath = path.join(gitDir, 'info', 'exclude');
93
+ const entry = '.opencode/openkit/';
94
+ let current = '';
95
+ if (fs.existsSync(excludePath)) {
96
+ current = fs.readFileSync(excludePath, 'utf8');
97
+ }
98
+ if (!current.split(/\r?\n/).includes(entry)) {
99
+ writeFile(excludePath, `${current}${current.endsWith('\n') || current.length === 0 ? '' : '\n'}${entry}\n`);
100
+ }
101
+ }
102
+
103
+ return paths;
104
+ }
@@ -2,6 +2,7 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
 
4
4
  import { getWorkspacePaths } from './paths.js';
5
+ import { ensureWorkspaceShim } from './workspace-shim.js';
5
6
 
6
7
  const WORKSPACE_STATE_SCHEMA = 'openkit/workspace-state@1';
7
8
 
@@ -50,6 +51,8 @@ export function ensureWorkspaceBootstrap(options = {}) {
50
51
  });
51
52
  }
52
53
 
54
+ ensureWorkspaceShim(paths);
55
+
53
56
  return paths;
54
57
  }
55
58
 
@@ -222,6 +222,10 @@ process.stdout.write('mock opencode launched\\n');
222
222
  assert.equal(invocation.configDir, path.join(tempHome, 'kits', 'openkit'));
223
223
  assert.match(invocation.workflowState, /workspaces\/.*\/openkit\/\.opencode\/workflow-state\.json$/);
224
224
  assert.equal(invocation.kitRoot, path.join(tempHome, 'kits', 'openkit'));
225
+ assert.equal(fs.existsSync(path.join(projectRoot, '.opencode', 'openkit', 'AGENTS.md')), true);
226
+ assert.equal(fs.existsSync(path.join(projectRoot, '.opencode', 'openkit', 'context', 'core', 'workflow.md')), true);
227
+ assert.equal(fs.lstatSync(path.join(projectRoot, '.opencode', 'openkit', 'workflow-state.json')).isSymbolicLink() || fs.existsSync(path.join(projectRoot, '.opencode', 'openkit', 'workflow-state.json')), true);
228
+ assert.equal(fs.existsSync(path.join(projectRoot, '.opencode', 'openkit', 'workflow-state.js')), true);
225
229
  });
226
230
 
227
231
  test('openkit run does not reinstall when the global install already exists', () => {
@@ -294,6 +298,7 @@ process.stdout.write('mock opencode launched after auto-install\\n');
294
298
  const invocation = readJson(logPath);
295
299
  assert.deepEqual(invocation.argv, [projectRoot]);
296
300
  assert.equal(invocation.kitRoot, path.join(tempHome, 'kits', 'openkit'));
301
+ assert.equal(fs.existsSync(path.join(projectRoot, '.opencode', 'openkit', 'AGENTS.md')), true);
297
302
  });
298
303
 
299
304
  test('openkit run reports missing opencode after first-time setup completes', () => {