@ngockhoale/ukit 2.7.10 → 2.7.12

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.
@@ -127,22 +127,6 @@ the root contract is the only carrier — keep both in sync with
127
127
  turn it into an end-user workflow.
128
128
  - Always preserve the CoDev priority: quality > safety > speed > token discipline.
129
129
 
130
- ## Post-Edit Sidecar Review — detail
131
-
132
- - If routed state's `routeSummary.line` includes a `review=code-reviewer(diff)` segment, a
133
- `local-build` or `shared-edit` task qualifies for a non-blocking second opinion — this
134
- exists because the daily-flow executor model can miss edge cases.
135
- - Only launch it once write evidence AND verification evidence already exist for the task
136
- (never before; never as a substitute for either).
137
- - Launch the `code-reviewer` agent (see the harness table under 3-Tier Model Routing) with
138
- `REVIEW_TARGET_TYPE=diff`, in the background, on the `smart` tier per
139
- `subagents.diffReviewModel`. Do not wait for it — continue and report the task as done
140
- using the normal completion rules.
141
- - Its findings are advisory only: never re-open, block, or delay the already-reported
142
- completion on their account. Surface them to the user as a follow-up note if/when they
143
- arrive.
144
- - This is internal orchestration — end users never invoke it directly; `ukit install` plus
145
- natural language remains the whole surface. No new commands.
146
130
 
147
131
  ## Selective Subagent Policy — detail
148
132
 
@@ -238,3 +222,81 @@ Phase-4 telemetry → advisory tuning loop (FR-206, TASK-232).
238
222
  - `learning/suggestions.json` — result of `computeTuningSuggestions(projectRoot)` (`src/learning/tuning.js`).
239
223
  - `cache/retriever-lanes.jsonl` — per-query lane hit/weight telemetry consumed by `collectLaneStats`.
240
224
  - **Advisory-only contract**: `suggestions` carry `{target, current, suggested, evidence}`; `applied` is always `[]`. `applyMode` is restricted to `manual|off` — **no writer ever mutates `codeIntel.retriever.weights` or `orchestration.escalation.debugLoopThreshold`**. Rules: lane weight ±0.1 step (clamped `[0.1, 2.0]`) when events ≥ 50 with a >0.5 dominant lane and a <0.02 starved lane; `debugLoopThreshold − 1` (min 1) when repeat-stall events ≥ 10. `ukit metrics` prints a `learning` section (pending count + targets; `n/a` when the artifact is absent).
