@ngockhoale/ukit 2.7.1 → 2.7.3

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 (52) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/README.md +1 -3
  3. package/manifests/hostCapabilities.yaml +0 -10
  4. package/manifests/instructionRules.yaml +0 -16
  5. package/manifests/platform.full.yaml +2 -16
  6. package/package.json +3 -5
  7. package/scripts/perf/audit-perf.mjs +4 -4
  8. package/scripts/perf/perf-findings.json +420 -0
  9. package/src/cli/adapters.js +10 -13
  10. package/src/cli/commands/doctor.js +60 -10
  11. package/src/cli/index.js +2 -2
  12. package/src/core/ompConfigMerge.js +19 -0
  13. package/src/core/opencodeSteer.js +37 -0
  14. package/src/core/permissionDoctor.js +319 -0
  15. package/src/core/permissionPolicy.js +179 -0
  16. package/src/core/projectImportant.js +14 -8
  17. package/src/core/runInstallPipeline.js +25 -0
  18. package/src/core/runtimeConfig.js +43 -4
  19. package/src/core/status.js +6 -4
  20. package/src/core/unattendedDoctor.js +9 -5
  21. package/src/manifest/selectItems.js +0 -1
  22. package/src/render/buildVariables.js +10 -1
  23. package/templates/.claude/agents/bug-debugger.md +1 -1
  24. package/templates/.claude/agents/feature-implementer.md +1 -1
  25. package/templates/.claude/agents/ukit-small-task-maintainer.md +2 -2
  26. package/templates/.claude/commands/ukit/handoff-create.md +4 -4
  27. package/templates/.claude/commands/ukit/handoff-fullstack.md +4 -4
  28. package/templates/.claude/commands/ukit/handoff-implement.md +2 -2
  29. package/templates/.claude/commands/ukit/handoff-review.md +2 -2
  30. package/templates/.claude/settings.json +14 -6
  31. package/templates/.claude/skills/update-status/SKILL.md +1 -1
  32. package/templates/.claude/ukit/index/route-task.mjs +7 -2
  33. package/templates/.claude/ukit/skill-router-state.json +1 -0
  34. package/templates/.codex/README.md +1 -1
  35. package/templates/.codex/settings.json +0 -1
  36. package/templates/.omp/agents/bug-debugger.md +1 -1
  37. package/templates/.omp/agents/feature-implementer.md +1 -1
  38. package/templates/.omp/agents/ukit-small-task-maintainer.md +2 -2
  39. package/templates/.omp/config.yml +13 -7
  40. package/templates/.ukit/storage/cache/hook-latency/unknown.jsonl +4 -0
  41. package/templates/AGENTS.md +4 -13
  42. package/templates/CLAUDE.md +1 -3
  43. package/templates/adapter-presets/claude/settings.local.json +0 -1
  44. package/templates/docs/AI_HANDOFF/INDEX.md +1 -1
  45. package/templates/docs/AI_HANDOFF/RULES.md +2 -2
  46. package/templates/docs/PROJECT.md +1 -1
  47. package/templates/docs/UKIT_INTERNALS.md +1 -1
  48. package/templates/instructions/core.md +1 -3
  49. package/templates/instructions/layout.yaml +2 -4
  50. package/templates/instructions/overlays/agents.md +3 -10
  51. package/templates/ukit/storage/config.json +2 -10
  52. package/templates/adapter-presets/opencode/opencode.template.json +0 -1
package/CHANGELOG.md CHANGED
@@ -2,6 +2,78 @@
2
2
 
3
3
  All notable changes to UKit are documented here.
4
4
 
