@duypham93/openkit 0.2.1 → 0.2.2

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.
@@ -8,7 +8,7 @@ For phase-1 navigation, treat this file as a local runtime boundary note, not as
8
8
 
9
9
  What lives here:
10
10
 
11
- - `.opencode/opencode.json`: the current repository-local runtime manifest
11
+ - `.opencode/opencode.json`: the current repository-local OpenCode project config
12
12
  - `.opencode/workflow-state.json`: the active compatibility mirror
13
13
  - `.opencode/work-items/`: per-item backing store
14
14
  - `.opencode/workflow-state.js`: lower-level runtime utility CLI
@@ -1,93 +1,7 @@
1
1
  {
2
- "model": "anthropic/claude-sonnet-4-5",
3
- "agents_dir": "agents",
4
- "skills_dir": "skills",
5
- "commands_dir": "commands",
6
- "kit": {
7
- "name": "OpenKit AI Software Factory",
8
- "version": "0.1.0",
9
- "entryAgent": "MasterOrchestrator",
10
- "productSurface": {
11
- "current": "repository-local-openkit-runtime",
12
- "emerging": "global-openkit-install",
13
- "installReadiness": "emerging",
14
- "migrationState": "staged-not-complete",
15
- "targetWrapperEntrypoint": "opencode.json",
16
- "repositoryInternal": [
17
- ".opencode/opencode.json",
18
- ".opencode/workflow-state.json",
19
- ".opencode/work-items/",
20
- ".opencode/workflow-state.js",
21
- "hooks/",
22
- "agents/",
23
- "skills/",
24
- "commands/",
25
- "context/",
26
- "docs/"
27
- ],
28
- "wrapperFacingMetadata": [
29
- "registry.json",
30
- ".opencode/install-manifest.json"
31
- ],
32
- "notes": "This file remains the live checked-in runtime manifest for the repository authoring and compatibility surface while the preferred end-user install path stays global."
33
- },
34
- "registry": {
35
- "path": "registry.json",
36
- "schema": "openkit/component-registry@1"
37
- },
38
- "installManifest": {
39
- "path": ".opencode/install-manifest.json",
40
- "schema": "openkit/install-manifest@1"
41
- },
42
- "activeProfile": "openkit-core",
43
- "installationMode": "additive-non-destructive",
44
- "runtimeSurface": "repository-internal",
45
- "wrapperMetadataSurface": "staged-additive"
46
- },
47
- "hooks": {
48
- "config": "hooks/hooks.json"
49
- },
50
- "state": {
51
- "file": ".opencode/workflow-state.json"
52
- },
53
- "agents": {
54
- "root": "agents",
55
- "primary": "agents/master-orchestrator.md",
56
- "teamRoles": [
57
- "agents/master-orchestrator.md",
58
- "agents/pm-agent.md",
59
- "agents/ba-agent.md",
60
- "agents/architect-agent.md",
61
- "agents/tech-lead-agent.md",
62
- "agents/fullstack-agent.md",
63
- "agents/qa-agent.md"
64
- ],
65
- "helpers": [
66
- "agents/code-reviewer.md"
67
- ]
68
- },
69
- "skills": {
70
- "root": "skills"
71
- },
72
- "commands": {
73
- "root": "commands",
74
- "available": [
75
- "commands/task.md",
76
- "commands/quick-task.md",
77
- "commands/migrate.md",
78
- "commands/delivery.md",
79
- "commands/brainstorm.md",
80
- "commands/write-plan.md",
81
- "commands/execute-plan.md"
82
- ]
83
- },
84
- "artifacts": {
85
- "tasks": "docs/tasks",
86
- "briefs": "docs/briefs",
87
- "specs": "docs/specs",
88
- "architecture": "docs/architecture",
89
- "plans": "docs/plans",
90
- "qa": "docs/qa",
91
- "adr": "docs/adr"
92
- }
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "instructions": [
4
+ "AGENTS.md",
5
+ "context/navigation.md"
6
+ ]
93
7
  }