225
+
226
+ ## Permission Modes + Unsafe Eval — detail
227
+
228
+ C38 unified permission model. `orchestration.permissionMode` (optional-present; absent tolerated for pre-C35 configs) declares one of three reserved modes — only `unattended` is implemented end-to-end today; `interactive`/`safe-auto` are modelled in the compiler so doctor can report on them but are not rendered modes.
229
+
230
+ - **`interactive`** — prompts are expected; mode fallback for unclassified entries is `prompt`. Doctor reports reachable prompts as INFO, never FAIL.
231
+ - **`safe-auto`** — same `prompt` fallback, modelled as "auto-allow safe classes, prompt the rest"; reachable prompts remain INFO.
232
+ - **`unattended`** — no human in the loop; mode fallback is `allow` for unclassified entries and any reachable `prompt`/`ask` on a managed surface is a doctor FAIL (`unattended-prompt`), because a prompt dead-ends the run.
233
+ - **Unattended ≠ all-destructive-allowed.** The canonical deny set (`CANONICAL_DENY` in `src/core/permissionPolicy.js`) applies in every mode; `hard-deny` entries (root/home/parent/dot recursive deletes, raw-device writes, mkfs, fork-bomb) are denied on every host including report-only codex, and `protected-guard` hooks (release credentials, protected files, stale-spec guard) outrank any host-deny. A deny never becomes a question — the agent picks the next safer alternative that satisfies the intent and records the substitution.
234
+ - **Host-internal waits are unchanged** — announce long waits, surface API/tool errors verbatim, name network/API as the suspect on stalls; the permission model does not alter the Stall & Wait Reporting contract.
235
+
236
+ `orchestration.allowUnsafeEval` (default `false`, optional-present boolean, migration never enables): only an explicit `true` renders `tools.approval.eval: allow` in `.omp/config.yml` via the `omp.evalApproval` render variable; every other state renders `deny` — fail-closed, never `prompt`. Residual risk stays documented: eval can carry subprocess payloads (`os.remove`, `shutil.rmtree`) that text-level `bash.patterns` denies cannot see.
237
+
238
+ Internals: `src/core/permissionPolicy.js` compiles the semantic policy (precedence hard-deny > protected-guard > host-deny > explicit-allow > mode-fallback; `UKIT_EPOLICY` on unknown mode). `src/core/permissionDoctor.js` backs `ukit doctor --permissions [--json]` — FAIL classes `unattended-prompt`, `deny-loss`, `unsafe-eval-mismatch`, `unrendered-token` exit 1; JSON shape `{ permissions: { declared, effective, hosts, checks, failures } }`. Template render, doctor, and the no-freeze matrix consume the same compiler so surfaces cannot drift.
239
+
240
+ ## Hook budget
241
+
242
+ - **Cap: 8 chain steps per hook group** (current max is 6). Any new step must also
243
+ carry a `:N` suffix with N > 0 — the runner never falls back to an implicit budget
244
+ for a declared chain.
245
+ - **Outer timeout = Σ(:N) + 10s minimum.** `settings.json` `timeout` is host-enforced
246
+ and cannot be derived at runtime, so the margin is enforced by
247
+ `tests/hooks/hookChainBudget.test.js` — forgetting to bump the outer fails loudly.
248
+ Every shipped group currently sits at exactly +10s.
249
+ - **Why env knobs can't violate the invariant:** `UKIT_HOOK_*_MS` only affect fallback
250
+ budgets for args that lack `:N`. On all-declared chains the inner budget is Σ:N by
251
+ construction, so inner ≤ outer − 10s holds regardless of env (the omp bridge shares
252
+ the `hook-chain-budget.mjs` resolver).
253
+ - **Convention: hot-path hooks ship as `.mjs` module steps, not new `.sh` processes.**
254
+ Each new `.sh` step costs a fresh spawn (~30–100ms on the hot path); `.mjs` steps run
255
+ in-proc in the runner with identical `:N` semantics. Keep the `.sh` thin wrapper
256
+ only when a direct/debug invocation path is needed.
257
+ - **Module-step contract:** a `"<path>.mjs[:N]"` arg is imported in-proc and must
258
+ export `runHook(ctx) -> {code, stdout, stderr}`; `ctx` =
259
+ `{payload, payloadText, projectRoot, env, deadlineMs, signal}`. A throw reports
260
+ `error`; a `deadlineMs`/`signal` breach reports `timeout` + `killed`. Export
261
+ `hookFailClosed = true` to join the fail-closed registry (infra failure → exit 2,
262
+ else 1) — the name-based `FAIL_CLOSED_SCRIPTS` list covers
263
+ `sensitive-data-guard.mjs` + `block-dangerous.mjs`. `isDirectRun()` gates a CLI
264
+ mode so the same file stays directly invocable; `UKIT_HOOK_DEADLINE_MS` is
265
+ scrubbed from `process.env`/`ctx.env` around import. Shipped modules:
266
+ `sensitive-data-guard.mjs`, `block-dangerous.mjs`, `record-execution.mjs`
267
+ (`hookFailClosed = false`; uses `setLedgerMessageEmitter` on
268
+ `execution-ledger.mjs` for the `noteSweepFailure` systemMessage).
269
+ - **Failure taxonomy + `--emit-verdict` mapping.** Every `results[]` entry carries a
270
+ `failureKind` from one closed set — `ok` (child exited 0), `exit-code` (child exited
271
+ non-zero on its own), `output-overflow` (capture exceeded the 2 MiB maxBuffer and the
272
+ tree was culled), `timeout` (the runner killed the child at its deadline), `signal`
273
+ (the child died from a signal the runner did not send), `error` (the child never
274
+ spawned), `budget-exhausted` (the script never ran — the chain total budget was spent
275
+ first). The `--emit-verdict` contract maps them onto one exit code: `ok`/`exit-code 0`
276
+ and any non-fail-closed failure → exit 0 (fail OPEN); a real `exit-code 2` block, or
277
+ ANY failure on a fail-closed gate (`output-overflow`, `timeout`, `signal`, `error`,
278
+ `budget-exhausted`) → exit 2 (fail CLOSED). An overflowed capture is dropped whole
279
+ before it can be replayed, so a truncated stream can never masquerade as a verdict.
280
+ `tests/hooks/hookChainFailureSurface.test.js` pins these surfaces.
281
+ - **stderr is a diagnostic channel, not verdict payload.** Under `--emit-verdict` the
282
+ runner drops the stderr of every non-verdict script: stdout is the verdict and Claude
283
+ Code parses it as ONE JSON document, so interleaving arbitrary hook diagnostics there
284
+ would break the contract (and leak whatever a hook happened to log). This is a
285
+ deliberate decision, not an open gap — stderr is replayed only where it carries the
286
+ verdict itself: the decision owner's stderr, the last executed script's stderr (block,
287
+ fail-closed-infra, and pass paths), and the runner's own synthesized diagnostics (the
288
+ unrun-gate line, `... could not produce a verdict (<failureKind>)`, the empty-chain
289
+ line). To surface diagnostics from an earlier step, have the step that owns the
290
+ verdict include them.
291
+ - The same test also guards the settings↔bridge mirror: `HOOK_EVENT_MAP` in
292
+ `templates/.omp/hooks/pre/ukit-bridge.js` must equal the settings chain args 1:1
293
+ per event/matcher.
294
+
295
+ ## Compressed contract detail (cycle 45 diet)
296
+
297
+ Detail dropped from `templates/instructions/core.md` during the ~25% system-prompt diet; semantics unchanged.
298
+
299
+ - **Prompt Caching one-liners** — CTX-01 deterministic segment bytes · CTX-02 keep roles and order · CTX-03 keep tool IDs and continuation state · CTX-04 no clock/random IDs in static blocks · CTX-05 compaction starts a new epoch · CTX-06 never change data to match a cache · CTX-07 no unconfirmed cache fields · CTX-08 tool-result reuse needs valid freshness · CTX-09 missing usage is unknown, not zero · CTX-10 never cut a required check to reduce calls. Full ruleset: `docs/PROMPT_CACHING.md`.
300
+ - **Common skill triggers** — review/audit/diff/PR → `code-review` · bug/error/crash/triage → `debugging-toolkit` · test/spec/coverage → `testing-quality` · docs/README/changelog/`docs/` edits → `docs-quality` · open-ended/status/continue/queued task → `next-step` · wrap up/`docs/STATUS.md` → `update-status` · auth/security/token/permission/risky → `discover-security` · stale workspace/reinstall/cleanup → `repo-maintenance` (all under `.claude/skills/<name>/SKILL.md`).
301
+ - **3-Tier typical tasks** — lite: reads, git queries, bash summaries, small doc edits · code: normal coding, shared edits, builds, debugging, impact mapping · smart: release review/audit, escalated deep reasoning after repeated failure.
302
+ - **UNATTENDED-02 tightened** — `maxAttemptsPerFailure` 5 → 2, `maxRecoveryStrategies` 3 → 2 (retry the same edit, then fix the cause differently; never loop one strategy).
@@ -1,167 +1,145 @@
1
1
  ## Core Rule