5
+ ## 2.7.3 - 2026-09-20
6
+
7
+ AI freeze audit remediation — cycle C38 (TASK-001..007).
8
+
9
+ - OpenCode residual sweep: `rg -i opencode` inventory classified into
10
+ keepers vs residuals; residual surfaces removed or steer-only, with a
11
+ zero-residual manifest test guarding regressions.
12
+ - Unresolved-template-token repair: `mergeOmpConfig` + `diffPlan` detect
13
+ literal `{{token}}` left in rendered artifacts, repair known tokens,
14
+ report unknown ones via `unresolvedTokens` (never fabricate); install
15
+ prints a repair line like the C35 migration line.
16
+ - `orchestration.allowUnsafeEval` (default `false`, optional-present):
17
+ only an explicit `true` renders `tools.approval.eval: allow` in
18
+ `.omp/config.yml` via the `omp.evalApproval` render variable; every
19
+ other state renders `deny` — fail-closed, never prompt. Migrations
20
+ never enable it; absence keeps the safe default.
21
+ - `src/core/permissionPolicy.js` — pure semantic compiler
22
+ `compilePermissionPolicy({ permissionMode, allowUnsafeEval, host,
23
+ surfaces? })`: canonical deny set + precedence tiers
24
+ (hard-deny > protected-guard > host-deny > explicit-allow >
25
+ mode-fallback), models `interactive`/`safe-auto`/`unattended` across
26
+ claude/omp/codex, throws `UKIT_EPOLICY` on unknown mode. Render,
27
+ doctor, and the matrix share it as single source of truth.
28
+ - `ukit doctor --permissions [--json]`: `src/core/permissionDoctor.js`
29
+ compiles the policy against live surfaces and reports FAIL classes
30
+ (unattended-prompt, deny-loss, unsafe-eval-mismatch,
31
+ unrendered-token) with exit 1; reachable prompts under
32
+ interactive/safe-auto report as INFO, absent host surfaces SKIP;
33
+ compact section in the default doctor run, full table under the flag.
34
+ - No-freeze matrix (`tests/manifest/c38NoFreezeMatrix.test.js`):
35
+ safe→allow, destructive→deny+recovery, unknown-in-unattended never
36
+ asks, truncated payloads fail closed, merge idempotent, zero `{{`
37
+ residuals.
38
+ - Canonical deny surfaces closed (R4.5 review): `templates/.claude/
39
+ settings.json` now denies the full canonical destructive set
40
+ (`git push -f`, `git clean -fd`, `git checkout .`, `git restore .`,
41
+ `rm -rf .`, `rm -rf`, `dd if=/dev/`, `*> /dev/sda`, `mkfs`,
42
+ fork-bomb) and the `gh pr create/comment` + `gh issue comment`
43
+ entries moved `ask`→`deny` — static surfaces can't express
44
+ ask-under-interactive-only, so deny is the only mode-safe posture
45
+ (unattended runs must never reach a prompt). `templates/.omp/
46
+ config.yml` gains `git push --force-with-lease*`. Report-only hosts
47
+ (codex) no longer count toward doctor `deny-loss`.
48
+ - `ukit-bridge.js` (omp): `ask` verdicts now degrade to `block` with a
49
+ recorded cause + recovery route instead of surfacing an interactive
50
+ prompt under unattended mode (audit row 61).
51
+ - Docs: `docs/UKIT_INTERNALS.md` gains a Permission Modes + Unsafe Eval
52
+ section — unattended ≠ all-destructive-allowed; a deny routes the
53
+ agent to the next safer alternative, and the host-internal-wait
54
+ guidance is unchanged.
55
+
56
+ ## 2.7.2 - 2026-09-20
57
+
58
+ OpenCode adapter removal — cycle C37 (TASK-001..004).
59
+
60
+ - Removed the OpenCode adapter lane end to end: adapter registry key +
61
+ aliases, `templates/adapter-presets/opencode/`, host-capability matrix
62
+ entry, doc-benchmark `opencode.yaml` fixture + BMK-09, manifest/manifest
63
+ wiring, `--tools` help listing, and root `opencode.json` dogfood file.
64
+ - Steer-not-break detection: a leftover `opencode.json` is a user file —
65
+ install/status/doctor now detect it via `src/core/opencodeSteer.js` and
66
+ print one canonical warning advising manual removal (`rm opencode.json`);
67
+ the file is never written, merged, pruned, or auto-deleted.
68
+ - Legacy tolerance: stale `agent`/`agents`/`compact.agentContext.targets`
69
+ values naming `opencode` are normalized away with a warning instead of
70
+ hard-failing; `--tools=opencode` / `--adapter opencode` warn + ignore /
71
+ fall back with exit 0; uninstall still removes a tracked `opencode.json`
72
+ on explicit user request; `opencode.json` stays in gitignore advice.
73
+ - Packaging: `package.json` description/keywords/`files` and `.npmignore`
74
+ no longer reference the deleted preset; `packageArtifact.test.js` asserts
75
+ the tarball ships zero `adapter-presets/opencode` entries.
76
+
5
77
  ## 2.7.1 - 2026-09-20
6
78
 
7
79
  omp native-tier steering — cycle C36 (TASK-001..005).
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # UKit
2
2
 
