@ngockhoale/ukit 2.2.1 → 2.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.
- package/CHANGELOG.md +29 -0
- package/manifests/platform.full.yaml +8 -0
- package/package.json +1 -1
- package/templates/.claude/commands/ukit/handoff-clear.md +1 -1
- package/templates/.claude/commands/ukit/handoff-create.md +4 -4
- package/templates/.claude/commands/ukit/handoff-fullstack.md +11 -9
- package/templates/.claude/commands/ukit/handoff-implement.md +2 -2
- package/templates/.claude/commands/ukit/handoff-review.md +1 -1
- package/templates/.claude/commands/ukit/handoff-status.md +1 -1
- package/templates/.claude/ukit/index/unic-gateway.mjs +23 -26
- package/templates/.omp/RULES.md +40 -12
- package/templates/.omp/config.yml +9 -7
- package/templates/.omp/hooks/pre/ukit-bridge.js +42 -10
- package/templates/AGENTS.md +131 -63
- package/templates/CLAUDE.md +59 -21
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to UKit are documented here.
|
|
4
4
|
|
|
5
|
+
## 2.2.2 - 2026-08-22
|
|
6
|
+
|
|
7
|
+
Running Claude Code and omp side by side exposed that they were not, in fact, running the same UKit. `CLAUDE.md` and `AGENTS.md` are hand-maintained forks of one instruction set read by different harnesses, and `AGENTS.md` had fallen three minor versions behind — so omp was never told the model-tier table existed. This wave re-unifies them and adds a test that makes the drift impossible to repeat.
|
|
8
|
+
|
|
9
|
+
It also settles the three `TODO(verify)` items 2.2.1 shipped with. Those were plan-time guesses about omp's API, unresolvable at the time because omp was not installed on any machine that could answer them. omp v17.4.2 is now installed and was inspected directly — and two of the three guesses were wrong, in the quiet way where nothing errors and the feature simply never engages.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **Auto-compact was never actually configured on omp.** `.omp/config.yml` set `compact.autoCompactWindow: 180000`, a key omp does not have — `omp config get compact.autoCompactWindow` answers "Unknown setting", so the value was inert and omp stayed on its own default. The real key is `compaction.thresholdTokens` ("Fixed token limit for context maintenance; overrides percentage if set", omp's default `-1`). Verified end-to-end against a scratch project: the nested form now reads back as `180000`, which is below `compact.hardCapTokens` (220000) as intended, so auto-compact fires before `context-hardcap-gate.sh` starts blocking tool calls.
|
|
14
|
+
- **Post-compact hooks never ran on omp.** The bridge assumed omp re-emitted `session_start` after a compaction, the way Claude Code's matcher-less `SessionStart` hook fires with `source: "compact"`. It does not — it has a dedicated event instead (`session_before_compact` → `session.compacting` → `session_compact`, the last firing once compaction settles). So on omp the entire post-compact chain was lost: the run cursor stayed un-surfaced, compact pressure was never reset, and a mid-cycle handoff silently failed to resume after a compaction. `ukit-bridge.js` now maps `session_compact` onto the same script chain, keeping `hook_event_name: 'SessionStart'` in the payload so the scripts stay shared with Claude Code rather than forked.
|
|
15
|
+
- **Two UNIC gateway probes could never have fired.** `unic-gateway.mjs` probed an `OMP_BASE_URL` env var and a `baseUrl` key in `.omp/config.yml`. Neither exists: omp's anthropic provider reads `ANTHROPIC_BASE_URL` (falling back to `https://api.anthropic.com`), and its settings schema declares no `baseUrl` at any level. Both probes are removed rather than left returning a permanent `false` — a probe that can never fire is worse than no probe, because it reads as coverage. Detection is unchanged in behaviour and now literally matches what the docs already claimed: routing is decided only by `ANTHROPIC_BASE_URL`, on omp for the same reason as on Claude Code.
|
|
16
|
+
- **omp behaved as if UKit only had one model, because it was never told otherwise.** `templates/AGENTS.md` — the context doc omp, Codex and OpenCode read — was missing the entire `3-Tier Model Routing` block, plus `Post-Edit Sidecar Review` and `Skill Quality`, and still announced itself as `UKit v1.5.1`. `.omp/config.yml` declared `modelRoles` for all four lanes, but nothing in omp's context ever said *when* to use a tier, so everything ran inline on the session model.
|
|
17
|
+
- **Five section pairs had been renamed apart** — `Core Rule`/`Core UKit Rule`, `Fast Classification`/`Fast Task Classification`, `Internal Helper Policy`/`Internal Helper Routing`, `Selective Subagent Policy`/`Subagent Policy`, `Project Snapshot`/`Environment Snapshot`. This is what let the drift hide: once the headings differ, no diff lines up and the gap is invisible. Headings are now shared, and the two docs carry byte-identical bodies for every shared section.
|
|
18
|
+
- **Every session opened by being told to resume a finished cycle.** `docs/AI_HANDOFF/RUN.md` was left at `Phase: R4` after 2.2.1 shipped, so `handoff-resume.sh` — which runs in the `session_start` chain of *both* Claude Code and the omp bridge — fired a "CONTINUATION — resume immediately" banner at the start of every new, unrelated session. The cursor now reads `Phase: done`.
|
|
19
|
+
- **`/ukit:*` commands re-pasted the user's whole problem statement up to seven times per file.** Only one `$ARGUMENTS` site per command is a real interpolation (the `## Problem / feature` body); the other six were *references* that expanded to the entire paragraph again mid-sentence. They now say "the **Problem / feature** section above".
|
|
20
|
+
- **Eight fallback lines told the model to do something only a human can do.** `> Other tools without subagent support: manually switch to the strong model` reads, to a running model, as an instruction to itself — which it cannot follow, so it improvises. Each is now explicitly addressed: `> **For the human operator, on a tool with no agent support (Codex, OpenCode) — not an instruction to the model:**`.
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **`### How a tier is actually bound`** in both context docs. The main session model never changes mid-turn; a tier only takes effect when work is handed to an agent whose own definition binds that model. The section carries a harness table (Claude Code `.claude/agents/*.md` + `subagent_type`, omp `.omp/agents/*.md` + `task-agent`) and states the consequence plainly: doing everything inline is exactly what makes UKit behave as if it had one model.
|
|
25
|
+
- **`tests/consistency/contextDocsParity.test.js`** (29 tests) — every `## ` section must exist in both `templates/CLAUDE.md` and `templates/AGENTS.md` with byte-identical bodies, unless allowlisted with a stated reason (currently one entry: `Session Start — OpenCode`, which exists because OpenCode does not auto-load `.claude/skills/`). Also asserts neither doc hardcodes a version, and that both manifest items declare the same variable set.
|
|
26
|
+
- **`.omp/RULES.md` grew from 4 rules to 7**, targeting direct chat specifically — direct chat is steered only by static context, so what is missing there is simply never applied. New: `Classify first, then act` (Trivial / Simple / Non-trivial lanes, decided *before* the first tool call), `Auto-activate skills`, and `Delegate to bind a model tier`. It stays short on purpose: it is re-attached near every turn.
|
|
27
|
+
- **The three `/ukit:*` sites that named only Claude Code now name omp too** — `handoff-fullstack.md`'s Model Split note, and the small-task-maintainer lines in `handoff-clear.md` and `handoff-status.md`.
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
|
|
31
|
+
- **Four more expired one-shot guards re-anchored, same class as the two below.** `ompDocsSync` cases 3 and 6 validated "the top CHANGELOG entry" — true on the day 2.2.1 shipped, false at the next release; they now find the omp entry by version. `ompContextLayer` case 10 guarded the compact key with a `TODO(verify)` marker instead of a value, and now asserts the verified key plus its provenance. `tests/handoff/cycle4/unic-gateway.test.mjs` case 13b had never actually run (it took its skip branch because the file it checked did not exist yet) and was matching a key spelling — `@vision:` — that belongs to the agent side, not the config side.
|
|
32
|
+
- **`tests/consistency/ompCommandParity.test.js` cases 4 and 5 no longer diff against `git show HEAD:`.** They were scope guards for one in-flight cycle ("TASK-005 must not modify these"), and that premise expired when the cycle shipped: against a committed baseline they pass vacuously, and against a dirty tree they block every later legitimate edit instead — which is exactly what they did. Both are re-expressed as the durable properties they stood in for (no `subagent_type` site in the two non-delegation commands; pinned per-file `Do NOT` and tier-justification-clause counts). No protection was dropped, only re-anchored.
|
|
33
|
+
|
|
5
34
|
## 2.2.1 - 2026-08-22
|
|
6
35
|
|
|
7
36
|
UKit gains a fourth runtime and loses one. omp (Oh My Pi) reaches full parity with the Claude Code workspace — same agents, same skills, same hooks, same `/ukit:*` commands — and the Antigravity adapter, unused and unmaintained, is gone. The parity is deliberate rather than incidental: the port reuses the existing `.claude/` assets wherever omp's discovery can already reach them, so there is one source of truth per capability, not two that drift.
|
|
@@ -110,13 +110,21 @@ items:
|
|
|
110
110
|
- docs-project
|
|
111
111
|
- docs-memory
|
|
112
112
|
mergeStrategy: overwrite_with_backup
|
|
113
|
+
# Same set as root-claude-md: AGENTS.md is the same body with a different H1 plus one
|
|
114
|
+
# OpenCode-only section, so it interpolates the same variables. Kept in sync by
|
|
115
|
+
# tests/consistency/contextDocsParity.test.js.
|
|
113
116
|
variables:
|
|
114
117
|
- project.name
|
|
118
|
+
- project.root
|
|
115
119
|
- project.stack
|
|
116
120
|
- stack.frontend
|
|
117
121
|
- stack.backendApi
|
|
118
122
|
- stack.postgres
|
|
119
123
|
- runtime.packageManager
|
|
124
|
+
- runtime.os
|
|
125
|
+
- runtime.nodeVersion
|
|
126
|
+
- providers.unic
|
|
127
|
+
- ukit.version
|
|
120
128
|
enabledByDefault: true
|
|
121
129
|
packs:
|
|
122
130
|
- core
|
package/package.json
CHANGED
|
@@ -57,7 +57,7 @@ Cleared: X worktrees removed, Y branches deleted, staged changes unstaged.
|
|
|
57
57
|
Handoff docs reset. Ready for new cycle.
|
|
58
58
|
```
|
|
59
59
|
|
|
60
|
-
> Claude Code: spawn `ukit-small-task-maintainer` (haiku).
|
|
60
|
+
> Claude Code: spawn `ukit-small-task-maintainer` (haiku). omp: the `task` tool with `agent: "ukit-small-task-maintainer"`.
|
|
61
61
|
> Other tools: lite model, follow steps 1–5.
|
|
62
62
|
|
|
63
63
|
**Next:** `/ukit:handoff-create <new problem description>`
|
|
@@ -22,7 +22,7 @@ Planning is the **only** place in the handoff pipeline where asking the human is
|
|
|
22
22
|
it is where every ambiguity must be burned off. Whatever is left unresolved here becomes a
|
|
23
23
|
guess during implementation, where nobody is available to correct it.
|
|
24
24
|
|
|
25
|
-
**Ask once, up front, batched.** Before Step 1, if
|
|
25
|
+
**Ask once, up front, batched.** Before Step 1, if the **Problem / feature** section above leaves a choice that changes
|
|
26
26
|
*what gets built* — not how — collect every such question into a **single** `AskUserQuestion`
|
|
27
27
|
call (max 4 questions, each with a `(Recommended)` first option). Then close the window.
|
|
28
28
|
|
|
@@ -49,7 +49,7 @@ After the batched call, run Steps 1–2.5 to completion without further question
|
|
|
49
49
|
4. Read `docs/AI_HANDOFF/tasks/_TEMPLATE.md` → task file structure
|
|
50
50
|
5. Return a compact summary. Do NOT write anything yet.
|
|
51
51
|
|
|
52
|
-
>
|
|
52
|
+
> **For the human operator, on a tool with no agent support (Codex, OpenCode) — not an instruction to the model:** manually switch to the lite model, run the steps above yourself, keep the summary in context.
|
|
53
53
|
|
|
54
54
|
---
|
|
55
55
|
|
|
@@ -106,7 +106,7 @@ The planner agent does the following (use Step 1 summary — do NOT re-read file
|
|
|
106
106
|
|
|
107
107
|
7. Report: task IDs, dependency graph, any `needs_breakdown` + reason
|
|
108
108
|
|
|
109
|
-
>
|
|
109
|
+
> **For the human operator, on a tool with no agent support (Codex, OpenCode) — not an instruction to the model:** manually switch to the strong model, execute steps 1–7 above yourself.
|
|
110
110
|
|
|
111
111
|
---
|
|
112
112
|
|
|
@@ -127,7 +127,7 @@ intact. What it no longer does is hand a stalled plan back and wait.
|
|
|
127
127
|
2. `Issues Found` → route back to Step 2: planner revises `PLAN.md` and the affected `TASK-xxx.md` files to address every finding, then re-submit for another Step 2.5 review (this becomes the next round). Do NOT commit or hand off to executor on `Issues Found`.
|
|
128
128
|
3. `Approved` → append `PLAN_REVIEW: Approved by <reviewer model>` to PLAN.md's `## Planner Report` footer, then proceed.
|
|
129
129
|
|
|
130
|
-
>
|
|
130
|
+
> **For the human operator, on a tool with no agent support (Codex, OpenCode) — not an instruction to the model:** manually switch to the strong model in a **separate** chat/session from Step 2, paste PLAN.md, review using the Spec/Plan Review checklist in `.claude/agents/code-reviewer.md`.
|
|
131
131
|
|
|
132
132
|
---
|
|
133
133
|
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
| Planning + Review (reasoning, design, verification) | opus · unic-smart · strongest available |
|
|
13
13
|
|
|
14
14
|
> Claude Code: spawn `ukit-small-task-maintainer` (haiku) for light steps; spawn `handoff-planner` (opus) for planning; spawn `feature-implementer` (sonnet) agents for implementation; spawn `code-reviewer` (opus) per task for review.
|
|
15
|
+
>
|
|
16
|
+
> omp: same four agents, launched with the `task` tool (`agent: "<name>"`). They live in `.omp/agents/` and bind their tier through `model: "@lite"` / `"@code"` / `"@smart"`, resolved via `modelRoles` in `.omp/config.yml` — you do not pass a model name.
|
|
15
17
|
|
|
16
18
|
> **omp model tiers:** the tiers above map to `.omp/config.yml`'s `modelRoles`, referenced from agent frontmatter as `@lite` / `@code` / `@smart`.
|
|
17
19
|
|
|
@@ -20,17 +22,17 @@
|
|
|
20
22
|
## Problem / feature
|
|
21
23
|
$ARGUMENTS
|
|
22
24
|
|
|
23
|
-
> **If
|
|
25
|
+
> **If the **Problem / feature** section above is empty:** Do NOT proceed. Ask the user: "What problem or feature would you like to tackle in this handoff cycle? Please describe it in one or more sentences." Wait for the answer before running any phase.
|
|
24
26
|
|
|
25
27
|
---
|
|
26
28
|
|
|
27
29
|
## Autonomy Contract — read before anything else
|
|
28
30
|
|
|
29
31
|
This command is a **one-shot pipeline**. The human is not watching. Treat every phase below
|
|
30
|
-
as unattended: they may walk away after submitting
|
|
32
|
+
as unattended: they may walk away after submitting the request and come back to a finished
|
|
31
33
|
result.
|
|
32
34
|
|
|
33
|
-
**The single question window is P0, before any file is written.** If
|
|
35
|
+
**The single question window is P0, before any file is written.** If the **Problem / feature** section above leaves a
|
|
34
36
|
choice that would change what gets built — not how it gets built — batch every such question
|
|
35
37
|
into **one** `AskUserQuestion` call (max 4 questions, each with a `(Recommended)` first
|
|
36
38
|
option) and resolve them all at once. Record the answers in `PLAN.md` §1.
|
|
@@ -62,7 +64,7 @@ numbered step completes:
|
|
|
62
64
|
|
|
63
65
|
```
|
|
64
66
|
Command: handoff-fullstack
|
|
65
|
-
Goal: <one sentence from
|
|
67
|
+
Goal: <one sentence from the **Problem / feature** section above>
|
|
66
68
|
Base: <BASE branch>
|
|
67
69
|
Phase: <P1|P2|P2.5|P3|I1|I2|I3|I4|R1|R2|R3|R4|R5|done>
|
|
68
70
|
Cursor: wave <N> batch <M> — <what just finished>
|
|
@@ -80,7 +82,7 @@ continue. Read the cursor, then jump straight to `Next:` and carry on. Tasks alr
|
|
|
80
82
|
or `pending_review` are skipped; only `ready`, `in_progress`, `changes_requested` and
|
|
81
83
|
`blocked` tasks are picked up.
|
|
82
84
|
|
|
83
|
-
Only when `RUN.md` is absent or `Phase: done` does
|
|
85
|
+
Only when `RUN.md` is absent or `Phase: done` does a new request start a fresh cycle.
|
|
84
86
|
|
|
85
87
|
---
|
|
86
88
|
|
|
@@ -97,11 +99,11 @@ Only when `RUN.md` is absent or `Phase: done` does `$ARGUMENTS` start a fresh cy
|
|
|
97
99
|
|
|
98
100
|
Return a compact summary. Do NOT write any files yet.
|
|
99
101
|
|
|
100
|
-
>
|
|
102
|
+
> **For the human operator, on a tool with no agent support (Codex, OpenCode) — not an instruction to the model:** manually switch to the lite model and run P1 yourself.
|
|
101
103
|
|
|
102
104
|
### P2 — Write PLAN.md + task files (strong model)
|
|
103
105
|
|
|
104
|
-
**Claude Code — MANDATORY, do this before anything else in P2:** call the Agent tool with `subagent_type: "handoff-planner"` (omp: the `task` tool with `agent: "handoff-planner"`), passing it the P1 summary and
|
|
106
|
+
**Claude Code — MANDATORY, do this before anything else in P2:** call the Agent tool with `subagent_type: "handoff-planner"` (omp: the `task` tool with `agent: "handoff-planner"`), passing it the P1 summary and the **Problem / feature** section above. Do NOT write PLAN.md or task files yourself in the current session — this step is contracted to the strong tier (opus/unic-smart), which only the spawned agent's frontmatter model guarantees.
|
|
105
107
|
|
|
106
108
|
The planner agent does the following (use P1 summary — do NOT re-read files):
|
|
107
109
|
|
|
@@ -168,7 +170,7 @@ is written. What it no longer does is hand a stalled plan back to a human who is
|
|
|
168
170
|
2. `Issues Found` → route back to P2: `handoff-planner` revises `PLAN.md` and the affected `TASK-xxx.md` files to address every finding, then re-submit for one more P2.5 review round — subject to the loop cap above.
|
|
169
171
|
3. `Approved` → append `PLAN_REVIEW: Approved by <reviewer model>` to PLAN.md's `## Planner Report` footer, then proceed to P3.
|
|
170
172
|
|
|
171
|
-
>
|
|
173
|
+
> **For the human operator, on a tool with no agent support (Codex, OpenCode) — not an instruction to the model:** manually switch to the strong model in a **separate** chat/session from P2, paste PLAN.md, review using the Spec/Plan Review checklist in `.claude/agents/code-reviewer.md`.
|
|
172
174
|
|
|
173
175
|
### P3 — Commit the plan (lite model)
|
|
174
176
|
|
|
@@ -179,7 +181,7 @@ git add docs/AI_HANDOFF/ && git commit -m "handoff: plan — <goal>"
|
|
|
179
181
|
|
|
180
182
|
Replace `<goal>` with the one-sentence goal from ACTIVE.md. This locks the plan in git before any implementation begins.
|
|
181
183
|
|
|
182
|
-
>
|
|
184
|
+
> **For the human operator, on a tool with no agent support (Codex, OpenCode) — not an instruction to the model:** manually switch to the lite model for P2/P3.
|
|
183
185
|
|
|
184
186
|
---
|
|
185
187
|
|
|
@@ -58,7 +58,7 @@ If this file already exists with `Phase:` not `done` when the command starts, th
|
|
|
58
58
|
## Step 1 — Setup
|
|
59
59
|
|
|
60
60
|
Read `docs/AI_HANDOFF/ACTIVE.md` → get `Base: <BASE>`.
|
|
61
|
-
Read `docs/AI_HANDOFF/INDEX.md` → collect `ready` tasks (or specific task
|
|
61
|
+
Read `docs/AI_HANDOFF/INDEX.md` → collect `ready` tasks (or the specific task named in the request above).
|
|
62
62
|
If there are no `ready` tasks, check for `changes_requested`/`blocked` ones and run those
|
|
63
63
|
instead. Only if nothing is actionable → report and stop.
|
|
64
64
|
|
|
@@ -163,7 +163,7 @@ disk in the task file, which is where the reviewer reads them from. Pasting them
|
|
|
163
163
|
second time is what blows up the orchestrator's context window and kills the run mid-wave.
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
>
|
|
166
|
+
> **For the human operator, on a tool with no agent support (Codex, OpenCode) — not an instruction to the model:** open each task in a separate session with the code model.
|
|
167
167
|
|
|
168
168
|
### 3c — Orchestrator: copy changes to main + IMMEDIATELY delete worktree
|
|
169
169
|
|
|
@@ -188,4 +188,4 @@ This is the only place this command may ask for a compaction. All state lives in
|
|
|
188
188
|
`INDEX.md` and `RUN.md`, so a compacted or fresh session resumes with nothing lost.
|
|
189
189
|
|
|
190
190
|
> Orchestrator (this session) handles Step 1, 2e, and 3 directly — those are not delegated.
|
|
191
|
-
>
|
|
191
|
+
> **For the human operator, on a tool with no agent support (Codex, OpenCode) — not an instruction to the model:** manually switch to the strong model, run 2a–2d per task (one session at a time).
|
|
@@ -45,5 +45,5 @@ Next action:
|
|
|
45
45
|
no active cycle → /ukit:handoff-create <description>
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
> Claude Code: spawn `ukit-small-task-maintainer` (haiku) with the above prompt.
|
|
48
|
+
> Claude Code: spawn `ukit-small-task-maintainer` (haiku) with the above prompt. omp: the `task` tool with `agent: "ukit-small-task-maintainer"`.
|
|
49
49
|
> Other tools: use lite model, run the reads above, format the report.
|
|
@@ -13,10 +13,13 @@
|
|
|
13
13
|
* 1. process.env.ANTHROPIC_BASE_URL -> 'env'
|
|
14
14
|
* 2. project .claude/settings.json -> env.ANTHROPIC_BASE_URL -> 'claude-settings'
|
|
15
15
|
* 3. ~/.claude/settings.json -> env.ANTHROPIC_BASE_URL -> 'claude-settings'
|
|
16
|
-
* 4. process.env.OMP_BASE_URL (TASK-004, name unverified) -> 'omp-env'
|
|
17
|
-
* 5. project .omp/config.yml -> baseUrl (TASK-004, key unverified) -> 'omp-config'
|
|
18
16
|
*
|
|
19
|
-
*
|
|
17
|
+
* omp needs no probe of its own: verified against omp v17.4.2, it reads `ANTHROPIC_BASE_URL`
|
|
18
|
+
* for the anthropic provider, so probe 1 covers an omp session for the same reason it covers a
|
|
19
|
+
* Claude Code one. See the note above the probe list below for the two guessed omp probes this
|
|
20
|
+
* replaced, and why they could never have fired.
|
|
21
|
+
*
|
|
22
|
+
* Every probe here is scoped to what changes the CALLING
|
|
20
23
|
* runtime's OWN outbound endpoint — same rule that already governs probes 1-3. Cross-tool
|
|
21
24
|
* configs are NOT probed. This module is only ever invoked from Claude Code / omp hooks
|
|
22
25
|
* (vision-router.sh, vision-gate.sh, route-task.mjs, and the omp bridge) to gate what THIS
|
|
@@ -51,21 +54,23 @@ import { fileURLToPath } from 'node:url';
|
|
|
51
54
|
const UNIC_TOKEN = 'unicjsc.com';
|
|
52
55
|
const VISION_MODEL_ALIAS = 'unic-vision';
|
|
53
56
|
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
//
|
|
60
|
-
//
|
|
61
|
-
//
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
//
|
|
65
|
-
//
|
|
66
|
-
//
|
|
67
|
-
//
|
|
68
|
-
|
|
57
|
+
// RESOLVED 2026-08-22 against a real omp v17.4.2 install -- both omp-specific probes that
|
|
58
|
+
// shipped in 2.2.1 were guesses, and both were wrong:
|
|
59
|
+
//
|
|
60
|
+
// * `OMP_BASE_URL` does not exist in omp. Its bundled provider resolver reads
|
|
61
|
+
// `ANTHROPIC_BASE_URL` for the anthropic provider, falling back to
|
|
62
|
+
// "https://api.anthropic.com" -- i.e. the exact variable probe 1 already reads.
|
|
63
|
+
// * `.omp/config.yml` has no `baseUrl` key at any level. `omp config get baseUrl` answers
|
|
64
|
+
// "Unknown setting", and omp's settings schema declares none.
|
|
65
|
+
//
|
|
66
|
+
// So omp needs no probe of its own: an omp session pointed at the UNIC gateway is detected by
|
|
67
|
+
// probe 1, on the same variable and for the same reason as a Claude Code session. That is what
|
|
68
|
+
// makes the rule stated in CLAUDE.md/AGENTS.md ("routing is decided ONLY by ANTHROPIC_BASE_URL")
|
|
69
|
+
// literally true on omp rather than an approximation of it. Both dead probes are removed rather
|
|
70
|
+
// than left in place returning a permanent false -- a probe that can never fire is worse than no
|
|
71
|
+
// probe, because it reads as coverage. Custom per-model `baseUrl` values do exist in omp, but
|
|
72
|
+
// they live in its models config, not in `.omp/config.yml`; if that ever needs probing it is a
|
|
73
|
+
// new probe against a verified path, not a revival of these.
|
|
69
74
|
|
|
70
75
|
function safeReadFile(filePath) {
|
|
71
76
|
try {
|
|
@@ -115,12 +120,6 @@ function probeClaudeSettings(filePath) {
|
|
|
115
120
|
|
|
116
121
|
// Narrow anchored regex probe (no YAML parsing) for the omp config file's `baseUrl` key. A
|
|
117
122
|
// missing file, unreadable path, or malformed YAML all degrade to "no hit" -- never throws.
|
|
118
|
-
function probeOmpConfig(filePath) {
|
|
119
|
-
const raw = safeReadFile(filePath);
|
|
120
|
-
if (raw == null) return false;
|
|
121
|
-
return OMP_CONFIG_BASE_URL_UNIC_RE.test(raw);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
123
|
/**
|
|
125
124
|
* Checks whether the Codex model catalog exists and, if so, whether it lists `unic-vision`.
|
|
126
125
|
* A missing/unreadable/malformed catalog is never an error — it degrades to "unknown" and the
|
|
@@ -163,8 +162,6 @@ export function detectUnicGateway(options = {}) {
|
|
|
163
162
|
() => recordHit(probeEnvVar('ANTHROPIC_BASE_URL'), 'env'),
|
|
164
163
|
() => recordHit(probeClaudeSettings(path.join(rootDir, '.claude', 'settings.json')), 'claude-settings'),
|
|
165
164
|
() => recordHit(probeClaudeSettings(path.join(homeDir, '.claude', 'settings.json')), 'claude-settings'),
|
|
166
|
-
() => recordHit(probeEnvVar(OMP_BASE_URL_ENV_VAR), 'omp-env'),
|
|
167
|
-
() => recordHit(probeOmpConfig(path.join(rootDir, '.omp', 'config.yml')), 'omp-config'),
|
|
168
165
|
];
|
|
169
166
|
for (const probe of probes) {
|
|
170
167
|
try {
|
package/templates/.omp/RULES.md
CHANGED
|
@@ -1,34 +1,62 @@
|
|
|
1
1
|
# .omp/RULES.md — sticky always-apply rules
|
|
2
2
|
|
|
3
3
|
omp re-attaches this file near every turn from its native location (`.omp/RULES.md` only, never a
|
|
4
|
-
copy elsewhere). It carries the always-apply subset of root `
|
|
5
|
-
|
|
6
|
-
`CLAUDE.md`. Keep this short: every line here is a per-turn tax.
|
|
4
|
+
copy elsewhere). It carries the always-apply subset of root `AGENTS.md` that must survive even when
|
|
5
|
+
nothing else is loaded. Keep this short: every line here is a per-turn tax.
|
|
7
6
|
|
|
8
|
-
## 1.
|
|
7
|
+
## 1. Classify first, then act
|
|
8
|
+
|
|
9
|
+
- **Trivial** (typo, rename, flag, obvious config) — act directly. No doc reads, no index, no agents.
|
|
10
|
+
- **Simple** (1-2 files, existing pattern) — act directly, pull the smallest useful context.
|
|
11
|
+
- **Non-trivial / risky** (auth, migration, shared runtime, data-loss, flaky) — index-first, then
|
|
12
|
+
activate the matching skill, then verify.
|
|
13
|
+
|
|
14
|
+
Pick the lane before the first tool call. Skipping this is what turns a direct chat into a
|
|
15
|
+
scattershot one.
|
|
16
|
+
|
|
17
|
+
## 2. Execution Contract
|
|
9
18
|
|
|
10
19
|
For implement/apply/fix requests, continue until the actual edit is made or a real blocker is found.
|
|
11
20
|
Do not stop after a read-only inspection step (read/grep/glob/search).
|
|
12
21
|
|
|
13
|
-
##
|
|
22
|
+
## 3. No "done" after read-only
|
|
14
23
|
|
|
15
24
|
Never say "done", "applied", or "fixed" after a read-only step. Completion wording requires concrete
|
|
16
25
|
edit/write evidence in the current turn, plus verification when the change is risky.
|
|
17
26
|
|
|
18
|
-
##
|
|
27
|
+
## 4. Index-first loop
|
|
19
28
|
|
|
20
29
|
Check `.cache/index/` freshness first. Then run
|
|
21
30
|
`node .claude/ukit/index/query-index.mjs "<error|symbol|path>"` and open only the top 1-3 suspect
|
|
22
31
|
files before widening further. These node scripts work unchanged under omp.
|
|
23
32
|
|
|
24
|
-
##
|
|
33
|
+
## 5. Auto-activate skills
|
|
34
|
+
|
|
35
|
+
Skills live in `.claude/skills/` and omp reads them through its `claude` discovery provider — no
|
|
36
|
+
mirror under `.omp/`. On any non-trivial task, and again after the first tool calls reveal what the
|
|
37
|
+
work really is, read the matching `SKILL.md` without being asked. Users never name skills.
|
|
38
|
+
|
|
39
|
+
## 6. Delegate to bind a model tier
|
|
40
|
+
|
|
41
|
+
Your own model does not change mid-turn. A tier only applies when work is handed to a task-agent in
|
|
42
|
+
`.omp/agents/`, whose `model:` field (`@lite` / `@code` / `@smart` / `@vision`) resolves through
|
|
43
|
+
`modelRoles` in `.omp/config.yml`.
|
|
44
|
+
|
|
45
|
+
- `tiny-fix` → `@lite` · `local-fix`, `local-build`, `shared-edit`, `find-cause`, `map-impact` →
|
|
46
|
+
`@code` · `review-release` → `@smart`
|
|
47
|
+
- Images: `@vision` only. `@code`/`@smart` cannot see images on the UNIC gateway and must never
|
|
48
|
+
guess at their contents — hand every image to `ukit-vision-analyst` first.
|
|
49
|
+
|
|
50
|
+
Doing everything inline is exactly what makes UKit look like it only has one model. Keep direct
|
|
51
|
+
execution for trivial/simple work; delegate when the tier differs or when a noisy lane would other-
|
|
52
|
+
wise flood this context.
|
|
53
|
+
|
|
54
|
+
## 7. Safe Patch
|
|
25
55
|
|
|
26
56
|
Prefer unique current-file anchors over line numbers or stale pasted blocks. Never silently merge a
|
|
27
57
|
stale spec — re-read current source and confirm before applying. Preserve existing BOM and line
|
|
28
58
|
endings.
|
|
29
59
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
only the three cost-tier values — `lite`, `code`, `smart` — never `vision`, which stays `unic-vision`
|
|
34
|
-
because it is a capability lane, not a cost tier.
|
|
60
|
+
> Maintainer note, not a per-turn rule: `modelRoles` in `.omp/config.yml` ships UNIC gateway names.
|
|
61
|
+
> On a non-UNIC provider, edit only the three cost tiers — `lite`, `code`, `smart` — never `vision`,
|
|
62
|
+
> which stays `unic-vision` because it is a capability lane, not a cost tier.
|
|
@@ -79,10 +79,12 @@ memory:
|
|
|
79
79
|
# Auto-compact must trigger BEFORE context-hardcap-gate.sh starts blocking tool
|
|
80
80
|
# calls (compact.hardCapTokens, default 220000). Mirrors the Claude Code value
|
|
81
81
|
# env.CLAUDE_CODE_AUTO_COMPACT_WINDOW = 180000 in templates/.claude/settings.json.
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
compact
|
|
88
|
-
|
|
82
|
+
#
|
|
83
|
+
# Key VERIFIED against omp v17.4.2 (2026-08-22): `compaction.thresholdTokens` is a
|
|
84
|
+
# fixed token limit for context maintenance and overrides the percentage threshold
|
|
85
|
+
# when set; omp's own default is -1 ("use compaction.thresholdPercent"). The key this
|
|
86
|
+
# file shipped with in 2.2.1 — `compact.autoCompactWindow` — was a plan-time guess and
|
|
87
|
+
# omp rejects it outright (`omp config get compact.autoCompactWindow` → "Unknown
|
|
88
|
+
# setting"), so auto-compact never moved off omp's default. See PLAN.md §3 D13.
|
|
89
|
+
compaction:
|
|
90
|
+
thresholdTokens: 180000
|
|
@@ -13,11 +13,14 @@
|
|
|
13
13
|
// 3. Executes each script via `pi.exec()` (never spawns/copies the script
|
|
14
14
|
// body) and translates the exit code back into an omp-shaped result.
|
|
15
15
|
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
//
|
|
16
|
+
// Event NAMES are verified against omp v17.4.2 (2026-08-22): its extension API
|
|
17
|
+
// registers `tool_call`, `tool_result`, `turn_start`, `session_start`,
|
|
18
|
+
// `session.compacting` and `session_compact` exactly as spelled below.
|
|
19
|
+
//
|
|
20
|
+
// `pi.exec`'s argument shape is still unverified — the contract chosen below (see
|
|
21
|
+
// the doc comments on each exported function) is internally consistent and is
|
|
22
|
+
// exercised end-to-end against a fake `pi` in tests/hooks/ompHookBridge.test.js,
|
|
23
|
+
// but nothing here has observed omp actually invoking it.
|
|
21
24
|
|
|
22
25
|
import path from 'node:path';
|
|
23
26
|
|
|
@@ -307,11 +310,13 @@ export async function runSessionCompacting(pi, event, { projectRoot }) {
|
|
|
307
310
|
return runScriptChain(pi, HOOK_EVENT_MAP['session.compacting'], payload, { projectRoot });
|
|
308
311
|
}
|
|
309
312
|
|
|
310
|
-
//
|
|
311
|
-
//
|
|
312
|
-
//
|
|
313
|
-
//
|
|
314
|
-
// handoff
|
|
313
|
+
// Claude Code's `SessionStart` entry in settings.json carries NO matcher, so it
|
|
314
|
+
// fires on every source including `compact`. Reaching that same behaviour on omp
|
|
315
|
+
// takes two events, not one -- see runSessionCompact below.
|
|
316
|
+
//
|
|
317
|
+
// handoff-resume.sh is idempotent by design (reads + prints the
|
|
318
|
+
// docs/AI_HANDOFF/RUN.md cursor, never advances state), so running this chain
|
|
319
|
+
// more than once in a session is safe (PLAN.md D11).
|
|
315
320
|
export async function runSessionStart(pi, event, { projectRoot }) {
|
|
316
321
|
const payload = buildHookPayload('SessionStart', {
|
|
317
322
|
sessionId: event.sessionId,
|
|
@@ -320,6 +325,32 @@ export async function runSessionStart(pi, event, { projectRoot }) {
|
|
|
320
325
|
return runScriptChain(pi, HOOK_EVENT_MAP.session_start, payload, { projectRoot });
|
|
321
326
|
}
|
|
322
327
|
|
|
328
|
+
// RESOLVED 2026-08-22 against a real omp v17.4.2 install. PLAN.md D11 carried this
|
|
329
|
+
// as a `TODO(verify)`: "does omp emit `session_start` on a post-compact
|
|
330
|
+
// continuation?" It does not -- and it does not need to, because omp exposes a
|
|
331
|
+
// dedicated post-compaction event instead. Its extension API registers
|
|
332
|
+
// `session_before_compact` -> `session.compacting` -> `session_compact`, the last
|
|
333
|
+
// firing after compaction settles and carrying the resulting `compactionEntry`.
|
|
334
|
+
//
|
|
335
|
+
// Without this handler the omp side lost the whole post-compact chain: the run
|
|
336
|
+
// cursor stayed un-surfaced, compact pressure was never reset, and a mid-cycle
|
|
337
|
+
// handoff silently failed to resume after a compaction -- the exact failure the
|
|
338
|
+
// plan named. Mapping `session_compact` onto the SAME script chain restores
|
|
339
|
+
// parity with Claude Code's matcher-less SessionStart.
|
|
340
|
+
//
|
|
341
|
+
// The payload keeps `hook_event_name: 'SessionStart'` deliberately: the scripts
|
|
342
|
+
// are shared with Claude Code and know that name, and Claude Code reaches them by
|
|
343
|
+
// the same event with `source: "compact"`. Inventing an omp-only event name here
|
|
344
|
+
// would mean forking the scripts, which is what this bridge exists to avoid.
|
|
345
|
+
export async function runSessionCompact(pi, event, { projectRoot }) {
|
|
346
|
+
const payload = buildHookPayload('SessionStart', {
|
|
347
|
+
sessionId: event.sessionId,
|
|
348
|
+
cwd: event.cwd,
|
|
349
|
+
source: 'compact',
|
|
350
|
+
});
|
|
351
|
+
return runScriptChain(pi, HOOK_EVENT_MAP.session_start, payload, { projectRoot });
|
|
352
|
+
}
|
|
353
|
+
|
|
323
354
|
// ---------------------------------------------------------------------------
|
|
324
355
|
// Default export -- omp hook factory contract: `export default function
|
|
325
356
|
// hook(pi) { pi.on(event, handler) }`.
|
|
@@ -333,4 +364,5 @@ export default function hook(pi) {
|
|
|
333
364
|
pi.on('turn_start', (event) => runTurnStart(pi, event, { projectRoot }));
|
|
334
365
|
pi.on('session.compacting', (event) => runSessionCompacting(pi, event, { projectRoot }));
|
|
335
366
|
pi.on('session_start', (event) => runSessionStart(pi, event, { projectRoot }));
|
|
367
|
+
pi.on('session_compact', (event) => runSessionCompact(pi, event, { projectRoot }));
|
|
336
368
|
}
|
package/templates/AGENTS.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# AGENTS.md — {{project.name}}
|
|
2
2
|
|
|
3
|
-
## Core
|
|
3
|
+
## Core Rule
|
|
4
4
|
|
|
5
|
-
- Human-facing workflow should
|
|
6
|
-
- After install,
|
|
7
|
-
- **Quality first, then speed, then token discipline
|
|
5
|
+
- Human-facing UKit workflow should collapse to one remembered command: `ukit install`.
|
|
6
|
+
- After install, default to natural-language work inside **Claude Code / Codex / OpenCode / omp**.
|
|
7
|
+
- **Quality first, then speed, then token discipline.**
|
|
8
8
|
- **Never stop after read-only steps.** For implement/apply/fix requests, continue to actual Edit/Write and verification in the same turn.
|
|
9
9
|
|
|
10
|
-
## Fast
|
|
10
|
+
## Fast Classification
|
|
11
11
|
|
|
12
|
-
- **Trivial** — typo, label, rename
|
|
13
|
-
- Act directly. No doc reads. No planning. No index.
|
|
12
|
+
- **Trivial** — typo, label, small rename, spacing, toggle flag, obvious config change.
|
|
13
|
+
- Act directly. No doc reads. No planning. No index. No agents.
|
|
14
14
|
- **Simple** — 1-2 files, clear scope, existing pattern.
|
|
15
15
|
- Handle directly. Pull only the smallest useful context via resolver or targeted read.
|
|
16
16
|
- **Non-trivial / Risky** — auth, security, migration, uninstall, shared runtime, race/flaky, data-loss.
|
|
@@ -44,11 +44,14 @@ For clearly non-code specialist lanes (docs-only, status, task queue), skip the
|
|
|
44
44
|
## Automatic Skill Activation (mandatory)
|
|
45
45
|
|
|
46
46
|
- End users should not need to know skill names.
|
|
47
|
-
-
|
|
47
|
+
- On every non-trivial task — and again after the first relevant tool calls — inspect installed project-local skills and **auto-activate the matching skill immediately**.
|
|
48
48
|
- Match from both prompt wording and tool/file evidence.
|
|
49
49
|
- Use the smallest effective set, usually 1-2 skills.
|
|
50
50
|
- If evidence becomes more specific than the original prompt, upgrade the active skill choice immediately.
|
|
51
|
-
-
|
|
51
|
+
- If docs work is detected, read `.claude/skills/docs-quality/SKILL.md` when present.
|
|
52
|
+
- Prefer routed context and routed verification over ad-hoc broad reading.
|
|
53
|
+
- Reuse `.claude/ukit/skill-router-state.json` when it already carries compact route memory.
|
|
54
|
+
- If shared route state already includes `previous-context` or `recent-output`, reuse those first.
|
|
52
55
|
|
|
53
56
|
### Common skill triggers
|
|
54
57
|
|
|
@@ -61,51 +64,65 @@ For clearly non-code specialist lanes (docs-only, status, task queue), skip the
|
|
|
61
64
|
- auth / security / token / permission / validation / risky shell-path-delete-db work → `.claude/skills/discover-security/SKILL.md`
|
|
62
65
|
- stale workspace / reinstall / cleanup / maintenance → `.claude/skills/repo-maintenance/SKILL.md`
|
|
63
66
|
|
|
64
|
-
## Internal Helper
|
|
67
|
+
## Internal Helper Policy
|
|
65
68
|
|
|
66
|
-
-
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
69
|
+
- Prefer `node .claude/ukit/index/route-task.mjs "<prompt>" [--tool-command <cmd>] [--target <file>]` when routing is complex or ambiguous.
|
|
70
|
+
- Prefer `node .claude/ukit/index/resolve-context.mjs ...` for indexed related-file context.
|
|
71
|
+
- Prefer `node .claude/ukit/index/verify-context.mjs ...` for concrete verification lanes.
|
|
72
|
+
- **Do not ask normal contributors to run internal helper commands**; run them yourself or tell them to rerun `ukit install`.
|
|
73
|
+
- Do not ask normal contributors to memorize `ukit doctor`, `ukit diff`, `ukit uninstall`, or `ukit index ...` unless they explicitly need maintainer/debug help.
|
|
74
|
+
- If the workspace needs a refresh, prefer telling them to rerun `ukit install`.
|
|
75
|
+
|
|
76
|
+
## Skill Quality (maintainer-only)
|
|
77
|
+
|
|
78
|
+
- When editing a template skill/agent under `templates/.claude/`, read `.claude/skills/skill-quality/SKILL.md` before shipping the change.
|
|
70
79
|
|
|
71
|
-
## UKit
|
|
80
|
+
## UKit v{{ukit.version}} Shared Runtime
|
|
72
81
|
|
|
73
82
|
- Shared runtime state lives in `.ukit/storage/`.
|
|
74
83
|
- Treat `.ukit/storage/config.json` as the source of runtime toggles for compact, token pipeline, router, memory, validation, and Safe Patch behavior.
|
|
75
|
-
- Reuse `.ukit/storage/memory/` before asking users to restate
|
|
84
|
+
- Reuse `.ukit/storage/memory/` before asking users to restate decisions.
|
|
76
85
|
- For non-trivial work, prefer `ukit memory recall "<current task>"` before widening doc reads.
|
|
77
|
-
- Reusable
|
|
86
|
+
- Reusable cache/compact/output state lives in `.ukit/storage/cache/prompt-cache.json`, `.ukit/storage/cache/compact-history.json`, `.ukit/storage/cache/compact-pressure.json`, `.ukit/storage/cache/output-history.json`, and preserved raw tool outputs under `.ukit/storage/cache/tee/`.
|
|
78
87
|
- Shared route memory lives in `.claude/ukit/skill-router-state.json`.
|
|
79
|
-
- If shared route state already includes compact `previous-context` or `recent-output
|
|
88
|
+
- If shared route state already includes compact `previous-context` or `recent-output`, reuse those first.
|
|
80
89
|
- If an older repo still has a visible `ukit/` runtime root, rerun `ukit install`; UKit should migrate the shared runtime into hidden `.ukit/` when safe.
|
|
81
90
|
- Maintainers can inspect runtime state with `ukit status` and `ukit memory export`, but normal teammates should still only need `ukit install`.
|
|
82
|
-
- If runtime files are missing
|
|
91
|
+
- If runtime files are missing or corrupt, tell maintainers to rerun `ukit install`.
|
|
83
92
|
- Threshold-based compact pressure is internal orchestration; do not expose it to users.
|
|
84
93
|
- For Codex Desktop long sessions, UKit can use soft auto-compact handoffs. Default `compact.codexContext.compactTarget=150` means about 150 compact handoff lines (120-150 preferred, hard max 170), not 150 tokens.
|
|
85
94
|
|
|
86
|
-
##
|
|
95
|
+
## Safe Patch Protocol
|
|
96
|
+
|
|
97
|
+
- Safe Patch is internal orchestration: normal users still only need `ukit install` and natural language.
|
|
98
|
+
- For risky/shared/large edits, prefer unique current-file anchors over line numbers or stale pasted blocks.
|
|
99
|
+
- Do not silently merge stale specs: if `old_string` is missing or ambiguous, re-read current source and ask whether to apply as-is, adapt, or skip.
|
|
100
|
+
- Preserve UTF-8 BOM/no-BOM and LF/CRLF for existing multilingual/user-authored files.
|
|
101
|
+
- Use `node .claude/ukit/index/safe-patch.mjs` internally when normal Edit/Write may normalize bytes or when anchor-based matching is needed.
|
|
87
102
|
|
|
88
|
-
|
|
103
|
+
## Handoff Quality Gate — OPT-IN
|
|
89
104
|
|
|
90
|
-
|
|
105
|
+
CHỈ kích hoạt khi task đi qua `docs/AI_HANDOFF/` (user nói "execute task TASK-xxx" hoặc target là `docs/AI_HANDOFF/tasks/*.md`). Daily prompt → KHÔNG đụng, flow cũ giữ nguyên.
|
|
91
106
|
|
|
107
|
+
Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+Plan → Create Tasks → Implement+Test → Review+Test) + state machine + comment thread + self-report model. Config: `.ukit/storage/config.json` → `handoff.*`.
|
|
92
108
|
|
|
93
109
|
## Context + Verification Budget
|
|
94
110
|
|
|
95
|
-
- **Trivial**: no docs, no index query unless the file target is unclear.
|
|
96
|
-
- **Simple**:
|
|
97
|
-
- **Non-trivial**:
|
|
98
|
-
- `docs/STATUS.md`:
|
|
99
|
-
- `docs/TASKS.md`:
|
|
100
|
-
- `docs/WORKLOG.md`: only recent
|
|
101
|
-
- Follow routed verification policy: targeted first
|
|
111
|
+
- **Trivial**: no docs, and no index query unless the file target is unclear.
|
|
112
|
+
- **Simple**: `docs/MEMORY.md` only, plus resolver-selected files/tests.
|
|
113
|
+
- **Non-trivial**: `docs/MEMORY.md` + `docs/PROJECT.md` + `docs/CODE_MAP.md`.
|
|
114
|
+
- `docs/STATUS.md`: use for open-ended status/continue prompts or meaningful continuation context; stale status is orientation only.
|
|
115
|
+
- `docs/TASKS.md`: use only for queued-task prompts or when status points at queued work; safely clean exact duplicates/completed overflow by default without deleting unfinished human-authored tasks.
|
|
116
|
+
- `docs/WORKLOG.md`: only recent relevant entries. Follow the Budget Rules at the top of the file; archive oldest entries to `docs/WORKLOG_ARCHIVE.md` when over limits.
|
|
117
|
+
- Follow routed verification policy: targeted first, widen only when risk/shared scope justifies it, ask before blanket broad runs.
|
|
102
118
|
|
|
103
119
|
## Living Status Workflow
|
|
104
120
|
|
|
105
|
-
- `docs/STATUS.md`
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
-
|
|
121
|
+
- `docs/STATUS.md` captures compact current state, active work, debug threads, blockers, verification, and next candidates.
|
|
122
|
+
- It is not source truth and must not replace source/index-first investigation.
|
|
123
|
+
- For "what next?" / "continue" prompts without a concrete target, use `next-step` and show a freshness cue before relying on the status file.
|
|
124
|
+
- For concrete debug/implementation/review prompts, keep the concrete workflow primary even if the user asks for an approach or next step.
|
|
125
|
+
- After meaningful work, use `update-status`; skip trivial/no-state-change tasks and avoid transcript-style noise.
|
|
109
126
|
- `docs/TASKS.md` is a local AI task queue: prefer `Ready for AI` when asked to pick queued work, and clean duplicates/prune `Done Recently` safely when reading/updating it.
|
|
110
127
|
|
|
111
128
|
## Small-Task Maintainer (internal)
|
|
@@ -117,36 +134,78 @@ In Handoff mode: read `docs/AI_HANDOFF/RULES.md` for the 4-phase spec (Idea+Plan
|
|
|
117
134
|
- This is optional internal orchestration config from `.ukit/storage/config.json`; never turn it into an end-user workflow.
|
|
118
135
|
- Always preserve the CoDev priority: quality > safety > speed > token discipline.
|
|
119
136
|
|
|
120
|
-
##
|
|
137
|
+
## Post-Edit Sidecar Review (internal)
|
|
121
138
|
|
|
122
|
-
-
|
|
123
|
-
-
|
|
139
|
+
- If routed state's `routeSummary.line` includes a `review=code-reviewer(diff)` segment, a `local-build` or `shared-edit` task qualifies for a non-blocking second opinion — this exists because the daily-flow executor model can miss edge cases.
|
|
140
|
+
- Only launch it once write evidence AND verification evidence already exist for the task (never before; never as a substitute for either).
|
|
141
|
+
- Launch the `code-reviewer` agent (see the harness table under 3-Tier Model Routing) with `REVIEW_TARGET_TYPE=diff`, in the background, on the `smart` tier per `subagents.diffReviewModel`. Do not wait for it — continue and report the task as done using the normal completion rules.
|
|
142
|
+
- Its findings are advisory only: never re-open, block, or delay the already-reported completion on their account. Surface them to the user as a follow-up note if/when they arrive.
|
|
143
|
+
- This is internal orchestration — end users never invoke it directly; `ukit install` plus natural language remains the whole surface. No new commands.
|
|
144
|
+
|
|
145
|
+
## Selective Subagent Policy (internal only)
|
|
146
|
+
|
|
147
|
+
- Keep direct execution as the default for trivial/simple work.
|
|
148
|
+
- Delegate only when it meaningfully shrinks context or enables useful parallel progress.
|
|
124
149
|
- Good delegation triggers:
|
|
125
150
|
- noisy side lanes (broad logs/search/test output)
|
|
126
151
|
- 3+ independent failures/files/checks
|
|
127
152
|
- explicit batch/plan execution
|
|
128
153
|
- broad implementation/debug lanes that can return a concise summary
|
|
129
|
-
- If route memory
|
|
154
|
+
- If route memory includes `delegate=<lane>`, treat it as an internal hint after any required indexed-context step.
|
|
130
155
|
- Do not ask end users to name agents or remember agent commands.
|
|
131
156
|
|
|
132
|
-
##
|
|
157
|
+
## Adaptive Autonomy
|
|
133
158
|
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
- Do not silently merge stale specs: if `old_string` is missing or ambiguous, re-read current source and ask whether to apply as-is, adapt, or skip.
|
|
137
|
-
- Preserve UTF-8 BOM/no-BOM and LF/CRLF for existing multilingual/user-authored files.
|
|
138
|
-
- Use `node .claude/ukit/index/safe-patch.mjs` internally when normal Edit/Write may normalize bytes or when anchor-based matching is needed.
|
|
159
|
+
- `autonomy.level` in `.ukit/storage/config.json` controls how much UKit acts without asking first: `conservative` (ask more), `balanced` (default), `free-run` (auto-run more).
|
|
160
|
+
- End users should not need to change this; maintainers may tune it per-project.
|
|
139
161
|
|
|
140
|
-
##
|
|
162
|
+
## 3-Tier Model Routing
|
|
141
163
|
|
|
142
|
-
|
|
143
|
-
- If the workspace needs a refresh, prefer telling them to rerun `ukit install`.
|
|
144
|
-
- Keep scope tight, prefer the smallest correct change set, reuse existing code, and update docs when source changes.
|
|
164
|
+
**Internal orchestration only — end users still just use natural language. No new commands.**
|
|
145
165
|
|
|
146
|
-
|
|
166
|
+
UKit routes tasks to one of three model tiers based on task complexity:
|
|
147
167
|
|
|
148
|
-
|
|
149
|
-
|
|
168
|
+
| Tier | Generic alias | Claude model | Typical tasks |
|
|
169
|
+
|------|--------------|--------------|---------------|
|
|
170
|
+
| lite | `unic-lite` | claude-haiku | Reads, git queries, bash summaries, small doc edits |
|
|
171
|
+
| code | `unic-code` | claude-sonnet | Normal coding, local fixes, shared edits, builds, debugging, impact mapping |
|
|
172
|
+
| smart | `unic-smart` | claude-opus | Release review/audit, and escalated deep reasoning after repeated failure |
|
|
173
|
+
|
|
174
|
+
### Contract-to-tier mapping
|
|
175
|
+
|
|
176
|
+
| Contract | Tier |
|
|
177
|
+
|----------|------|
|
|
178
|
+
| `tiny-fix` | lite |
|
|
179
|
+
| `local-fix`, `local-build`, `shared-edit`, `find-cause`, `map-impact` | code |
|
|
180
|
+
| `review-release` | smart |
|
|
181
|
+
|
|
182
|
+
### How a tier is actually bound
|
|
183
|
+
|
|
184
|
+
The main session model never changes mid-turn. A tier only takes effect when work is handed to
|
|
185
|
+
an agent whose own definition binds that model:
|
|
186
|
+
|
|
187
|
+
| Harness | Agent definitions | How to launch one |
|
|
188
|
+
|---------|-------------------|-------------------|
|
|
189
|
+
| Claude Code | `.claude/agents/*.md` (`model:` frontmatter) | Agent tool, `subagent_type: "<name>"` |
|
|
190
|
+
| omp | `.omp/agents/*.md` (`model: "@lite"` / `"@code"` / `"@smart"` / `"@vision"`, resolved through `modelRoles` in `.omp/config.yml`) | task-agent `<name>` |
|
|
191
|
+
|
|
192
|
+
When a task's contract maps to a tier other than the current session model, hand it to the
|
|
193
|
+
matching agent instead of doing it inline. Doing everything inline is exactly what makes UKit
|
|
194
|
+
behave as if it only had one model — the tier table above has no effect on its own.
|
|
195
|
+
|
|
196
|
+
### Escalation rule
|
|
197
|
+
|
|
198
|
+
When the same file or symbol fails `debugLoopThreshold` (default: 2) times in one session, UKit routes the next attempt one tier higher (capped at `smart`). Config: `orchestration.escalation` in `.ukit/storage/config.json`.
|
|
199
|
+
|
|
200
|
+
This is internal orchestration — end users do not need to know about tiers, thresholds, or escalation. The AI handles routing transparently.
|
|
201
|
+
|
|
202
|
+
### Vision lane (capability, not a cost tier)
|
|
203
|
+
|
|
204
|
+
`unic-vision` is a **capability lane**, not a fourth cost tier — it is orthogonal to lite/code/smart above and never appears as a row in the tier table. `unic-code` and `unic-smart` cannot read images on the UNIC gateway; they must never guess at image contents.
|
|
205
|
+
|
|
206
|
+
- **Gateway detection**: UNIC routing for a Claude Code session is decided ONLY by what changes Claude Code's own outbound endpoint — `ANTHROPIC_BASE_URL` (env var, or the `env.ANTHROPIC_BASE_URL` key in project/home `.claude/settings.json`) containing `unicjsc.com`. Other tools' configs — Codex `config.toml`, Kilo `secrets.json`, or an `OPENAI_BASE_URL` env var — describe a different tool's endpoint entirely and never decide this session's routing.
|
|
207
|
+
- **Enforcement**: every image (pasted, local file path, or URL) must be analysed by the `ukit-vision-analyst` agent running on the vision lane before any related edit happens. `Edit`/`Write` are **hard-blocked** until an analysis receipt exists for every pending image; `Read`/`Grep`/`Glob`/`Bash` stay unblocked so the analyst itself can see the image and write its receipt.
|
|
208
|
+
- This is internal orchestration — end users never invoke a vision command directly; `ukit install` plus natural language remains the whole surface. No new commands.
|
|
150
209
|
|
|
151
210
|
## Session Start — OpenCode
|
|
152
211
|
|
|
@@ -155,35 +214,43 @@ At the start of every OpenCode session, before working on the first task:
|
|
|
155
214
|
2. Note which skills are installed by scanning `.claude/skills/` (directory listing only); read the full SKILL.md only when a task triggers it.
|
|
156
215
|
3. For every non-trivial task: run `/ukit-route <task summary>` immediately to get skill + context hints **before** writing any code.
|
|
157
216
|
4. If the route result points to a skill, read that SKILL.md before acting — do not skip this step.
|
|
158
|
-
5. If `.ukit/storage/config.json` has `router.enabled: true`, prefer the router
|
|
159
|
-
|
|
160
|
-
## Environment Snapshot
|
|
161
|
-
|
|
162
|
-
- Project name: {{project.name}}
|
|
163
|
-
- Detected packs: {{project.stack}}
|
|
164
|
-
- Frontend detected: {{stack.frontend}}
|
|
165
|
-
- Backend API detected: {{stack.backendApi}}
|
|
166
|
-
- PostgreSQL detected: {{stack.postgres}}
|
|
167
|
-
- Package manager: {{runtime.packageManager}}
|
|
217
|
+
5. If `.ukit/storage/config.json` has `router.enabled: true`, prefer the router output over ad-hoc guessing.
|
|
168
218
|
|
|
169
219
|
## Skills
|
|
170
220
|
|
|
171
221
|
- Canonical skills live in `.claude/skills/`.
|
|
172
222
|
- Adapter mirrors may also exist, for example `.codex/skills/` → `.claude/skills/` (symlink). **omp** has no mirror: it reads `.claude/skills/` directly through its own `claude` discovery provider.
|
|
173
|
-
- **OpenCode**: reads `AGENTS.md` at session start only — it does NOT auto-load `.claude/skills/`. The model must explicitly read the triggered SKILL.md
|
|
223
|
+
- **OpenCode**: reads `AGENTS.md` at session start only — it does NOT auto-load `.claude/skills/`. The model must explicitly read the triggered SKILL.md.
|
|
174
224
|
- If `opencode.json` ships `ukit-*` commands, treat them as internal helper entrypoints only and **never ask end users to run them**; humans should still only need `ukit install`.
|
|
175
225
|
|
|
226
|
+
## Project Snapshot
|
|
227
|
+
|
|
228
|
+
- Project: {{project.name}} | Root: {{project.root}}
|
|
229
|
+
- Packs: {{project.stack}} | Frontend: {{stack.frontend}} | Backend API: {{stack.backendApi}} | PostgreSQL: {{stack.postgres}}
|
|
230
|
+
- Package manager: {{runtime.packageManager}} | OS: {{runtime.os}} | Node: {{runtime.nodeVersion}} | Provider: {{providers.unic}}
|
|
231
|
+
|
|
232
|
+
## Working Rules
|
|
233
|
+
|
|
234
|
+
- Keep scope tight, prefer the smallest correct change set, and reuse existing code.
|
|
235
|
+
- For explicit implement/apply/fix requests, keep working until the actual edit is made or a real blocker is found; do not stop after a read-only inspection step.
|
|
236
|
+
- If routed state still says `pull-indexed-context`, treat it as an internal continuation step, not a stopping point.
|
|
237
|
+
- If routed state shows `continuation required` or a stuck-lane rescue mode, finish the named milestone before widening reads or rephrasing the same partial status.
|
|
238
|
+
- Never claim "done", "applied", or "fixed" after Read/Grep/analysis alone. Completion language requires concrete Edit/Write evidence in the current turn, plus verification when the change is risky.
|
|
239
|
+
- Update `docs/WORKLOG.md` after significant work.
|
|
240
|
+
- If source contradicts docs, update docs immediately.
|
|
241
|
+
- Use `{{runtime.packageManager}}`.
|
|
242
|
+
|
|
176
243
|
## DuraOne Skill — Conditional Activation
|
|
177
244
|
|
|
178
245
|
DuraOne skill chỉ active khi pack `duraone` được cài hoặc `.claude/skills/duraone/SKILL.md` tồn tại.
|
|
179
246
|
|
|
180
|
-
- Khi active: đọc `.claude/skills/duraone/SKILL.md` trước khi code.
|
|
247
|
+
- Khi active: luôn đọc `.claude/skills/duraone/SKILL.md` trước khi code.
|
|
181
248
|
- References:
|
|
182
249
|
- `.claude/skills/duraone/references/frontend.md`
|
|
183
250
|
- `.claude/skills/duraone/references/backend.md`
|
|
184
251
|
- `.claude/skills/duraone/references/sql.md`
|
|
185
252
|
- `.claude/skills/duraone/references/workflow.md`
|
|
186
|
-
- Khi không active: dùng generic coding standards + project patterns từ index.
|
|
253
|
+
- Khi không active: dùng generic coding standards + project-specific patterns từ index.
|
|
187
254
|
|
|
188
255
|
## Completion Checklist
|
|
189
256
|
|
|
@@ -191,3 +258,4 @@ DuraOne skill chỉ active khi pack `duraone` được cài hoặc `.claude/skil
|
|
|
191
258
|
- No unrelated changes
|
|
192
259
|
- Verification executed and reported
|
|
193
260
|
- Docs updated when source truth changed
|
|
261
|
+
{{codegraphSection}}
|
package/templates/CLAUDE.md
CHANGED
|
@@ -3,15 +3,19 @@
|
|
|
3
3
|
## Core Rule
|
|
4
4
|
|
|
5
5
|
- Human-facing UKit workflow should collapse to one remembered command: `ukit install`.
|
|
6
|
-
- After install, default to natural-language work inside Claude/Codex
|
|
6
|
+
- After install, default to natural-language work inside **Claude Code / Codex / OpenCode / omp**.
|
|
7
7
|
- **Quality first, then speed, then token discipline.**
|
|
8
8
|
- **Never stop after read-only steps.** For implement/apply/fix requests, continue to actual Edit/Write and verification in the same turn.
|
|
9
9
|
|
|
10
10
|
## Fast Classification
|
|
11
11
|
|
|
12
|
-
- **Trivial
|
|
13
|
-
-
|
|
14
|
-
- **
|
|
12
|
+
- **Trivial** — typo, label, small rename, spacing, toggle flag, obvious config change.
|
|
13
|
+
- Act directly. No doc reads. No planning. No index. No agents.
|
|
14
|
+
- **Simple** — 1-2 files, clear scope, existing pattern.
|
|
15
|
+
- Handle directly. Pull only the smallest useful context via resolver or targeted read.
|
|
16
|
+
- **Non-trivial / Risky** — auth, security, migration, uninstall, shared runtime, race/flaky, data-loss.
|
|
17
|
+
- Read deeper, verify harder, and avoid shortcuts.
|
|
18
|
+
- Use index-first loop, then skill activation, then targeted verification.
|
|
15
19
|
|
|
16
20
|
## Execution Contract (mandatory)
|
|
17
21
|
|
|
@@ -33,6 +37,7 @@ For any task that needs code context:
|
|
|
33
37
|
3. For bug signatures:
|
|
34
38
|
- `node .claude/ukit/index/triage.mjs "<error signature>"`
|
|
35
39
|
4. Open only the **top 1-3 suspect files first**, then widen if needed.
|
|
40
|
+
5. For analog/reuse patterns, check if `resolve-context` returns related existing patterns.
|
|
36
41
|
|
|
37
42
|
For clearly non-code specialist lanes (docs-only, status, task queue), skip the source-code index.
|
|
38
43
|
|
|
@@ -40,8 +45,9 @@ For clearly non-code specialist lanes (docs-only, status, task queue), skip the
|
|
|
40
45
|
|
|
41
46
|
- End users should not need to know skill names.
|
|
42
47
|
- On every non-trivial task — and again after the first relevant tool calls — inspect installed project-local skills and **auto-activate the matching skill immediately**.
|
|
43
|
-
- Match from prompt
|
|
44
|
-
- Use the smallest
|
|
48
|
+
- Match from both prompt wording and tool/file evidence.
|
|
49
|
+
- Use the smallest effective set, usually 1-2 skills.
|
|
50
|
+
- If evidence becomes more specific than the original prompt, upgrade the active skill choice immediately.
|
|
45
51
|
- If docs work is detected, read `.claude/skills/docs-quality/SKILL.md` when present.
|
|
46
52
|
- Prefer routed context and routed verification over ad-hoc broad reading.
|
|
47
53
|
- Reuse `.claude/ukit/skill-router-state.json` when it already carries compact route memory.
|
|
@@ -49,22 +55,23 @@ For clearly non-code specialist lanes (docs-only, status, task queue), skip the
|
|
|
49
55
|
|
|
50
56
|
### Common skill triggers
|
|
51
57
|
|
|
52
|
-
- review / audit / diff → `.claude/skills/code-review/SKILL.md`
|
|
53
|
-
- bug / error / crash / triage → `.claude/skills/debugging-toolkit/SKILL.md`
|
|
54
|
-
- test / spec / coverage → `.claude/skills/testing-quality/SKILL.md`
|
|
58
|
+
- review / audit / diff / PR feedback → `.claude/skills/code-review/SKILL.md`
|
|
59
|
+
- bug / error / crash / triage / failing path → `.claude/skills/debugging-toolkit/SKILL.md`
|
|
60
|
+
- test / spec / coverage / fixture → `.claude/skills/testing-quality/SKILL.md`
|
|
55
61
|
- docs / README / changelog / handoff / editing `docs/` / cleaning `docs/TASKS.md` → `.claude/skills/docs-quality/SKILL.md`
|
|
56
62
|
- open-ended next step / project status / continue with no concrete target / choose queued task → `.claude/skills/next-step/SKILL.md`
|
|
57
63
|
- explicit handoff / wrap up / update `docs/STATUS.md` → `.claude/skills/update-status/SKILL.md`
|
|
58
|
-
- auth / security / token / permission / validation → `.claude/skills/discover-security/SKILL.md`
|
|
59
|
-
- stale workspace / reinstall / cleanup → `.claude/skills/repo-maintenance/SKILL.md`
|
|
64
|
+
- auth / security / token / permission / validation / risky shell-path-delete-db work → `.claude/skills/discover-security/SKILL.md`
|
|
65
|
+
- stale workspace / reinstall / cleanup / maintenance → `.claude/skills/repo-maintenance/SKILL.md`
|
|
60
66
|
|
|
61
67
|
## Internal Helper Policy
|
|
62
68
|
|
|
63
|
-
- Prefer `node .claude/ukit/index/route-task.mjs
|
|
69
|
+
- Prefer `node .claude/ukit/index/route-task.mjs "<prompt>" [--tool-command <cmd>] [--target <file>]` when routing is complex or ambiguous.
|
|
64
70
|
- Prefer `node .claude/ukit/index/resolve-context.mjs ...` for indexed related-file context.
|
|
65
71
|
- Prefer `node .claude/ukit/index/verify-context.mjs ...` for concrete verification lanes.
|
|
66
72
|
- **Do not ask normal contributors to run internal helper commands**; run them yourself or tell them to rerun `ukit install`.
|
|
67
73
|
- Do not ask normal contributors to memorize `ukit doctor`, `ukit diff`, `ukit uninstall`, or `ukit index ...` unless they explicitly need maintainer/debug help.
|
|
74
|
+
- If the workspace needs a refresh, prefer telling them to rerun `ukit install`.
|
|
68
75
|
|
|
69
76
|
## Skill Quality (maintainer-only)
|
|
70
77
|
|
|
@@ -76,11 +83,11 @@ For clearly non-code specialist lanes (docs-only, status, task queue), skip the
|
|
|
76
83
|
- Treat `.ukit/storage/config.json` as the source of runtime toggles for compact, token pipeline, router, memory, validation, and Safe Patch behavior.
|
|
77
84
|
- Reuse `.ukit/storage/memory/` before asking users to restate decisions.
|
|
78
85
|
- For non-trivial work, prefer `ukit memory recall "<current task>"` before widening doc reads.
|
|
79
|
-
- Reusable cache/compact/output state lives in `.ukit/storage/cache/prompt-cache.json`, `.ukit/storage/cache/compact-history.json`, `.ukit/storage/cache/compact-pressure.json`,
|
|
86
|
+
- Reusable cache/compact/output state lives in `.ukit/storage/cache/prompt-cache.json`, `.ukit/storage/cache/compact-history.json`, `.ukit/storage/cache/compact-pressure.json`, `.ukit/storage/cache/output-history.json`, and preserved raw tool outputs under `.ukit/storage/cache/tee/`.
|
|
80
87
|
- Shared route memory lives in `.claude/ukit/skill-router-state.json`.
|
|
81
88
|
- If shared route state already includes compact `previous-context` or `recent-output`, reuse those first.
|
|
82
89
|
- If an older repo still has a visible `ukit/` runtime root, rerun `ukit install`; UKit should migrate the shared runtime into hidden `.ukit/` when safe.
|
|
83
|
-
- Maintainers can inspect runtime state with `ukit status` and `ukit memory export`.
|
|
90
|
+
- Maintainers can inspect runtime state with `ukit status` and `ukit memory export`, but normal teammates should still only need `ukit install`.
|
|
84
91
|
- If runtime files are missing or corrupt, tell maintainers to rerun `ukit install`.
|
|
85
92
|
- Threshold-based compact pressure is internal orchestration; do not expose it to users.
|
|
86
93
|
- For Codex Desktop long sessions, UKit can use soft auto-compact handoffs. Default `compact.codexContext.compactTarget=150` means about 150 compact handoff lines (120-150 preferred, hard max 170), not 150 tokens.
|
|
@@ -99,10 +106,9 @@ CHỈ kích hoạt khi task đi qua `docs/AI_HANDOFF/` (user nói "execute task
|
|
|
99
106
|
|
|
100
107
|
Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+Plan → Create Tasks → Implement+Test → Review+Test) + state machine + comment thread + self-report model. Config: `.ukit/storage/config.json` → `handoff.*`.
|
|
101
108
|
|
|
102
|
-
|
|
103
109
|
## Context + Verification Budget
|
|
104
110
|
|
|
105
|
-
- **Trivial**: no docs.
|
|
111
|
+
- **Trivial**: no docs, and no index query unless the file target is unclear.
|
|
106
112
|
- **Simple**: `docs/MEMORY.md` only, plus resolver-selected files/tests.
|
|
107
113
|
- **Non-trivial**: `docs/MEMORY.md` + `docs/PROJECT.md` + `docs/CODE_MAP.md`.
|
|
108
114
|
- `docs/STATUS.md`: use for open-ended status/continue prompts or meaningful continuation context; stale status is orientation only.
|
|
@@ -132,7 +138,7 @@ Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+P
|
|
|
132
138
|
|
|
133
139
|
- If routed state's `routeSummary.line` includes a `review=code-reviewer(diff)` segment, a `local-build` or `shared-edit` task qualifies for a non-blocking second opinion — this exists because the daily-flow executor model can miss edge cases.
|
|
134
140
|
- Only launch it once write evidence AND verification evidence already exist for the task (never before; never as a substitute for either).
|
|
135
|
-
- Launch the `code-reviewer` agent
|
|
141
|
+
- Launch the `code-reviewer` agent (see the harness table under 3-Tier Model Routing) with `REVIEW_TARGET_TYPE=diff`, in the background, on the `smart` tier per `subagents.diffReviewModel`. Do not wait for it — continue and report the task as done using the normal completion rules.
|
|
136
142
|
- Its findings are advisory only: never re-open, block, or delay the already-reported completion on their account. Surface them to the user as a follow-up note if/when they arrive.
|
|
137
143
|
- This is internal orchestration — end users never invoke it directly; `ukit install` plus natural language remains the whole surface. No new commands.
|
|
138
144
|
|
|
@@ -140,8 +146,13 @@ Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+P
|
|
|
140
146
|
|
|
141
147
|
- Keep direct execution as the default for trivial/simple work.
|
|
142
148
|
- Delegate only when it meaningfully shrinks context or enables useful parallel progress.
|
|
143
|
-
- Good delegation triggers:
|
|
149
|
+
- Good delegation triggers:
|
|
150
|
+
- noisy side lanes (broad logs/search/test output)
|
|
151
|
+
- 3+ independent failures/files/checks
|
|
152
|
+
- explicit batch/plan execution
|
|
153
|
+
- broad implementation/debug lanes that can return a concise summary
|
|
144
154
|
- If route memory includes `delegate=<lane>`, treat it as an internal hint after any required indexed-context step.
|
|
155
|
+
- Do not ask end users to name agents or remember agent commands.
|
|
145
156
|
|
|
146
157
|
## Adaptive Autonomy
|
|
147
158
|
|
|
@@ -168,6 +179,20 @@ UKit routes tasks to one of three model tiers based on task complexity:
|
|
|
168
179
|
| `local-fix`, `local-build`, `shared-edit`, `find-cause`, `map-impact` | code |
|
|
169
180
|
| `review-release` | smart |
|
|
170
181
|
|
|
182
|
+
### How a tier is actually bound
|
|
183
|
+
|
|
184
|
+
The main session model never changes mid-turn. A tier only takes effect when work is handed to
|
|
185
|
+
an agent whose own definition binds that model:
|
|
186
|
+
|
|
187
|
+
| Harness | Agent definitions | How to launch one |
|
|
188
|
+
|---------|-------------------|-------------------|
|
|
189
|
+
| Claude Code | `.claude/agents/*.md` (`model:` frontmatter) | Agent tool, `subagent_type: "<name>"` |
|
|
190
|
+
| omp | `.omp/agents/*.md` (`model: "@lite"` / `"@code"` / `"@smart"` / `"@vision"`, resolved through `modelRoles` in `.omp/config.yml`) | task-agent `<name>` |
|
|
191
|
+
|
|
192
|
+
When a task's contract maps to a tier other than the current session model, hand it to the
|
|
193
|
+
matching agent instead of doing it inline. Doing everything inline is exactly what makes UKit
|
|
194
|
+
behave as if it only had one model — the tier table above has no effect on its own.
|
|
195
|
+
|
|
171
196
|
### Escalation rule
|
|
172
197
|
|
|
173
198
|
When the same file or symbol fails `debugLoopThreshold` (default: 2) times in one session, UKit routes the next attempt one tier higher (capped at `smart`). Config: `orchestration.escalation` in `.ukit/storage/config.json`.
|
|
@@ -179,9 +204,16 @@ This is internal orchestration — end users do not need to know about tiers, th
|
|
|
179
204
|
`unic-vision` is a **capability lane**, not a fourth cost tier — it is orthogonal to lite/code/smart above and never appears as a row in the tier table. `unic-code` and `unic-smart` cannot read images on the UNIC gateway; they must never guess at image contents.
|
|
180
205
|
|
|
181
206
|
- **Gateway detection**: UNIC routing for a Claude Code session is decided ONLY by what changes Claude Code's own outbound endpoint — `ANTHROPIC_BASE_URL` (env var, or the `env.ANTHROPIC_BASE_URL` key in project/home `.claude/settings.json`) containing `unicjsc.com`. Other tools' configs — Codex `config.toml`, Kilo `secrets.json`, or an `OPENAI_BASE_URL` env var — describe a different tool's endpoint entirely and never decide this session's routing.
|
|
182
|
-
- **Enforcement**: every image (pasted, local file path, or URL) must be analysed by the `ukit-vision-analyst` agent running on
|
|
207
|
+
- **Enforcement**: every image (pasted, local file path, or URL) must be analysed by the `ukit-vision-analyst` agent running on the vision lane before any related edit happens. `Edit`/`Write` are **hard-blocked** until an analysis receipt exists for every pending image; `Read`/`Grep`/`Glob`/`Bash` stay unblocked so the analyst itself can see the image and write its receipt.
|
|
183
208
|
- This is internal orchestration — end users never invoke a vision command directly; `ukit install` plus natural language remains the whole surface. No new commands.
|
|
184
209
|
|
|
210
|
+
## Skills
|
|
211
|
+
|
|
212
|
+
- Canonical skills live in `.claude/skills/`.
|
|
213
|
+
- Adapter mirrors may also exist, for example `.codex/skills/` → `.claude/skills/` (symlink). **omp** has no mirror: it reads `.claude/skills/` directly through its own `claude` discovery provider.
|
|
214
|
+
- **OpenCode**: reads `AGENTS.md` at session start only — it does NOT auto-load `.claude/skills/`. The model must explicitly read the triggered SKILL.md.
|
|
215
|
+
- If `opencode.json` ships `ukit-*` commands, treat them as internal helper entrypoints only and **never ask end users to run them**; humans should still only need `ukit install`.
|
|
216
|
+
|
|
185
217
|
## Project Snapshot
|
|
186
218
|
|
|
187
219
|
- Project: {{project.name}} | Root: {{project.root}}
|
|
@@ -190,8 +222,7 @@ This is internal orchestration — end users do not need to know about tiers, th
|
|
|
190
222
|
|
|
191
223
|
## Working Rules
|
|
192
224
|
|
|
193
|
-
- Keep scope tight.
|
|
194
|
-
- Reuse existing code.
|
|
225
|
+
- Keep scope tight, prefer the smallest correct change set, and reuse existing code.
|
|
195
226
|
- For explicit implement/apply/fix requests, keep working until the actual edit is made or a real blocker is found; do not stop after a read-only inspection step.
|
|
196
227
|
- If routed state still says `pull-indexed-context`, treat it as an internal continuation step, not a stopping point.
|
|
197
228
|
- If routed state shows `continuation required` or a stuck-lane rescue mode, finish the named milestone before widening reads or rephrasing the same partial status.
|
|
@@ -211,4 +242,11 @@ DuraOne skill chỉ active khi pack `duraone` được cài hoặc `.claude/skil
|
|
|
211
242
|
- `.claude/skills/duraone/references/sql.md`
|
|
212
243
|
- `.claude/skills/duraone/references/workflow.md`
|
|
213
244
|
- Khi không active: dùng generic coding standards + project-specific patterns từ index.
|
|
245
|
+
|
|
246
|
+
## Completion Checklist
|
|
247
|
+
|
|
248
|
+
- Requirements implemented
|
|
249
|
+
- No unrelated changes
|
|
250
|
+
- Verification executed and reported
|
|
251
|
+
- Docs updated when source truth changed
|
|
214
252
|
{{codegraphSection}}
|