2
2
  <!-- RULES: CORE-01 CORE-02 -->
3
- - Human-facing UKit workflow collapses to one remembered command: `ukit install`.
4
- - After install, default to natural-language work inside **Claude Code / Codex / omp**.
3
+ - One command: `ukit install`; then work in natural language inside **Claude Code / Codex / omp**.
5
4
  - **Quality first, then speed, then token discipline.**
6
- - **Never stop after read-only steps** — implement/apply/fix requests continue to Edit/Write + verification in the same turn.
5
+ - **Never stop after read-only steps** — implement/apply/fix continues to Edit/Write + verification same turn.
7
6
 
8
7
  ## Fast Classification
9
8
  <!-- RULE: CLS-01 -->
10
- - **Trivial** — typo, label, small rename, spacing, toggle flag, obvious config change. Act directly. No doc reads, planning, index, or agents.
9
+ - **Trivial** — typo, label, rename, spacing, flag, obvious config. Act directly; no docs/index/agents.
11
10
  <!-- RULE: CLS-02 -->
12
- - **Simple** — 1-2 files, clear scope, existing pattern. Handle directly; pull only the smallest useful context via resolver or targeted read.
11
+ - **Simple** — 1-2 files, clear scope, existing pattern. Act directly; smallest useful context only.
13
12
  <!-- RULE: CLS-03 -->
14
- - **Non-trivial / Risky** — auth, security, migration, uninstall, shared runtime, race/flaky, data-loss. Read deeper, verify harder; index-first loop → skill activation → targeted verification.
13
+ - **Non-trivial / Risky** — auth, security, migration, uninstall, shared runtime, race/flaky, data-loss. Index-first → skill → targeted verification.
15
14
 
16
15
  ## Execution Contract (mandatory)
17
16
  <!-- RULE: EXEC-01 -->
18
- - For explicit implement/apply/fix requests, **continue until the actual edit is made** or a real blocker is found — never stop after a read-only inspection step.
17
+ - Implement/apply/fix: continue until the actual edit is made or a real blocker — never stop after read-only inspection.
19
18
  <!-- RULE: EXEC-03 -->
20
- - Routed states like `pull-indexed-context` or `continuation required` — treat it as an internal continuation step, not a stopping point; finish the named milestone before widening reads.
19
+ - Routed states (`pull-indexed-context`, `continuation required`): treat it as an internal continuation step, not a stopping point; finish the named milestone first.
21
20
  <!-- RULE: EXEC-02 -->
22
- - **Do NOT say "done"/"applied"/"fixed" after Read/Grep/analysis alone** — completion wording requires concrete Edit/Write evidence this turn, plus verification when scope is risky.
21
+ - **No "done"/"applied"/"fixed" after Read/Grep/analysis alone** — needs concrete Edit/Write evidence this turn, plus verification when risky.
23
22
  <!-- RULE: EXEC-04 -->
24
- - **Every stop says why — no silent idle.** Turns ending on a user-only action open with `WAITING ON YOU: <command/action>` plus a one-shot wakeup (~20-30 min) when available — an ended turn cannot observe external changes, so without it idle looks identical to a stall. Report any error verbatim the same turn.
23
+ - **Every stop says why — no silent idle.** User-only-action stops open with `WAITING ON YOU: <command/action>` + one-shot wakeup (~20-30 min) when available; report errors verbatim.
25
24
 
26
25
  ## Stall & Wait Reporting
27
26
  <!-- RULE: STALL-01 -->
28
- - Announce long waits as they happen: `Waiting for API response / tool result — will keep retrying; check your network/API provider if this persists`. Surface any API/tool error **verbatim** in the same turn, and name network/API as the suspect on long stalls — **never blame UKit**. This guidance makes the model's side of a wait visible; it cannot detect a stall inside the host's own request loop.
27
+ - Announce long waits: `Waiting for API response / tool result — will keep retrying; check your network/API provider if this persists`. Surface errors verbatim; suspect network/API — **never blame UKit**.
29
28
  <!-- RULE: STALL-02 -->
30
- - Every stop still says why (Execution Contract EXEC-04) — the stall rules above extend it, they do not replace it.
29
+ - Stall rules extend EXEC-04 (every stop says why); they do not replace it.
31
30
  <!-- RULE: STALL-03 -->
32
- - **Conditional workaround only:** fall back to one tool call per assistant message ONLY when malformed/concatenated tool-input errors are observed or the harness version is known-affected — otherwise keep using legitimate parallel calls; serializing healthy hosts contradicts batching guidance.
31
+ - **Conditional workaround only:** one tool call per assistant message only when malformed/concatenated tool-input errors are observed or the harness is known-affected — healthy hosts keep parallel calls.
33
32
 
34
33
  ## Long-Run Continuity
35
34
  <!-- RULES: LONG-01 LONG-02 -->
36
- - Near token-cap: **LAND one thing** end-to-end (edit + verify, ≤3 tool calls), **DEFER** the rest into `docs/STATUS.md` or bounded `docs/AI_HANDOFF/` tasks, **DELEGATE** broad work to subagents. Only then compact.
37
- - After any compact or handoff: continue from persisted disk state — never reread pre-compact context; delegate broad work, keep replies short.
38
- - A run ends only on completion evidence, a genuine blocker, or a user-only action — every stop names its reason. Detail: `docs/UKIT_INTERNALS.md`.
35
+ - Near token-cap: **LAND one thing** end-to-end (edit + verify, ≤3 tool calls), **DEFER** the rest to `docs/STATUS.md` or bounded `docs/AI_HANDOFF/` tasks, **DELEGATE** broad work to subagents. Then compact.
36
+ - After compact/handoff: continue from persisted disk state — never reread pre-compact context; delegate broadly, keep replies short.
37
+ - A run ends only on completion evidence, a genuine blocker, or a user-only action — every stop names its reason.
39
38
 