package/AGENTS.md CHANGED
@@ -41,7 +41,7 @@ Current repository facts:
41
41
  - `context/core/workflow.md` is the canonical workflow-semantics document for lane behavior, stages, escalation, approvals, and quick-lane artifact expectations
42
42
  - Historical planning and example docs have been intentionally pruned from the working tree; prefer current runtime docs and git history when older rationale is needed
43
43
  - `npm install -g @duypham93/openkit`, `openkit run`, `openkit doctor`, `openkit upgrade`, and `openkit uninstall` now define the preferred operator path for the global OpenKit kit
44
- - `.opencode/opencode.json` is present as the runtime manifest for this kit
44
+ - `.opencode/opencode.json` is present as the repository-local OpenCode config for this kit
45
45
  - `.opencode/workflow-state.json` is present as the active external compatibility mirror for the active work item
46
46
  - `.opencode/work-items/` is present as the internal per-item workflow backing store for managed runtime state
47
47
  - `.opencode/workflow-state.js` now supports the live mode-aware workflow state contract
@@ -71,7 +71,7 @@ Approved follow-on direction from FEATURE-002 also includes:
71
71
  The next product-layer direction is the global OpenKit kit layered over OpenCode while preserving the checked-in authoring and compatibility runtime. In this repository today:
72
72
 
73
73
  - the global install path is implemented for the `openkit` CLI and stores the managed kit inside the OpenCode home directory, materializing it automatically on first `openkit run`
74
- - `.opencode/opencode.json` remains the checked-in authoring and compatibility runtime manifest
74
+ - `.opencode/opencode.json` remains the checked-in repository-local OpenCode config for the authoring surface
75
75
  - `registry.json` remains checked-in local metadata describing repository surfaces and profiles
76
76
  - `.opencode/install-manifest.json` remains additive local install metadata for this repository
77
77
  - project artifacts stay local to the target repository, while kit installation and workspace state are managed through the global OpenKit path
@@ -130,7 +130,7 @@ Current state:
130
130
  - No single canonical package manager or language toolchain has been established for future generated applications
131
131
  - Node.js is a documented runtime dependency for the workflow-state utility only, not for future application code by default
132
132
  - The workflow-state CLI exists and is aligned with the live stage and approval model documented in this repository
133
- - The repository-local runtime still boots from `.opencode/opencode.json`; do not claim that a root `opencode.json` entrypoint already exists unless the file is added
133
+ - The repository-local OpenCode config still lives at `.opencode/opencode.json`; do not claim that a root `opencode.json` entrypoint already exists unless the file is added
134
134
 
135
135
  Rules for agents:
136
136
 
@@ -153,8 +153,8 @@ These are illustrative patterns, not current repository commands.
153
153
 
154
154
  The operating system layer is file-backed and should stay explicit.
155
155
 
156
- - Runtime manifest: `.opencode/opencode.json`
157
- - Runtime manifest for the checked-in authoring surface: `.opencode/opencode.json`
156
+ - Repository-local OpenCode config: `.opencode/opencode.json`
157
+ - Repository-local OpenCode config for the checked-in authoring surface: `.opencode/opencode.json`
158
158
  - Active compatibility mirror: `.opencode/workflow-state.json`
159
159
  - Per-item backing store: `.opencode/work-items/`
160
160
  - Workflow-state CLI: `node .opencode/workflow-state.js ...`
package/README.md CHANGED
@@ -80,7 +80,7 @@ The preferred product path is now the globally installed OpenKit kit. This repos
80
80
  Preferred global path:
81
81
 
82
82
  1. Run `npm install -g @duypham93/openkit` to install the CLI once on the machine.
83
- 2. Run `openkit run <args>` to launch `opencode --profile openkit`; on first run, OpenKit materializes the global kit into the OpenCode home directory automatically.
83
+ 2. Run `openkit run <args>` to launch OpenCode with the OpenKit-managed kit directory injected as the active config for the current project; on first run, OpenKit materializes the global kit into the OpenCode home directory automatically.
84
84
  3. Run `openkit doctor` to confirm the global install and current workspace are healthy.
85
85
  4. Run `openkit upgrade` to refresh the installed global kit when a newer package version is available.