3
- UKit installs a project-local AI workspace (`.claude/`, adapters, docs, and index helpers) so your team can work with Claude Code, OpenAI Codex, OpenCode, and omp (Oh My Pi) from the same repo setup.
3
+ UKit installs a project-local AI workspace (`.claude/`, adapters, docs, and index helpers) so your team can work with Claude Code, OpenAI Codex, and omp (Oh My Pi) from the same repo setup.
4
4
 
5
5
  ## Install
6
6
 
@@ -39,7 +39,6 @@ Fill in the generated docs baseline (`docs/PROJECT.md`, `docs/MEMORY.md`, `docs/
39
39
 
40
40
  **Adapters**
41
41
  - `.codex/settings.json` + `.codex/settings.local.json` — Codex config
42
- - `opencode.json` — OpenCode project config with UKit-safe guardrails
43
42
  - `.omp/AGENTS.md` — thin `@../AGENTS.md` import so omp reads the shared instructions
44
43
  - `.omp/RULES.md` — sticky hard rules for omp sessions
45
44
  - `.omp/config.yml` — omp model roles, tool approval, and bash patterns
@@ -75,7 +74,6 @@ When long sessions approach the compact threshold, UKit compacts only safe-zone
75
74
  |------|-------------|--------|--------|
76
75
  | Claude Code | `CLAUDE.md` | `.claude/skills/` (canonical) | `.claude/settings.json` |
77
76
  | OpenAI Codex | `AGENTS.md` | `.claude/skills/` (referenced) | `.codex/settings.json`, `.codex/settings.local.json`, `.codex/README.md` |
78
- | OpenCode | `AGENTS.md` | `.claude/skills/` (native Claude-compatible support) | `opencode.json` |
79
77
  | omp (Oh My Pi) | `.omp/AGENTS.md` (imports `AGENTS.md`) | `.claude/skills/` (read via omp's claude provider — no symlink) | `.omp/config.yml`, `.omp/RULES.md`, `.omp/README.md` |
80
78
 
81
79
  All supported tools share the same SKILL.md ecosystem so the workspace is authored once and reused everywhere.
@@ -27,16 +27,6 @@ hosts:
27
27
  owner-file-injection: { state: observed, note: 'AGENTS.md rendered for codex; parity asserted only at artifact level' }
28
28
  settings-env: { state: tested, evidence: tests/integration/installPipeline.test.js }
29
29
  context-files: { state: tested, evidence: tests/integration/installPipeline.test.js }
30
- opencode:
31
- skills: { state: observed, note: 'reads .claude/skills via discovery; asserted indirectly by artifact tests' }
32
- subagents: { state: unknown }
33
- hooks: { state: unknown }
34
- session-start-injection: { state: unknown }
35
- stop-gate: { state: unknown }
36
- slash-commands: { state: observed, note: 'ukit-* helper entrypoints declared in opencode.json' }
37
- owner-file-injection: { state: observed, note: 'AGENTS.md loaded at session start; no injection test' }
38
- settings-env: { state: tested, evidence: tests/integration/installPipeline.test.js }
39
- context-files: { state: observed, note: 'AGENTS.md asserted by install pipeline; no opencode-specific parse test' }
40
30
  omp:
41
31
  skills: { state: observed, note: 'omp reads .claude/skills via claude discovery provider' }
42
32
  subagents: { state: tested, evidence: tests/consistency/ompAgentParity.test.js }
@@ -412,22 +412,6 @@ rules:
412
412
  When the same file or symbol fails debugLoopThreshold times in one
413
413
  session, route the next attempt one tier higher, capped at smart.
414
414
  marker_in: [templates/CLAUDE.md, templates/AGENTS.md, CLAUDE.md, AGENTS.md]
415
- - id: HOST-OC-01
416
- title: OpenCode must explicitly read the triggered SKILL.md
417
- kind: critical
418
- statement: >-
419
- OpenCode reads AGENTS.md at session start only and does not auto-load
420
- skills; the model must explicitly read the triggered SKILL.md.
421
- marker_in: [templates/AGENTS.md, AGENTS.md]
422
- anchor: 'read the triggered SKILL.md'
423
- - id: HOST-OWN-01
424
- title: Codex/OpenCode read the root owner instructions
425
- kind: critical
426
- statement: >-
427
- When running in Codex or OpenCode, read and follow the root
428
- PROJECT_IMPORTANT.md before doing project work.
429
- marker_in: [templates/AGENTS.md, AGENTS.md]
430
- anchor: 'read and follow the root'
431
415
  - id: DURA-01
432
416
  title: DuraOne skill activates only when installed
433
417
  kind: supporting
@@ -124,8 +124,8 @@ items:
124
124
  - docs-project
125
125
  - docs-memory
126
126
  mergeStrategy: overwrite_with_backup
127
- # Same set as root-claude-md: AGENTS.md is the same body with a different H1 plus one
128
- # OpenCode-only section, so it interpolates the same variables. Kept in sync by
127
+ # Same set as root-claude-md: AGENTS.md is the same body with a different H1, so it
128
+ # interpolates the same variables. Kept in sync by
129
129
  # tests/consistency/contextDocsParity.test.js.
130
130
  variables:
131
131
  - project.name
@@ -1805,17 +1805,3 @@ items:
1805
1805
  packs:
1806
1806
  - core
1807
1807
 
1808
- # --- OpenCode ---
1809
-
1810
- - id: multi-opencode-config
1811
- type: config
1812
- sourceTemplate: adapter-presets/opencode/opencode.template.json
1813
- targetPath: opencode.json
1814
- requires: []
1815
- mergeStrategy: overwrite_with_backup
1816
- variables:
1817
- - project.name
1818
- - runtime.packageManager
1819
- enabledByDefault: true
1820
- packs:
1821
- - core
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ngockhoale/ukit",
3
- "version": "2.7.1",
4
- "description": "Install/update an index-first AI workspace for Claude Code, OpenAI Codex, OpenCode, and omp (Oh My Pi).",
3
+ "version": "2.7.3",
4
+ "description": "Install/update an index-first AI workspace for Claude Code, OpenAI Codex and omp (Oh My Pi).",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "keywords": [
@@ -9,7 +9,6 @@
9
9
  "claude",
10
10
  "codex",
11
11
  "claude-code",
12
- "opencode",
13
12
  "omp",
14
13
  "oh-my-pi",
15
14
  "skills",
@@ -37,8 +36,7 @@
37
36
  "templates/CLAUDE.md",
38
37
  "templates/AGENTS.md",
39
38
  "templates/.gitignore",
40
- "manifests/",
41
- "templates/adapter-presets/opencode/opencode.template.json"
39
+ "manifests/"
42
40
  ],
43
41
  "publishConfig": {
44
42
  "access": "public"
@@ -3,8 +3,8 @@
3
3
  * audit-perf.mjs — TASK-233 (SPEC §2 FR-001) performance audit generator.
4
4
  *
5
5
  * Measures every SPEC §2 area from four independent sources and writes
6
- * `docs/AI_REPORT/perf-findings.json` (machine-readable, consumed by TASK-234,
7
- * TASK-235 and TASK-236) plus `docs/AI_REPORT/perf-measure.md` (raw appendix).
6
+ * `scripts/perf/perf-findings.json` (machine-readable, consumed by TASK-234,
7
+ * TASK-235 and TASK-236) plus `perf-measure.md` next to it (raw appendix).
8
8
  * Running this again with the same arguments IS the "measure it the same way
9
9
  * both times" requirement from SPEC §5 — TASK-236 re-runs it for before/after.
10
10
  *
@@ -735,7 +735,7 @@ function renderMeasureDoc(context) {
735
735
  lines.push('```bash');
736
736
  lines.push('node scripts/perf/audit-perf.mjs \\');
737
737
  lines.push(` --telemetry-dir "${telemetry.dir || path.join(root, '.ukit', 'storage', 'cache', 'hook-latency')}" \\`);
738
- lines.push(` --out "${root}/docs/AI_REPORT/perf-findings.json"`);
738
+ lines.push(` --out "${root}/scripts/perf/perf-findings.json"`);
739
739
  lines.push('node --test tests/handoff/c33/perfFindings.test.js');
740
740
  lines.push('```');
741
741
  lines.push('');
@@ -848,7 +848,7 @@ function main() {
848
848
  const options = parseArgs(process.argv.slice(2));
849
849
  const root = options.root;
850
850
  const telemetryDir = options.telemetryDir || path.join(root, '.ukit', 'storage', 'cache', 'hook-latency');
851
- const outFile = options.out || path.join(root, 'docs', 'AI_REPORT', 'perf-findings.json');
851
+ const outFile = options.out || path.join(root, 'scripts', 'perf', 'perf-findings.json');
852
852
  const measureFile = path.join(path.dirname(outFile), 'perf-measure.md');
853
853
 
854
854
  const telemetry = loadTelemetry(telemetryDir);