40
39
  ## Index-First Loop
41
- For any task needing code context:
42
-
43
40
  <!-- RULE: IDX-01 -->
44
- 1. Check the index is fresh (`.cache/index/`); if stale/missing, refresh via `node .claude/ukit/index/refresh-index.mjs`.
45
- 2. Query files: `node .claude/ukit/index/query-index.mjs "<error|symbol|path>"`; bug signatures: `triage.mjs "<error signature>"`.
41
+ 1. Check the index is fresh (`.cache/index/`); stale/missing → `node .claude/ukit/index/refresh-index.mjs`. Query: `query-index.mjs "<error|symbol|path>"`; bugs: `triage.mjs "<error>"`.
46
42
  <!-- RULE: IDX-02 -->
47
- 3. Open only the **top 1-3 suspect files first**, then widen if needed — the `outline:` block lets you jump straight to `Read(file, offset=<line>)`.
43
+ 2. Open only the **top 1-3 suspect files first**, then widen — `outline:` jumps to `Read(file, offset=<line>)`.
48
44
  <!-- RULE: IDX-03 -->
49
- The outline locates code; it does not describe behaviour — **any code you are about to change must still be read**.
50
- 4. For analog/reuse patterns, check `resolve-context`. Non-code lanes (docs-only, status, task queue) skip the source-code index.
45
+ The outline locates code, not behaviour — **code you are about to change must still be read**. Analog/reuse → `resolve-context`; non-code lanes skip.
51
46
 
52
47
  ## Automatic Skill Activation (mandatory)
53
48
  <!-- RULE: SKILL-01 -->
54
- - 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**; end users should not need skill names. Match from prompt wording and tool/file evidence.
49
+ - On every non-trivial task — and again after the first relevant tool calls — **auto-activate the matching skill immediately**; users never name skills. Match from prompt wording and tool/file evidence.
55
50
  <!-- RULES: SKILL-02 SKILL-03 -->
56
- - Use the smallest effective set (usually 1-2 skills); if evidence sharpens, upgrade the active skill choice immediately.
57
- - Prefer routed context/verification over ad-hoc broad reading; reuse `.claude/ukit/skill-router-state.json` compact route memory.
51
+ - Smallest effective set (1-2 skills); upgrade as evidence sharpens. Prefer routed context/verification over broad reading; reuse `.claude/ukit/skill-router-state.json` route memory.
58
52
 
59
53
  ### Common skill triggers
60
-
61
- - review / audit / diff / PR feedback → `code-review` · bug / error / crash / triage → `debugging-toolkit` · test / spec / coverage / fixture → `testing-quality`
62
- - docs / README / changelog / handoff / `docs/` edits → `docs-quality` (`.claude/skills/docs-quality/SKILL.md`) · open-ended / status / continue / queued task → `next-step` · wrap up / `docs/STATUS.md` update → `update-status`
63
- - auth / security / token / permission / risky work → `discover-security` · stale workspace / reinstall / cleanup → `repo-maintenance` (all under `.claude/skills/<name>/SKILL.md`)
54
+ - review/audit/diff → `code-review` · bug/error/crash → `debugging-toolkit` · test/coverage → `testing-quality` · docs/README/`docs/` → `docs-quality` (`.claude/skills/docs-quality/SKILL.md`) · open-ended/continue → `next-step` · wrap-up/`docs/STATUS.md` → `update-status` · auth/security/risky → `discover-security` · stale workspace/cleanup → `repo-maintenance`
64
55
 
65
56
  ## Internal Helper Policy
66
57
  <!-- RULES: HELP-01 HELP-02 -->
67
- - Prefer the internal index helpers (`node .claude/ukit/index/route-task.mjs`, `resolve-context.mjs`, `verify-context.mjs`) for routing, related-file context, and verification.
58
+ - Prefer the internal index helpers (`node .claude/ukit/index/route-task.mjs`, `resolve-context.mjs`, `verify-context.mjs`) for routing, context, verification.
68
59
  - **Do not ask normal contributors to run internal helper commands** or memorize maintainer commands (`ukit doctor`, `ukit diff`, `ukit uninstall`) — run them yourself.
69
60
  <!-- RULE: FALLBACK-01 -->
70
- - Missing/corrupt runtime files or stale workspace → tell maintainers to rerun `ukit install`. Detail: `docs/UKIT_INTERNALS.md`.
61
+ - Missing/corrupt runtime or stale workspace → rerun `ukit install`.
71
62
 
72
63
  ## Skill Quality (maintainer-only)
73
- - When editing a template skill/agent under `templates/.claude/`, read `.claude/skills/skill-quality/SKILL.md` before shipping.
64
+ - Editing `templates/.claude/` skills/agents → read `.claude/skills/skill-quality/SKILL.md` first.
74
65
 
75
66
  ## UKit v{{ukit.version}} Shared Runtime