86
86
  5. Run `openkit uninstall [--remove-workspaces]` when you need to remove the global kit and optionally clear workspace state.
@@ -100,7 +100,7 @@ On first run, `openkit run` materializes the managed global kit into the OpenCod
100
100
 
101
101
  Current boundary:
102
102
 
103
- - `.opencode/opencode.json` is still the live runtime manifest in this checked-in repository runtime.
103
+ - `.opencode/opencode.json` is the repository-local OpenCode config for this checked-in authoring surface.
104
104
  - `.opencode/workflow-state.json`, `.opencode/work-items/`, `.opencode/workflow-state.js`, `hooks/`, `agents/`, `skills/`, `commands/`, `context/`, and `docs/` remain repository-internal runtime or support surfaces.
105
105
  - `registry.json` is local metadata describing repository surfaces and the global-kit compatibility contract.
106
106
  - `.opencode/install-manifest.json` records the local installed profile for this repository and remains additive metadata rather than a destructive installer.
@@ -196,7 +196,7 @@ node .opencode/workflow-state.js show
196
196
  node --test ".opencode/tests/*.test.js"
197
197
  ```
198
198
 
199
- The default manifest currently carries a starter model value inherited from the existing repo setup. Treat that as a default, not as a statement that the kit only supports one model.
199
+ The repository-local OpenCode config stays intentionally minimal and should not be treated as proof that the kit only supports one model or one launcher shape.
200
200
 
201
201
  ## Registry Metadata
202
202
 
@@ -204,7 +204,7 @@ OpenKit includes a small checked-in metadata layer for local inspection and for
204
204
 
205
205
  - `registry.json` describes the component categories that exist in this repository today, including agents, skills, commands, artifact directories, runtime files, hooks, and anchor docs, while also declaring which metadata participates in the global-kit compatibility contract.
206
206
  - `.opencode/install-manifest.json` records which local profile is active for this repository, points back to `registry.json`, and documents the current install stance as additive and non-destructive.
207
- - `.opencode/opencode.json` remains the live repository-local manifest while also exposing pointers to both metadata files plus the active profile name and current wrapper-readiness status.
207
+ - `.opencode/opencode.json` remains the repository-local OpenCode config, while `registry.json` and `.opencode/install-manifest.json` carry the additive OpenKit metadata for this repository.
208
208
 
209
209
  This metadata is local repository state, not a remote installer. It does not fetch, download, replace, or update components from elsewhere.
210
210
 
@@ -225,7 +225,7 @@ The install manifest is intended to make future runtime commands and diagnostics
225
225
  The current workflow for profile metadata is local and inspectable:
226
226
 
227
227
  1. `registry.json` defines the available component categories, checked-in components, and named profiles.
228
- 2. `.opencode/opencode.json` points to the registry and install manifest, declares the repository's active profile, and remains the live manifest for the current repository-local runtime.
228
+ 2. `.opencode/opencode.json` remains the repository-local OpenCode config for this worktree.
229
229
  3. `.opencode/install-manifest.json` records which profile is installed for this working tree, which broad component categories are present, and that installation remains additive rather than destructive.
230
230
  4. `node .opencode/workflow-state.js profiles` lists the named profiles from the registry.
231
231
  5. `node .opencode/workflow-state.js show-profile <name>` shows whether a profile is the repository default and which component categories it includes.
@@ -23,7 +23,7 @@ For the canonical workflow contract, including lane semantics, stage order, esca
23
23
  - Session hook configuration lives in `hooks/hooks.json`.
24
24
  - The session-start hook script lives in `hooks/session-start`.
25
25
  - The global OpenKit CLI entrypoint lives at `bin/openkit.js`.
26
- - The OpenCode kit manifest lives in `.opencode/opencode.json`.
26
+ - The repository-local OpenCode project config lives in `.opencode/opencode.json`.
27
27
  - The global install writes its own profile manifest under the OpenCode home directory.
28
28
  - The active compatibility mirror lives in `.opencode/workflow-state.json`.
29
29
  - The managed work-item backing store lives in `.opencode/work-items/`.
@@ -82,7 +82,7 @@ Current workflow-state behavior:
82
82
  - `openkit run` materializes the globally managed kit into the OpenCode home directory on first use when needed.
83
83
  - `openkit doctor` checks the global install and the current workspace bootstrap.
84
84
  - `openkit install-global` remains available as a manual or compatibility setup path.
85
- - `openkit run` launches OpenCode with the globally installed `openkit` profile and workspace-specific environment.
85
+ - `openkit run` launches OpenCode with the OpenKit-managed config directory and workspace-specific environment.
86
86
  - `openkit upgrade` refreshes the global managed kit bundle in place.
87
87
  - `openkit uninstall` removes the global managed kit and profile, with optional workspace cleanup.
88
88
  - `status`, `doctor`, `version`, `profiles`, `show-profile`, and `sync-install-manifest` are part of the current runtime inspection surface.
@@ -31,7 +31,7 @@ Use it to find canonical repository docs and upkeep surfaces quickly. Do not tre
31
31
 
32
32
  ## Repository Internals To Keep Honest
33
33
 
34
- - `.opencode/opencode.json` remains the checked-in authoring and compatibility runtime manifest even though the preferred end-user install path is now global
34
+ - `.opencode/opencode.json` remains the checked-in repository-local OpenCode config even though the preferred end-user install path is now global
35
35
  - `.opencode/workflow-state.json` remains the active compatibility mirror for the active work item
36
36
  - `.opencode/work-items/` remains the per-item backing store for managed runtime state
37
37
  - `registry.json` and `.opencode/install-manifest.json` remain additive local metadata, not destructive install machinery
@@ -46,5 +46,5 @@ Use it to find the right live docs quickly. Do not treat it as a canonical repla
46
46
 
47
47
  - The preferred user path is the global OpenKit install in the OpenCode home directory
48
48
  - `openkit install-global` remains available as a manual or compatibility setup command, but it is no longer the preferred onboarding step
49
- - `.opencode/opencode.json` remains the checked-in authoring and compatibility runtime manifest in this repository
49
+ - `.opencode/opencode.json` remains the checked-in repository-local OpenCode config in this repository
50
50
  - `Quick Task+` remains the current semantics of the `quick` lane, not a third live mode
@@ -35,7 +35,7 @@ approval_gate: tech_lead_to_fullstack
35
35
  - `npx @duypham93/openkit@latest install-global`
36
36
  - `npx @duypham93/openkit@latest doctor`
37
37
  - Day-to-day usage in any repo:
38
- - `opencode --profile openkit`
38
+ - `openkit run`
39
39
  - Existing repo should not need checked-in `agents/`, `skills/`, `commands/`, or `.opencode/` surfaces just to use the kit.
40
40
 
41
41
  ## Proposed Runtime Shape
@@ -105,7 +105,7 @@ approval_gate: tech_lead_to_fullstack
105
105
 
106
106
  ### [ ] Task 7: Register and validate the OpenCode profile integration
107
107
  - Files: global profile config templates, launcher wiring, doctor/profile checks
108
- - Goal: make `opencode --profile openkit` a supported path after global installation.
108
+ - Goal: make `openkit run` the supported path after global installation, with OpenCode launched through managed config injection rather than a profile flag.
109
109
  - Validation: profile registration can be inspected; doctor confirms registration; run-path smoke tests succeed.
110
110
  - Notes:
111
111
  - do not assume OpenCode plugin APIs that are not proven; verify the real profile/config surface during implementation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duypham93/openkit",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "type": "module",
5
5
  "files": [
6
6
  ".opencode/",
@@ -19,10 +19,10 @@ export function launchGlobalOpenKit(args = [], { projectRoot = process.cwd(), en
19
19
  OPENKIT_WORKFLOW_STATE: paths.workflowStatePath,
20
20
  OPENKIT_KIT_ROOT: paths.kitRoot,
21
21
  OPENKIT_HOME: paths.openCodeHome,
22
- OPENCODE_CONFIG_DIR: paths.profilesRoot,
22
+ OPENCODE_CONFIG_DIR: paths.kitRoot,
23
23
  };
24
24
 
25
- const result = spawn('opencode', ['--profile', 'openkit', ...args], {
25
+ const result = spawn('opencode', [paths.projectRoot, ...args], {
26
26
  cwd: paths.projectRoot,
27
27
  env: launcherEnv,
28
28
  encoding: 'utf8',
@@ -58,23 +58,10 @@ function listManagedFiles(kitRoot) {
58
58
  return files.sort();
59
59
  }
60
60
 
61
- function createProfileManifest(kitRoot, profileHooksPath) {
62
- const kitManifestPath = path.join(kitRoot, '.opencode', 'opencode.json');
63
- const kitManifest = JSON.parse(fs.readFileSync(kitManifestPath, 'utf8'));
64
-
61
+ function createOpenCodeConfig() {
65
62
  return {
66
- model: kitManifest.model,
67
- agents_dir: path.join(kitRoot, 'agents'),
68
- skills_dir: path.join(kitRoot, 'skills'),
69
- commands_dir: path.join(kitRoot, 'commands'),
70
- hooks: {
71
- config: profileHooksPath,
72
- },
73
- openkit: {
74
- profile: 'openkit',
75
- kit_root: kitRoot,
76
- manifest: kitManifestPath,
77
- },
63
+ $schema: 'https://opencode.ai/config.json',
64
+ default_agent: 'master-orchestrator',
78
65
  };
79
66
  }
80
67
 
@@ -92,8 +79,11 @@ export function materializeGlobalInstall({ env = process.env, kitVersion = '0.1.
92
79
  }
93
80
 
94
81
  const installState = createGlobalInstallState({ kitVersion, profile: 'openkit' });
82
+ const openCodeConfig = createOpenCodeConfig();
83
+
84
+ writeJson(paths.kitConfigPath, openCodeConfig);
95
85
  writeJson(paths.installStatePath, installState);
96
- writeJson(paths.profileManifestPath, createProfileManifest(paths.kitRoot, paths.profileHooksPath));
86
+ writeJson(paths.profileManifestPath, openCodeConfig);
97
87
  writeJson(paths.profileHooksPath, {
98
88
  hooks: {
99
89
  SessionStart: [
@@ -52,6 +52,7 @@ export function getGlobalPaths(options = {}) {
52
52
  return {
53
53
  openCodeHome,
54
54
  kitRoot,
55
+ kitConfigPath: path.join(kitRoot, 'opencode.json'),
55
56
  installStatePath: path.join(kitRoot, 'install-state.json'),
56
57
  managedFilesPath: path.join(kitRoot, 'managed-files.json'),
57
58
  profilesRoot,
@@ -1,13 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
 
4
- export const CONFIG_DIR_RELATIVE_PATHS = [
5
- 'agents_dir',
6
- 'commands_dir',
7
- 'skills_dir',
8
- 'hooks.config',
9
- ];
10
-
11
4
  function isPlainObject(value) {
12
5
  return value !== null && typeof value === 'object' && !Array.isArray(value);
13
6
  }
@@ -51,11 +44,6 @@ function parseJsonContent(content, sourceLabel) {
51
44
  }
52
45
  }
53
46
 
54
- function shouldResolveRelativeToConfigDir(keyPath) {
55
- const joinedPath = keyPath.filter((segment) => typeof segment === 'string').join('.');
56
- return CONFIG_DIR_RELATIVE_PATHS.includes(joinedPath);
57
- }
58
-
59
47
  function normalizeConfigPaths(value, configDir, keyPath = []) {
60
48
  if (Array.isArray(value)) {
61
49
  return value.map((entry, index) => normalizeConfigPaths(entry, configDir, [...keyPath, index]));
@@ -74,11 +62,14 @@ function normalizeConfigPaths(value, configDir, keyPath = []) {
74
62
  return value;
75
63
  }
76
64
 
77
- if (!shouldResolveRelativeToConfigDir(keyPath)) {
78
- return value;
65
+ const parentKey = keyPath.at(-2);
66
+ const currentKey = keyPath.at(-1);
67
+
68
+ if (currentKey === 'instructions' || parentKey === 'instructions') {
69
+ return path.resolve(configDir, value);
79
70
  }
80
71
 
81
- return path.resolve(configDir, value);
72
+ return value;
82
73
  }
83
74
 
84
75
  export function buildOpenCodeLayering({ projectRoot, env = process.env }) {
@@ -90,7 +90,8 @@ test('openkit install-global materializes global kit and profile files', () => {
90
90
  assert.equal(fs.existsSync(path.join(kitRoot, '.opencode', 'workflow-state.js')), true);
91
91
  assert.equal(fs.existsSync(path.join(kitRoot, 'commands', 'migrate.md')), true);
92
92
  assert.equal(fs.existsSync(path.join(profileRoot, 'opencode.json')), true);
93
- assert.equal(readJson(path.join(profileRoot, 'opencode.json')).openkit.profile, 'openkit');
93
+ assert.equal(readJson(path.join(profileRoot, 'opencode.json')).default_agent, 'master-orchestrator');
94
+ assert.equal(fs.existsSync(path.join(kitRoot, 'opencode.json')), true);
94
95
  });
95
96
 
96
97
  test('openkit init and install remain compatibility aliases for install-global', () => {
@@ -215,10 +216,10 @@ process.stdout.write('mock opencode launched\\n');
215
216
  assert.match(result.stdout, /mock opencode launched/);
216
217
 
217
218
  const invocation = readJson(logPath);
218
- assert.deepEqual(invocation.argv, ['--profile', 'openkit', '--mode', 'quick']);
219
+ assert.deepEqual(invocation.argv, [projectRoot, '--mode', 'quick']);
219
220
  assert.equal(fs.realpathSync(invocation.cwd), fs.realpathSync(projectRoot));
220
221
  assert.equal(fs.realpathSync(invocation.projectRoot), fs.realpathSync(projectRoot));
221
- assert.equal(invocation.configDir, path.join(tempHome, 'profiles', 'openkit'));
222
+ assert.equal(invocation.configDir, path.join(tempHome, 'kits', 'openkit'));
222
223
  assert.match(invocation.workflowState, /workspaces\/.*\/openkit\/\.opencode\/workflow-state\.json$/);
223
224
  assert.equal(invocation.kitRoot, path.join(tempHome, 'kits', 'openkit'));
224
225
  });
@@ -291,7 +292,7 @@ process.stdout.write('mock opencode launched after auto-install\\n');
291
292
  assert.equal(fs.existsSync(path.join(tempHome, 'kits', 'openkit', '.opencode', 'workflow-state.js')), true);
292
293
 
293
294
  const invocation = readJson(logPath);
294
- assert.deepEqual(invocation.argv, ['--profile', 'openkit']);
295
+ assert.deepEqual(invocation.argv, [projectRoot]);
295
296
  assert.equal(invocation.kitRoot, path.join(tempHome, 'kits', 'openkit'));
296
297
  });
297
298
 
@@ -5,7 +5,6 @@ import os from 'node:os';
5
5
  import path from 'node:path';
6
6
 
7
7
  import {
8
- CONFIG_DIR_RELATIVE_PATHS,
9
8
  buildOpenCodeLayering,
10
9
  } from '../../src/runtime/opencode-layering.js';
11
10
  import { launchManagedOpenCode } from '../../src/runtime/launcher.js';
@@ -23,8 +22,8 @@ test('buildOpenCodeLayering uses the managed config dir when no baseline config
23
22
  const projectRoot = makeTempDir();
24
23
 
25
24
  writeJson(path.join(projectRoot, '.opencode', 'opencode.json'), {
26
- model: 'managed-model',
27
- commands_dir: 'commands',
25
+ $schema: 'https://opencode.ai/config.json',
26
+ default_agent: 'master-orchestrator',
28
27
  });
29
28
 
30
29
  const result = buildOpenCodeLayering({ projectRoot, env: {} });
@@ -41,19 +40,15 @@ test('buildOpenCodeLayering preserves baseline config while layering managed con
41
40
  const baselineConfigDir = path.join(projectRoot, 'user-config');
42
41
 
43
42
  writeJson(path.join(baselineConfigDir, 'opencode.json'), {
44
- commands_dir: 'user-commands',
45
- hooks: {
46
- config: 'user-hooks/hooks.json',
47
- },
43
+ model: 'baseline-model',
44
+ instructions: ['./docs/global-instructions.md'],
45
+ plugin: ['existing-plugin'],
48
46
  });
49
47
 
50
48
  writeJson(path.join(projectRoot, '.opencode', 'opencode.json'), {
51
- model: 'managed-model',
52
- agents_dir: 'agents',
53
- commands_dir: 'commands',
54
- hooks: {
55
- config: 'hooks/hooks.json',
56
- },
49
+ $schema: 'https://opencode.ai/config.json',
50
+ default_agent: 'master-orchestrator',
51
+ instructions: ['AGENTS.md', 'context/navigation.md'],
57
52
  });
58
53
 
59
54
  const result = buildOpenCodeLayering({
@@ -61,12 +56,8 @@ test('buildOpenCodeLayering preserves baseline config while layering managed con
61
56
  env: {
62
57
  OPENCODE_CONFIG_DIR: baselineConfigDir,
63
58
  OPENCODE_CONFIG_CONTENT: JSON.stringify({
64
- model: 'baseline-model',
65
59
  customSetting: true,
66
- skills_dir: 'user-skills',
67
- hooks: {
68
- enabled: true,
69
- },
60
+ share: 'manual',
70
61
  }),
71
62
  },
72
63
  });
@@ -75,29 +66,24 @@ test('buildOpenCodeLayering preserves baseline config while layering managed con
75
66
 
76
67
  const layeredContent = JSON.parse(result.env.OPENCODE_CONFIG_CONTENT);
77
68
  assert.equal(layeredContent.customSetting, true);
78
- assert.equal(layeredContent.model, 'managed-model');
79
- assert.equal(layeredContent.commands_dir, 'commands');
80
- assert.equal(layeredContent.agents_dir, 'agents');
81
- assert.equal(layeredContent.skills_dir, path.join(baselineConfigDir, 'user-skills'));
82
- assert.deepEqual(layeredContent.hooks, {
83
- enabled: true,
84
- config: 'hooks/hooks.json',
85
- });
69
+ assert.equal(layeredContent.share, 'manual');
70
+ assert.equal(layeredContent.model, 'baseline-model');
71
+ assert.equal(layeredContent.default_agent, 'master-orchestrator');
72
+ assert.deepEqual(layeredContent.plugin, ['existing-plugin']);
73
+ assert.deepEqual(layeredContent.instructions, ['AGENTS.md', 'context/navigation.md']);
86
74
  assert.equal(result.baseline.configDir, baselineConfigDir);
87
- assert.equal(result.baseline.config.commands_dir, path.join(baselineConfigDir, 'user-commands'));
88
- assert.equal(
89
- result.baseline.config.hooks.config,
90
- path.join(baselineConfigDir, 'user-hooks', 'hooks.json')
91
- );
92
75
  assert.equal(result.baseline.config.model, 'baseline-model');
76
+ assert.deepEqual(result.baseline.config.instructions, [
77
+ path.join(baselineConfigDir, 'docs/global-instructions.md'),
78
+ ]);
93
79
  });
94
80
 
95
- test('buildOpenCodeLayering only normalizes the documented config-dir-relative keys', () => {
81
+ test('buildOpenCodeLayering only resolves instruction paths relative to the config dir', () => {
96
82
  const projectRoot = makeTempDir();
97
83
  const baselineConfigDir = path.join(projectRoot, 'user-config');
98
84
 
99
85
  writeJson(path.join(projectRoot, '.opencode', 'opencode.json'), {
100
- model: 'managed-model',
86
+ $schema: 'https://opencode.ai/config.json',
101
87
  });
102
88
 
103
89
  const result = buildOpenCodeLayering({
@@ -105,23 +91,13 @@ test('buildOpenCodeLayering only normalizes the documented config-dir-relative k
105
91
  env: {
106
92
  OPENCODE_CONFIG_DIR: baselineConfigDir,
107
93
  OPENCODE_CONFIG_CONTENT: JSON.stringify({
108
- model: 'baseline-model',
109
- agents_dir: 'agents',
110
- skills_dir: 'skills',
111
- commands_dir: 'commands',
112
- hooks: {
113
- config: 'hooks/hooks.json',
114
- },
94
+ instructions: ['docs/local.md'],
115
95
  otherRelativePath: 'notes/local.md',
116
96
  }),
117
97
  },
118
98
  });
119
99
 
120
- assert.deepEqual(CONFIG_DIR_RELATIVE_PATHS, ['agents_dir', 'commands_dir', 'skills_dir', 'hooks.config']);
121
- assert.equal(result.baseline.config.agents_dir, path.join(baselineConfigDir, 'agents'));
122
- assert.equal(result.baseline.config.skills_dir, path.join(baselineConfigDir, 'skills'));
123
- assert.equal(result.baseline.config.commands_dir, path.join(baselineConfigDir, 'commands'));
124
- assert.equal(result.baseline.config.hooks.config, path.join(baselineConfigDir, 'hooks', 'hooks.json'));
100
+ assert.deepEqual(result.baseline.config.instructions, [path.join(baselineConfigDir, 'docs/local.md')]);
125
101
  assert.equal(result.baseline.config.otherRelativePath, 'notes/local.md');
126
102
  });
127
103
 
@@ -129,7 +105,7 @@ test('launchManagedOpenCode reports a clear error when opencode is unavailable',
129
105
  const projectRoot = makeTempDir();
130
106
 
131
107
  writeJson(path.join(projectRoot, '.opencode', 'opencode.json'), {
132
- model: 'managed-model',
108
+ $schema: 'https://opencode.ai/config.json',
133
109
  });
134
110
 
135
111
  const result = launchManagedOpenCode([], {
@@ -153,7 +129,7 @@ test('launchManagedOpenCode uses interactive stdio by default for the real launc
153
129
  let spawnCall = null;
154
130
 
155
131
  writeJson(path.join(projectRoot, '.opencode', 'opencode.json'), {
156
- model: 'managed-model',
132
+ $schema: 'https://opencode.ai/config.json',
157
133
  });
158
134
 
159
135
  const result = launchManagedOpenCode(['status'], {
@@ -178,13 +154,14 @@ test('launchManagedOpenCode forwards layered config to opencode on the supported
178
154
  const baselineConfigDir = path.join(projectRoot, 'user-config');
179
155
 
180
156
  writeJson(path.join(baselineConfigDir, 'opencode.json'), {
181
- skills_dir: 'baseline-skills',
157
+ model: 'baseline-model',
158
+ instructions: ['./docs/global-instructions.md'],
182
159
  });
183
160
 
184
161
  writeJson(path.join(projectRoot, '.opencode', 'opencode.json'), {
185
- model: 'managed-model',
186
- commands_dir: 'commands',
187
- agents_dir: 'agents',
162
+ $schema: 'https://opencode.ai/config.json',
163
+ default_agent: 'master-orchestrator',
164
+ instructions: ['AGENTS.md', 'context/navigation.md'],
188
165
  });
189
166
 
190
167
  fs.mkdirSync(fakeBinDir, { recursive: true });
@@ -223,8 +200,7 @@ test('launchManagedOpenCode forwards layered config to opencode on the supported
223
200
 
224
201
  const layeredContent = JSON.parse(payload.configContent);
225
202
  assert.equal(layeredContent.customSetting, true);
226
- assert.equal(layeredContent.model, 'managed-model');
227
- assert.equal(layeredContent.commands_dir, 'commands');
228
- assert.equal(layeredContent.agents_dir, 'agents');
229
- assert.equal(layeredContent.skills_dir, path.join(baselineConfigDir, 'baseline-skills'));
203
+ assert.equal(layeredContent.model, 'baseline-model');
204
+ assert.equal(layeredContent.default_agent, 'master-orchestrator');
205
+ assert.deepEqual(layeredContent.instructions, ['AGENTS.md', 'context/navigation.md']);
230
206
  });
@@ -1,3 +0,0 @@
1
- {
2
- "type": "commonjs"
3
- }