76
- - Runtime state lives in `.ukit/storage/`; `.ukit/storage/config.json` holds runtime toggles (compact, token pipeline, router, memory, validation, Safe Patch).
77
- - Reuse `.ukit/storage/memory/` + `ukit memory recall "<current task>"` before asking users to restate decisions; `ukit memory learn` surfaces pending proposals, `ukit memory promote` writes approved rules to MEMORY.md, `ukit memory episode` records session episodes; inspect via `ukit status` / `ukit memory export`.
78
- - Route memory: `.claude/ukit/skill-router-state.json` — reuse compact `previous-context`/`recent-output` first. Cache state: `.ukit/storage/cache/output-history.json`, `retriever-lanes.jsonl`, `tee/`. Lifecycle hooks all degrade to exit 0 (SessionEnd `session-episode.sh` auto-writes episodes; full map: `docs/UKIT_INTERNALS.md`). Missing/corrupt runtime or old `ukit/` root → rerun `ukit install`. Detail: `docs/UKIT_INTERNALS.md`.
79
-
67
+ - Runtime state: `.ukit/storage/`; `config.json` holds toggles (compact, token pipeline, router, memory, validation, Safe Patch). `ukit memory recall "<task>"` before asking users to restate decisions; `learn`/`promote`/`episode` manage memory; inspect via `ukit status` / `ukit memory export`. Route memory: `.claude/ukit/skill-router-state.json` (`previous-context`/`recent-output` first); cache: `.ukit/storage/cache/output-history.json` + `retriever-lanes.jsonl` + `tee/`. Hooks degrade to exit 0; missing/corrupt runtime → rerun `ukit install`.
80
68
  ## Prompt Caching
81
69
  <!-- RULES: CTX-01 CTX-02 CTX-03 CTX-04 CTX-05 CTX-06 CTX-07 CTX-08 CTX-09 CTX-10 -->
82
- - Full ruleset: `docs/PROMPT_CACHING.md` (read on demand; not loaded every session).
83
- - CTX-01 deterministic segment bytes · CTX-02 keep roles and order · CTX-03 keep tool IDs and continuation state · CTX-04 no clock/random IDs in static blocks · CTX-05 compaction starts a new epoch · CTX-06 never change data to match a cache · CTX-07 no unconfirmed cache fields · CTX-08 tool-result reuse needs valid freshness · CTX-09 missing usage is unknown, not zero · CTX-10 never cut a required check to reduce calls.
70
+ - Full ruleset: `docs/PROMPT_CACHING.md` (read on demand).
84
71
 
85
72
  ## Safe Patch Protocol
86
73
  <!-- RULES: SAFE-02 SAFE-03 SAFE-01 -->
87
- - Risky/shared/large edits: prefer unique current-file anchors over line numbers or stale pasted blocks; if `old_string` is missing/ambiguous, re-read current source and ask whether to apply as-is, adapt, or skip.
88
- - Preserve UTF-8 BOM/no-BOM and LF/CRLF for existing multilingual/user-authored files. Helper: `node .claude/ukit/index/safe-patch.mjs`; detail: `docs/UKIT_INTERNALS.md`.
74
+ - Risky/shared/large edits: prefer unique current-file anchors over line numbers or stale pasted blocks; missing/ambiguous `old_string` → re-read source, then apply, adapt, or skip.
75
+ - Preserve UTF-8 BOM/no-BOM and LF/CRLF on existing files. Helper: `node .claude/ukit/index/safe-patch.mjs`.
89
76
 
90
77
  ## Handoff Quality Gate — OPT-IN
91
78
  <!-- RULE: HAND-01 -->
92
- 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. Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+Plan → Create Tasks → Implement+Test → Review+Test) + state machine + self-report model. Config: `.ukit/storage/config.json` → `handoff.*`.
79
+ Chỉ active khi task đi qua `docs/AI_HANDOFF/` ("execute task TASK-xxx" hoặc `docs/AI_HANDOFF/tasks/*.md`); daily prompt giữ flow cũ. Khi active: đọc `docs/AI_HANDOFF/RULES.md` (4 phase + state machine + self-report). Config: `.ukit/storage/config.json` → `handoff.*`.
93
80
 
94
81
  ## Context + Verification Budget
95
82
  <!-- RULE: BUDGET-01 -->
96
- - **Trivial**: no docs, no index query unless the file target is unclear. **Simple**: `docs/MEMORY.md` only + resolver-selected files/tests. **Non-trivial**: `docs/MEMORY.md` + `docs/PROJECT.md` + `docs/CODE_MAP.md`.
83
+ - **Trivial**: no docs, no index query unless the target is unclear. **Simple**: `docs/MEMORY.md` + resolver-selected files/tests. **Non-trivial**: + `docs/PROJECT.md` + `docs/CODE_MAP.md`.
97
84
  <!-- RULES: BUDGET-02 BUDGET-03 -->
98
- - `docs/STATUS.md` for open-ended/continue prompts; `docs/TASKS.md` only for queued-task prompts; `docs/WORKLOG.md` recent entries only (archive overflow). Verification: targeted first, widen only on risk/shared scope, ask before blanket broad runs.
85
+ - `docs/STATUS.md` for open-ended/continue; `docs/TASKS.md` only for queued-task prompts; `docs/WORKLOG.md` recent entries only. Verification: targeted first, widen on risk/shared scope, ask before broad runs.
99
86
 
100
87
  ## Living Status Workflow
101
88
  <!-- RULE: STATUS-01 -->
102
- - `docs/STATUS.md` captures compact current state — not source truth, never replaces source/index-first investigation.
103
- - "What next?"/"continue" → `next-step` with a freshness cue; after meaningful work → `update-status`. `docs/TASKS.md` is the local AI task queue — prefer `Ready for AI`. Detail: `docs/UKIT_INTERNALS.md`.
89
+ - `docs/STATUS.md` = compact current state — not source truth, never replaces index-first investigation.
90
+ - "What next?"/"continue" → `next-step`; after meaningful work → `update-status`. `docs/TASKS.md` = local AI task queue — prefer `Ready for AI`.
104
91
 
105
92
  ## Subagent Lanes (internal)
106
93
  <!-- RULE: SUBAG-02 -->
107
- - The `ukit-small-task-maintainer` subagent (`subagents.smallTaskModel`, default `unic-lite`) handles safe/reversible UKit chores as a sidecar lane — never block or slow the user task; risky work hands back to the main model. Detail: `docs/UKIT_INTERNALS.md`.
108
- - When routed state's `routeSummary.line` carries `review=code-reviewer(diff)`, launch `code-reviewer` in background (`smart` tier) **only after** write + verification evidence; findings advisory — never block the reported completion. Detail: `docs/UKIT_INTERNALS.md`.
94
+ - `ukit-small-task-maintainer` (`subagents.smallTaskModel`, default `unic-lite`) = sidecar lane for safe/reversible UKit chores — never block the user task; risky work hands back.
109
95
  <!-- RULE: SUBAG-01 -->
110
- - Direct execution is default for trivial/simple work; delegate only on meaningful context shrink or parallel gains (noisy side lanes, 3+ independent failures, batch plans). Never ask end users to name agents or remember agent commands.
96
+ - Direct execution is default for trivial/simple work; delegate only on real context shrink or parallel gains. Never ask users to name agents or agent commands.
111
97
 
112
98
  ## Adaptive Autonomy
113
99
  <!-- RULE: AUTO-01 -->
114
- - `autonomy.level` in `.ukit/storage/config.json` controls how much UKit acts without asking: `conservative` (ask more), `balanced` (default), `free-run` (auto-run more), `vibecode` (one prompt to a finished result; the gate stops only on completion evidence, a genuine blocker, or a dangerous-command decision). End users should not need to change it.
100
+ - `autonomy.level` in `.ukit/storage/config.json`: `conservative` | `balanced` (default) | `free-run` | `vibecode` (one prompt to a finished result; stops only on completion evidence, a genuine blocker, or a dangerous-command decision).
115
101
 
116
102
  ## Unattended Completion Loop
117
103
  <!-- RULE: UNATTENDED-01 -->
118
- - Under `orchestration.permissionMode: unattended` there is no human in the loop — the loop is UNDERSTAND → PLAN → IMPLEMENT → VERIFY → FIX → REVERIFY → COMPLETE. A turn ends only on COMPLETE evidence, a real external blocker, or a deny decision.
104
+ - `orchestration.permissionMode: unattended` = no human in the loop — UNDERSTAND → PLAN → IMPLEMENT → VERIFY → FIX → REVERIFY → COMPLETE. A turn ends only on COMPLETE evidence, a real external blocker, or a deny.
119
105
  <!-- RULE: UNATTENDED-02 -->
120
- - `maxAttemptsPerFailure: 5` per failing verification, `maxRecoveryStrategies: 3` distinct fix strategies before reassessing — retry the same edit, fix the cause differently, then reduce scope/approach; do not loop one strategy.
106
+ - `maxAttemptsPerFailure: 2`, `maxRecoveryStrategies: 2` distinct fix strategies before reassessing — retry the same edit, then fix the cause differently; never loop one strategy.
121
107
  <!-- RULE: UNATTENDED-03 -->
122
- - BLOCKED only on true external blockers: missing credentials, dead service, unreachable network/API. Test failures, lint errors, review findings, and ambiguity are NOT blockers — they feed FIX.
108
+ - BLOCKED only on true external blockers: missing credentials, dead service, unreachable network/API. Test failures, lint errors, review findings, ambiguity are NOT blockers — feed FIX.
123
109
  <!-- RULE: UNATTENDED-04 -->
124
- - A deny (hook/gate/permission) never becomes a question: pick the next safer alternative that satisfies the intent and record the substitution. Never emit "do you want me to…" — decide and proceed.
110
+ - A deny (hook/gate/permission) never becomes a question: pick the next safer alternative satisfying the intent, record the substitution. Never emit "do you want me to…" — decide and proceed.
125
111
 
126
112
  ## 3-Tier Model Routing
127
113
  <!-- RULES: TIER-01 TIER-02 -->
128
- **Internal orchestration only — end users still just use natural language. No new commands.**
114
+ **Internal orchestration only — end users still use natural language. No new commands.**
129
115
 
130
- | Tier | Generic alias | Claude model | Typical tasks |
131
- |------|--------------|--------------|---------------|
132
- | lite | `unic-lite` | claude-haiku | Reads, git queries, bash summaries, small doc edits |
133
- | code | `unic-code` | claude-sonnet | Normal coding, local fixes, shared edits, builds, debugging, impact mapping |
134
- | smart | `unic-smart` | claude-opus | Release review/audit, escalated deep reasoning after repeated failure |
116
+ | Tier | Alias | Claude model |
117
+ |------|-------|--------------|
118
+ | lite | `unic-lite` | claude-haiku |
119
+ | code | `unic-code` | claude-sonnet |
120
+ | smart | `unic-smart` | claude-opus |
135
121
 
136
- - A tier takes effect only when work is handed to an agent whose definition binds that model (`model:` frontmatter in `.claude/agents/*.md`; `model:` `@smol`/`@default`/`@slow`/`@vision` in `.omp/agents/*.md` via `modelRoles`) — the main session model never changes mid-turn.
137
- - Contract map: `tiny-fix` → lite · `local-fix`, `local-build`, `shared-edit`, `find-cause`, `map-impact` → code · `review-release` → smart. Escalation: same file/symbol failing `debugLoopThreshold` (default 2) times routes the next attempt one tier higher, capped at `smart`.
138
- - `unic-vision` is a capability lane, not a cost tier — unverified vision must never guess image contents; route images to `ukit-vision-analyst`. Harness table: `docs/UKIT_INTERNALS.md`.
122
+ - A tier binds only via an agent's `model:` field (`.claude/agents/*.md`; `.omp/agents/*.md` `@smol`/`@default`/`@slow`/`@vision` via `modelRoles`) — the session model never changes mid-turn. Contract map: `tiny-fix` → lite · `local-fix`/`local-build`/`shared-edit`/`find-cause`/`map-impact` → code · `review-release` → smart; escalation: same file/symbol failing `debugLoopThreshold` (2) → one tier up, cap `smart`. `unic-vision` = capability lane (not cost) — never guess images; route to `ukit-vision-analyst`.
139
123
 
140
124
  ## Skills
141
- - Canonical skills live in `.claude/skills/`; adapter mirrors may exist (`.codex/skills/` → symlink). **omp** reads `.claude/skills/` via its `claude` discovery provider.
125
+ - Canonical skills: `.claude/skills/`; adapter mirrors may exist (`.codex/skills/` → symlink). **omp** reads `.claude/skills/` via its `claude` provider.
142
126
 
143
127
  ## Project Snapshot
144
- - Project: {{project.name}} | Root: {{project.root}}
145
- - Packs: {{project.stack}} | Frontend: {{stack.frontend}} | Backend API: {{stack.backendApi}} | PostgreSQL: {{stack.postgres}}
146
- - Package manager: {{runtime.packageManager}} | OS: {{runtime.os}} | Node: {{runtime.nodeVersion}} | Provider: {{providers.unic}}
128
+ - Project: {{project.name}} | Root: {{project.root}} | Packs: {{project.stack}} | PM: {{runtime.packageManager}} | OS: {{runtime.os}} | Node: {{runtime.nodeVersion}} | Provider: {{providers.unic}}
147
129
 
148
130
  ## Working Rules
149
- - Keep scope tight, prefer the smallest correct change set, and reuse existing code.
150
- - Update `docs/WORKLOG.md` after significant work; if source contradicts docs, update docs immediately.
151
- - Use `{{runtime.packageManager}}`.
131
+ - Keep scope tight; smallest correct change set; reuse existing code. Update `docs/WORKLOG.md` after significant work; source contradicts docs → update docs. Use `{{runtime.packageManager}}`.
152
132
 
153
133
  ## DuraOne Skill — Conditional Activation
154
134
  <!-- RULE: DURA-01 -->
155
- DuraOne skill chỉ active khi pack `duraone` được cài hoặc `.claude/skills/duraone/SKILL.md` tồn tại — khi active, luôn đọc SKILL.md + references trước khi code; khi không, dùng generic standards + index patterns. Chi tiết: `docs/UKIT_INTERNALS.md`.
135
+ DuraOne skill chỉ active khi pack `duraone` được cài hoặc `.claude/skills/duraone/SKILL.md` tồn tại — khi active, đọc SKILL.md + references trước khi code; khi không, dùng generic standards + index patterns.
156
136
 
157
137
  ## Completion Checklist
158
- - Requirements implemented · No unrelated changes · Verification executed and reported · Docs updated when source truth changed.
138
+ - Requirements implemented · No unrelated changes · Verification executed + reported · Docs updated when source truth changed.
159
139
 
160
140
  ## Handoff Fullstack Rules
161
141
  <!-- RULE: HAND-02 -->
162
- - `docs/AI_HANDOFF/RUN.md` là run cursor có thẩm quyền; `Phase:` ≠ `done`/`blocked` nghĩa là run còn sống — Stop gate từ chối stop và trả về `Next:` step.
163
- - Recap/checkpoint không bao giờ là completion — chỉ `HANDOFF FULLSTACK COMPLETE` (sau `Phase: done`) hoặc `HANDOFF FULLSTACK BLOCKED` (sau `Phase: blocked`) mới kết thúc run. Resume tự động mọi task chưa xong (current, legacy, pending, interrupted, recovery `-R<n>`).
164
- - Kết thúc cycle: docs sync → archive `docs/AI_HANDOFF/archive/cycle-NN/` → `Phase: done`. `handoff-clear` bắt buộc đóng RUN.md. Full rules: `docs/AI_HANDOFF/RULES.md`.
142
+ - `docs/AI_HANDOFF/RUN.md` là run cursor có thẩm quyền; `Phase:` ≠ `done`/`blocked` = run còn sống — Stop gate từ chối stop, trả về `Next:`. Chỉ `HANDOFF FULLSTACK COMPLETE`/`BLOCKED` kết thúc run — recap/checkpoint không phải completion; resume tự động mọi task chưa xong. Kết thúc cycle: docs sync → archive `archive/cycle-NN/` → `Phase: done`; `handoff-clear` bắt buộc đóng RUN.md. Full rules: `docs/AI_HANDOFF/RULES.md`.
165
143
 
166
144
  ## Compact Instructions
167
- Khi compact giữa một handoff run: giữ lại goal, RUN.md path + phase hiện tại, task inventory, task đang làm, `Next:` step, blockers, verification evidence, commits, worktree/copy-back state, và quy tắc "compact không phải completion". Sau compact: đọc lại RUN.md + INDEX.md rồi chạy tiếp `Next:` ngay.
145
+ Compact giữa handoff run: giữ goal, RUN.md path + phase, task inventory + task đang làm, `Next:` step, blockers, verification evidence, commits, worktree/copy-back state, "compact không phải completion". Sau compact: đọc lại RUN.md + INDEX.md rồi chạy `Next:`.
@@ -75,19 +75,17 @@
75
75
  "tokenPipeline": {
76
76
  "inputCompression": true,
77
77
  "outputCompression": true,
78
- "promptCache": true
78
+ "promptCache": true,
79
+ "outputMaxTokens": 600,
80
+ "outputMaxLines": 40
79
81
  },
80
82
  "router": {
81
83
  "enabled": true,
82
- "defaultModel": "claude-sonnet-5",
83
- "advisorModel": "claude-opus-5",
84
- "advisorEnabled": true,
85
- "maxAdvisorCalls": 3
84
+ "defaultModel": "claude-sonnet-5"
86
85
  },
87
86
  "orchestration": {
88
87
  "enabled": true,
89
88
  "orchestratorModel": "claude-sonnet-5",
90
- "advisorEnabled": true,
91
89
  "permissionMode": "unattended",
92
90
  "allowUnsafeEval": false,
93
91
  "contracts": {
@@ -110,8 +108,7 @@
110
108
  "maxContextPulls": 1,
111
109
  "verificationPolicy": "targeted-if-covered",
112
110
  "completionRule": "require-write-and-verification",
113
- "delegationPolicy": "disallow-by-default",
114
- "postEditReviewPolicy": "sidecar-non-blocking"
111
+ "delegationPolicy": "disallow-by-default"
115
112
  },
116
113
  "find-cause": {
117
114
  "maxReadPassesBeforeReassess": 3,
@@ -124,8 +121,7 @@
124
121
  "maxContextPulls": 2,
125
122
  "verificationPolicy": "targeted-then-widen-on-risk",
126
123
  "completionRule": "require-write-and-verification",
127
- "delegationPolicy": "allow-qualified-sidecar",
128
- "postEditReviewPolicy": "sidecar-non-blocking"
124
+ "delegationPolicy": "allow-qualified-sidecar"
129
125
  },
130
126
  "map-impact": {
131
127
  "maxReadPasses": 3,
@@ -213,9 +209,8 @@
213
209
  },
214
210
  "memory": {
215
211
  "enabled": true,
216
- "autoCapture": true,
217
212
  "progressiveRetrieval": true,
218
- "maxInjectionTokens": 1000,
213
+ "maxInjectionTokens": 320,
219
214
  "archiveAfterDays": 30,
220
215
  "maxSessions": 20,
221
216
  "redactSecrets": true
@@ -326,9 +321,6 @@
326
321
  "enabled": true,
327
322
  "smallTaskModel": "unic-lite",
328
323
  "smallTaskAgent": "ukit-small-task-maintainer",
329
- "diffReviewEnabled": true,
330
- "diffReviewAgent": "code-reviewer",
331
- "diffReviewModel": "unic-smart",
332
324
  "visionEnabled": true,
333
325
  "visionModel": "unic-vision",
334
326
  "visionAgent": "ukit-vision-analyst",
@@ -537,28 +529,25 @@
537
529
  "tokenPipeline": {
538
530
  "inputCompression": "Nén/tái sử dụng input context khi an toàn.",
539
531
  "outputCompression": "Tóm tắt output command ồn nhưng vẫn giữ recovery hint.",
540
- "promptCache": "Dùng cache prompt/context compact để giảm lặp lại."
532
+ "promptCache": "Dùng cache prompt/context compact để giảm lặp lại.",
533
+ "outputMaxTokens": "Ngân sách token tối đa cho output command sau khi nén. Output nhỏ hơn ngưỡng này được bỏ qua nén hoàn toàn. Mặc định 600.",
534
+ "outputMaxLines": "Số dòng tối đa trong bản tóm tắt output đã nén. Mặc định 40."
541
535
  },
542
536
  "router": {
543
537
  "enabled": "Bật task routing nội bộ.",
544
- "defaultModel": "Model hint cân bằng cho công việc bình thường. Adapter/provider có thể map khác.",
545
- "advisorModel": "Model hint mạnh hơn cho planning/reasoning khó khi được bật.",
546
- "advisorEnabled": "Cho phép advisor-style planning cho task phức tạp.",
547
- "maxAdvisorCalls": "Giới hạn số lần gọi advisor để không lãng phí."
538
+ "defaultModel": "Model hint cân bằng cho công việc bình thường. Adapter/provider có thể map khác."
548
539
  },
549
540
  "orchestration": {
550
541
  "enabled": "Bật ladder điều phối nội bộ của UKit. Ladder này thay cách nghĩ LITE/FULL cứng nhắc bằng các tầng tiny-fix → review-release an toàn hơn.",
551
542
  "orchestratorModel": "Model điều phối chất lượng cao để chọn execution layer. Đây là model quan trọng cho chất lượng completion, không nên dùng model quá yếu.",
552
- "advisorEnabled": "Cho phép UKit dùng advisor-style reasoning khi chọn layer trong tình huống mơ hồ.",
553
543
  "permissionMode": "Chế độ quyền của orchestration. Ba giá trị dành riêng: interactive, safe-auto, unattended. Chu kỳ này chỉ triển khai unattended.",
554
544
  "allowUnsafeEval": "Mặc định false. Chỉ khi user tự bật true, .omp/config.yml mới render tools.approval.eval: allow; mọi trường hợp khác render deny (fail-closed, không bao giờ prompt). Residual risk: eval chạy payload subprocess (os.remove, shutil.rmtree) mà bash.patterns text deny không chặn được — chỉ dựa vào bridge eval->Bash của TASK-004.",
555
545
  "contracts": "Bộ contract cho 7 tầng điều phối: tiny-fix, local-fix, local-build, find-cause, shared-edit, map-impact, review-release. Khi mơ hồ, UKit nên lệch lên tầng an toàn hơn dù tốn token hơn."
556
546
  },
557
547
  "memory": {
558
548
  "enabled": "Bật memory local của UKit.",
559
- "autoCapture": "Cho phép UKit lưu decision/rule bền vững khi an toàn.",
560
549
  "progressiveRetrieval": "Lấy memory liên quan nhỏ trước, chỉ mở rộng khi cần.",
561
- "maxInjectionTokens": "Số token memory tối đa được inject vào context.",
550
+ "maxInjectionTokens": "Số token memory tối đa được inject vào context (clamp thực tế trong khoảng 160–640).",
562
551
  "archiveAfterDays": "Sau bao nhiêu ngày memory có thể được archive/compact.",
563
552
  "maxSessions": "Số session memory gần đây giữ active.",
564
553
  "redactSecrets": "Cố tránh lưu secret vào memory."