@ngockhoale/ukit 2.6.11 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/manifests/documentation.yaml +24 -2
  3. package/manifests/instructionRules.yaml +62 -0
  4. package/package.json +1 -1
  5. package/scripts/perf/audit-perf.mjs +920 -0
  6. package/src/cli/commands/doctor.js +23 -4
  7. package/src/core/diffPlan.js +8 -0
  8. package/src/core/ompConfigMerge.js +251 -0
  9. package/src/core/runInstallPipeline.js +11 -0
  10. package/src/core/runtimeConfig.js +16 -3
  11. package/src/core/unattendedDoctor.js +227 -0
  12. package/templates/.claude/commands/ukit/handoff-create.md +1 -1
  13. package/templates/.claude/commands/ukit/handoff-fullstack.md +2 -2
  14. package/templates/.claude/commands/ukit/handoff-implement.md +1 -1
  15. package/templates/.claude/commands/ukit/handoff-review.md +1 -1
  16. package/templates/.claude/hooks/block-dangerous.sh +76 -9
  17. package/templates/.claude/hooks/context-hardcap-gate.sh +26 -8
  18. package/templates/.claude/hooks/project-important.sh +70 -9
  19. package/templates/.claude/hooks/protect-files.sh +24 -7
  20. package/templates/.claude/hooks/sensitive-data-guard.sh +57 -5
  21. package/templates/.claude/settings.json +22 -117
  22. package/templates/.claude/ukit/runtime/hook-chain-runner.mjs +217 -10
  23. package/templates/.claude/ukit/runtime/hook-input.sh +119 -0
  24. package/templates/.omp/README.md +11 -7
  25. package/templates/.omp/RULES.md +7 -6
  26. package/templates/.omp/agents/bug-debugger.md +1 -1
  27. package/templates/.omp/agents/code-reviewer.md +1 -1
  28. package/templates/.omp/agents/feature-implementer.md +1 -1
  29. package/templates/.omp/agents/handoff-planner.md +1 -1
  30. package/templates/.omp/agents/ukit-small-task-maintainer.md +2 -2
  31. package/templates/.omp/config.yml +42 -8
  32. package/templates/.omp/hooks/pre/ukit-bridge.js +12 -1
  33. package/templates/AGENTS.md +23 -11
  34. package/templates/CLAUDE.md +23 -11
  35. package/templates/adapter-presets/opencode/opencode.template.json +1 -1
  36. package/templates/docs/UKIT_INTERNALS.md +1 -1
  37. package/templates/instructions/core.md +23 -11
  38. package/templates/instructions/layout.yaml +12 -12
  39. package/templates/instructions/overlays/omp-rules.md +7 -6
  40. package/templates/ukit/storage/config.json +9 -3
@@ -26,19 +26,23 @@ whatever was there before, so local edits are never silently lost — they move,
26
26
 
27
27
  ## Model roles
28
28
 
29
- `.omp/config.yml` defines four roles. Agent frontmatter references them as `@lite` / `@code` /
30
- `@smart` / `@vision`, so retargeting a whole tier is a one-line edit in one file.
29
+ `.omp/config.yml` defines omp's native roles `smol` / `default` / `slow` / `vision` plus
30
+ back-compat aliases `lite` / `code` / `smart` that resolve to the same models. Agent frontmatter
31
+ references the native roles as `@smol` / `@default` / `@slow` / `@vision`, so retargeting a whole
32
+ tier is a one-line edit in one file — but remember the matching `lite`/`code`/`smart` alias is an
33
+ independent key: edit it too, or it keeps resolving to the old value.
31
34
 
32
35
  | Role | Default model | Agents using it |
33
36
  |------|---------------|-----------------|
34
- | `lite` | `unic-lite` | `ukit-small-task-maintainer` |
35
- | `code` | `unic-code` | `feature-implementer`, `bug-debugger` |
36
- | `smart` | `unic-smart` | `handoff-planner`, `code-reviewer` |
37
+ | `smol` (alias `lite`) | `unic-lite` | `ukit-small-task-maintainer` |
38
+ | `default` (alias `code`) | `unic-code` | `feature-implementer`, `bug-debugger` |
39
+ | `slow` (alias `smart`) | `unic-smart` | `handoff-planner`, `code-reviewer` |
37
40
  | `vision` | `unic-vision` | `ukit-vision-analyst` |
38
41
 
39
42
  These are **literal model names on the UNIC gateway, not aliases**, and they ship as the installed
40
- default. If this project does not run against UNIC, a maintainer swaps the three cost tiers for the
41
- values in `orchestration.modelTiers[*].claudeModel` in `.ukit/storage/config.json`.
43
+ default. If this project does not run against UNIC, a maintainer swaps the three cost tiers
44
+ (`smol`/`default`/`slow` — and their `lite`/`code`/`smart` aliases) for the values in
45
+ `orchestration.modelTiers[*].claudeModel` in `.ukit/storage/config.json`.
42
46
 
43
47
  `vision` is the exception and stays `unic-vision` either way: it is a *capability* lane, not a cost
44
48
  tier. `unic-code` and `unic-smart` cannot read images on this gateway, so substituting one of them
@@ -40,12 +40,12 @@ work really is, read the matching `SKILL.md` without being asked. Users never na
40
40
  ## 6. Delegate to bind a model tier
41
41
 
42
42
  Your own model does not change mid-turn. A tier only applies when work is handed to a task-agent in
43
- `.omp/agents/`, whose `model:` field (`@lite` / `@code` / `@smart` / `@vision`) resolves through
43
+ `.omp/agents/`, whose `model:` field (`@smol` / `@default` / `@slow` / `@vision`) resolves through
44
44
  `modelRoles` in `.omp/config.yml`.
45
45
 
46
- - `tiny-fix` → `@lite` · `local-fix`, `local-build`, `shared-edit`, `find-cause`, `map-impact` →
47
- `@code` · `review-release` → `@smart`
48
- - Images: `@vision` only. `@code`/`@smart` cannot see images on the UNIC gateway and must never
46
+ - `tiny-fix` → `@smol` · `local-fix`, `local-build`, `shared-edit`, `find-cause`, `map-impact` →
47
+ `@default` · `review-release` → `@slow`
48
+ - Images: `@vision` only. `@default`/`@slow` cannot see images on the UNIC gateway and must never
49
49
  guess at their contents — hand every image to `ukit-vision-analyst` first.
50
50
 
51
51
  Doing everything inline is exactly what makes UKit look like it only has one model. Keep direct
@@ -73,5 +73,6 @@ last thing you emit is one short line naming what is unfinished and what you nee
73
73
  a status — the user cannot distinguish it from a crash.
74
74
 
75
75
  > Maintainer note, not a per-turn rule: `modelRoles` in `.omp/config.yml` ships UNIC gateway names.
76
- > On a non-UNIC provider, edit only the three cost tiers — `lite`, `code`, `smart` — never `vision`,
77
- > which stays `unic-vision` because it is a capability lane, not a cost tier.
76
+ > On a non-UNIC provider, edit only the three cost tiers — `smol`, `default`, `slow` — never `vision`,
77
+ > which stays `unic-vision` (capability lane, not a cost tier). Old keys `lite`/`code`/`smart` remain
78
+ > as compat aliases — edit each alias alongside its tier (smol↔lite, default↔code, slow↔smart).
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: bug-debugger
3
3
  description: "Debugging specialist for reproducible errors, failing tests, and unexpected behavior. Use proactively when investigation will involve noisy logs, stack traces, or a self-contained reproduce-trace-fix-verify loop. Do not use for trivial obvious fixes or broad architecture ideation."
4
- model: "@code"
4
+ model: "@default"
5
5
  tools: ["read","grep","glob","bash","edit","ast_edit"]
6
6
  ---
7
7
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: code-reviewer
3
3
  description: "Independent reviewer for handoff Phase 3, for spec/plan documents, and for non-blocking sidecar diff review of daily-flow edits. For code (default): use after executor reports STATUS: DONE on a handoff task, MUST run with a model different from the executor (configured in .ukit/storage/config.json → handoff.reviewer.model, default unic-smart), produces a verdict: APPROVED | APPROVED-WITH-MINOR | CHANGES-REQUESTED | CRITICAL. For spec/plan documents (set REVIEW_TARGET_TYPE=spec or plan): reviews a docs/plans/*.md file for completeness/consistency/clarity/scope/YAGNI, produces Status: Approved | Issues Found. For sidecar diff review (set REVIEW_TARGET_TYPE=diff): reviews the current uncommitted git diff after a local-build/shared-edit task, runs in the background and never blocks the main task, produces STATUS: clean | issues-found."
4
- model: "@smart"
4
+ model: "@slow"
5
5
  tools: ["read","grep","glob","bash"]
6
6
  ---
7
7
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: feature-implementer
3
3
  description: "Implementation specialist for clear, self-contained coding tasks. Use proactively when the approach is clear and the work can be completed in a bounded pass with a concise summary. Do not use for trivial one-file tweaks or tightly coupled exploratory work."
4
- model: "@code"
4
+ model: "@default"
5
5
  tools: ["read","edit","write","ast_edit","grep","glob","bash"]
6
6
  ---
7
7
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: handoff-planner
3
3
  description: "Handoff planning specialist for Phase 1+2. Use when creating a new handoff cycle: writes PLAN.md with full test plan, splits into TASK-xxx.md files with TDD-embedded test cases, and updates INDEX.md. Always use the strongest available model (Opus/unic-smart)."
4
- model: "@smart"
4
+ model: "@slow"
5
5
  tools: ["read","edit","write","ast_edit","glob","bash"]
6
6
  ---
7
7
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ukit-small-task-maintainer
3
3
  description: "Internal UKit maintenance subagent for low-risk, reversible UKit decisions. Use proactively when UKit needs to decide or perform safe cleanup such as pruning docs/TASKS.md, classifying queued work, choosing whether compact/summarization is appropriate, summarizing local docs/status, or maintaining small UKit runtime queues. Do not use for product implementation, security, release/publish, data-loss, architecture, or risky/shared code changes."
4
- model: "@lite"
4
+ model: "@smol"
5
5
  tools: ["read","grep","glob","edit","write","ast_edit"]
6
6
  blocking: false
7
7
  ---
@@ -11,7 +11,7 @@ You are UKit's internal small-task maintainer. You run as a sidecar/parallel/non
11
11
  ## Model Policy
12
12
 
13
13
  - Use the model selected by `subagents.smallTaskModel` when the host supports model selection for this subagent.
14
- - Default intended model: `unic-lite`.
14
+ - Default intended model: `unic-lite` (frontmatter `@smol` resolves to `unic-lite` via `.omp/config.yml` modelRoles).
15
15
  - If the host cannot bind a model from config directly, still follow this role and report that the configured model is a hint.
16
16
  - This lane must run separately from the user's main task model. It must never replace, pause, or slow down the main task.
17
17
 
@@ -2,23 +2,56 @@
2
2
  # models may change during development; orchestration must not branch on vendor names.
3
3
  # Do NOT substitute sonnet/opus/haiku here. See PLAN.md §3 D15.
4
4
  #
5
- # Non-UNIC omp provider? A maintainer edits the three cost tiers to the values in
6
- # orchestration.modelTiers[*].claudeModel (.ukit/storage/config.json) — currently
7
- # lite: claude-haiku-4-5, code: claude-sonnet-5, smart: claude-opus-5.
5
+ # Non-UNIC omp provider? A maintainer edits the three cost tiers — smol, default, slow —
6
+ # to the values in orchestration.modelTiers[*].claudeModel (.ukit/storage/config.json) —
7
+ # currently lite: claude-haiku-4-5, code: claude-sonnet-5, smart: claude-opus-5.
8
8
  # `vision` STAYS unic-vision: its claudeModel is already unic-vision, because
9
9
  # unic-code/unic-smart cannot read images on this gateway. claude-sonnet-5 is only
10
10
  # modelTiers.vision.fallbackModel, used when unicMode is off — never a drop-in here.
11
11
  modelRoles:
12
+ smol: unic-lite
13
+ default: unic-code
14
+ slow: unic-smart
15
+ vision: unic-vision
16
+ # Back-compat aliases — INDEPENDENT keys, not references. A maintainer overriding a
17
+ # cost tier above must edit the matching alias too (smol↔lite, default↔code,
18
+ # slow↔smart), or the alias keeps resolving to the old unic-* value.
12
19
  lite: unic-lite
13
20
  code: unic-code
14
21
  smart: unic-smart
15
- vision: unic-vision
16
22
 
17
23
  tools:
18
- approvalMode: write
24
+ # TASK-009 / SPEC FR-003: the unattended approval surface is pinned HERE —
25
+ # `approvalMode: yolo` plus all ten `tools.approval.*: allow`. The product
26
+ # source of truth is `orchestration.permissionMode: unattended`
27
+ # (.ukit/storage/config.json, written by TASK-008); this map is its omp-side
28
+ # rendering so installed projects run prompt-free out of the box.
29
+ # This SUPERSEDES the TASK-006/C34 omission decision (approvalMode left absent
30
+ # so the end user's global/runtime mode won): an interactive global would
31
+ # silently downgrade a shipped install to prompting, contradicting the
32
+ # unattended contract — the project-level pin is now required, not optional.
33
+ # `approvalMode: yolo` VERIFIED against omp v17.4.2 (2026-08-22) — same
34
+ # docContracts allowlist citation as compaction.thresholdTokens below.
35
+ # Safety under yolo is unchanged: the bash.patterns deny set below, the
36
+ # TASK-004 hook-bridge deny chain, and this approval map still gate dangerous
37
+ # ops — `allow` removes interactive prompts, not the deny checks.
38
+ # Residual risk: yolo + all-allow IS dangerously autonomous and is a
39
+ # deliberate, user-chosen posture (unattended mode). `eval` stays `allow`
40
+ # (was `prompt` pre-TASK-001): bash.patterns never covers the eval tool, but
41
+ # the TASK-004 bridge maps `eval` -> `Bash`, so every eval call is gated by
42
+ # the same block-dangerous chain as a bash command.
43
+ approvalMode: yolo
19
44
  approval:
20
45
  bash: allow
21
- eval: prompt
46
+ eval: allow
47
+ task: allow
48
+ read: allow
49
+ grep: allow
50
+ write: allow
51
+ edit: allow
52
+ lsp: allow
53
+ browser: allow
54
+ computer: allow
22
55
 
23
56
  bash:
24
57
  # Translated from templates/.claude/hooks/block-dangerous.sh's DANGEROUS_PATTERNS array.
@@ -27,8 +60,9 @@ bash:
27
60
  # catches it. `allow` only ever matches an ENTIRE, non-compound command, so the trailing "*"
28
61
  # allow is NOT a universal escape hatch: any compound command (`&&`, `;`, `|`) not itself caught
29
62
  # by a `deny`/`prompt` entry falls through to `tools.approvalMode` instead of being auto-allowed.
30
- # `bash.patterns` does not cover the `eval` tool at all — that is why `tools.approval.eval` above
31
- # is `prompt`, and why TASK-004's bridge separately maps `eval` -> `Bash`.
63
+ # `bash.patterns` does not cover the `eval` tool at all — that is why TASK-004's bridge
64
+ # separately maps `eval` -> `Bash`, and why `tools.approval.eval: allow` above does NOT
65
+ # weaken eval safety: eval stays gated by the bridge's Bash chain (TASK-001).
32
66
  patterns:
33
67
  - match: "rm -rf /*"
34
68
  approval: deny
@@ -294,10 +294,18 @@ function translateExecResult(scriptName, execResult) {
294
294
  if (code === 2) {
295
295
  const structured = parseStructuredDecision(stdout);
296
296
  if (structured?.permissionDecision === 'ask') {
297
+ const askBase = structured.reason || stderr || `${scriptName} requires a human decision`;
298
+ // omp has no native `ask` — hook() converts this to a block. A bare
299
+ // "defers to a human" reason dead-ended under YOLO, so the reason must
300
+ // name the cause class + the recovery action and the chain must surface
301
+ // a display:true note (done in runScriptChain) so a deliberate block is
302
+ // distinguishable from a stall.
297
303
  return {
298
304
  block: false,
299
305
  ask: true,
300
- reason: structured.reason || stderr || `${scriptName} requires a human decision`,
306
+ reason: `${askBase} [UKit ask→block: omp has no native "ask", so this gate decision was surfaced as a block. `
307
+ + 'Recovery: if the cause was an oversized or truncated payload, shrink the payload or re-send it; '
308
+ + 'if the gate is asking for a decision, decide explicitly — answer the question and re-send the call.]',
301
309
  stdout,
302
310
  stderr,
303
311
  };
@@ -628,6 +636,9 @@ export async function runScriptChain(
628
636
  return { block: true, reason: verdict.reason, context, invoked };
629
637
  }
630
638
  if (verdict.ask) {
639
+ // The block must be user-visible, not just model-visible — a deliberate
640
+ // ask→block has to be distinguishable from a silent stall.
641
+ sendContext(pi, [`[UKit] Gate asks for a human decision — the call was blocked: ${verdict.reason}`], 'nextTurn', { display: true });
631
642
  return { block: false, ask: true, reason: verdict.reason, context, invoked };
632
643
  }
633
644
  }
@@ -26,6 +26,14 @@
26
26
  <!-- RULE: EXEC-04 -->
27
27
  - **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.
28
28
 
29
+ ## Stall & Wait Reporting
30
+ <!-- RULE: STALL-01 -->
31
+ - 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.
32
+ <!-- RULE: STALL-02 -->
33
+ - Every stop still says why (Execution Contract EXEC-04) — the stall rules above extend it, they do not replace it.
34
+ <!-- RULE: STALL-03 -->
35
+ - **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.
36
+
29
37
  ## Long-Run Continuity
30
38
  <!-- RULES: LONG-01 LONG-02 -->
31
39
  - 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.
@@ -69,8 +77,8 @@ For any task needing code context:
69
77
 
70
78
  ## UKit v{{ukit.version}} Shared Runtime
71
79
  - Runtime state lives in `.ukit/storage/`; `.ukit/storage/config.json` holds runtime toggles (compact, token pipeline, router, memory, validation, Safe Patch).
72
- - Reuse `.ukit/storage/memory/` + `ukit memory recall "<current task>"` before asking users to restate decisions; inspect via `ukit status` / `ukit memory export`.
73
- - Route memory: `.claude/ukit/skill-router-state.json` — reuse compact `previous-context`/`recent-output` first. Cache state: `.ukit/storage/cache/output-history.json`, tee/. Missing/corrupt runtime or old `ukit/` root → rerun `ukit install`. Detail: `docs/UKIT_INTERNALS.md`.
80
+ - 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`.
81
+ - 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`.
74
82
 
75
83
  ## Prompt Caching
76
84
  <!-- RULES: CTX-01 CTX-02 CTX-03 CTX-04 CTX-05 CTX-06 CTX-07 CTX-08 CTX-09 CTX-10 -->
@@ -84,9 +92,7 @@ For any task needing code context:
84
92
 
85
93
  ## Handoff Quality Gate — OPT-IN
86
94
  <!-- RULE: HAND-01 -->
87
- 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.
88
-
89
- 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.*`.
95
+ 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.*`.
90
96
 
91
97
  ## Context + Verification Budget
92
98
  <!-- RULE: BUDGET-01 -->
@@ -99,14 +105,10 @@ Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+P
99
105
  - `docs/STATUS.md` captures compact current state — not source truth, never replaces source/index-first investigation.
100
106
  - "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`.
101
107
 
102
- ## Small-Task Maintainer (internal)
108
+ ## Subagent Lanes (internal)
103
109
  <!-- RULE: SUBAG-02 -->
104
110
  - 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`.
105
-
106
- ## Post-Edit Sidecar Review (internal)
107
111
  - 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`.
108
-
109
- ## Selective Subagent Policy (internal only)
110
112
  <!-- RULE: SUBAG-01 -->
111
113
  - 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.
112
114
 
@@ -114,6 +116,16 @@ Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+P
114
116
  <!-- RULE: AUTO-01 -->
115
117
  - `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.
116
118
 
119
+ ## Unattended Completion Loop
120
+ <!-- RULE: UNATTENDED-01 -->
121
+ - 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.
122
+ <!-- RULE: UNATTENDED-02 -->
123
+ - `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.
124
+ <!-- RULE: UNATTENDED-03 -->
125
+ - 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.
126
+ <!-- RULE: UNATTENDED-04 -->
127
+ - 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.
128
+
117
129
  ## 3-Tier Model Routing
118
130
  <!-- RULES: TIER-01 TIER-02 -->
119
131
  **Internal orchestration only — end users still just use natural language. No new commands.**
@@ -124,7 +136,7 @@ Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+P
124
136
  | code | `unic-code` | claude-sonnet | Normal coding, local fixes, shared edits, builds, debugging, impact mapping |
125
137
  | smart | `unic-smart` | claude-opus | Release review/audit, escalated deep reasoning after repeated failure |
126
138
 
127
- - A tier takes effect only when work is handed to an agent whose definition binds that model (`model:` frontmatter in `.claude/agents/*.md`; `model:` `@lite`/`@code`/`@smart`/`@vision` in `.omp/agents/*.md` via `modelRoles`) — the main session model never changes mid-turn.
139
+ - 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.
128
140
  - 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`.
129
141
  - `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`.
130
142
 
@@ -26,6 +26,14 @@
26
26
  <!-- RULE: EXEC-04 -->
27
27
  - **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.
28
28
 
29
+ ## Stall & Wait Reporting
30
+ <!-- RULE: STALL-01 -->
31
+ - 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.
32
+ <!-- RULE: STALL-02 -->
33
+ - Every stop still says why (Execution Contract EXEC-04) — the stall rules above extend it, they do not replace it.
34
+ <!-- RULE: STALL-03 -->
35
+ - **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.
36
+
29
37
  ## Long-Run Continuity
30
38
  <!-- RULES: LONG-01 LONG-02 -->
31
39
  - 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.
@@ -69,8 +77,8 @@ For any task needing code context:
69
77
 
70
78
  ## UKit v{{ukit.version}} Shared Runtime
71
79
  - Runtime state lives in `.ukit/storage/`; `.ukit/storage/config.json` holds runtime toggles (compact, token pipeline, router, memory, validation, Safe Patch).
72
- - Reuse `.ukit/storage/memory/` + `ukit memory recall "<current task>"` before asking users to restate decisions; inspect via `ukit status` / `ukit memory export`.
73
- - Route memory: `.claude/ukit/skill-router-state.json` — reuse compact `previous-context`/`recent-output` first. Cache state: `.ukit/storage/cache/output-history.json`, tee/. Missing/corrupt runtime or old `ukit/` root → rerun `ukit install`. Detail: `docs/UKIT_INTERNALS.md`.
80
+ - 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`.
81
+ - 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`.
74
82
 
75
83
  ## Prompt Caching
76
84
  <!-- RULES: CTX-01 CTX-02 CTX-03 CTX-04 CTX-05 CTX-06 CTX-07 CTX-08 CTX-09 CTX-10 -->
@@ -84,9 +92,7 @@ For any task needing code context:
84
92
 
85
93
  ## Handoff Quality Gate — OPT-IN
86
94
  <!-- RULE: HAND-01 -->
87
- 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.
88
-
89
- 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.*`.
95
+ 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.*`.
90
96
 
91
97
  ## Context + Verification Budget
92
98
  <!-- RULE: BUDGET-01 -->
@@ -99,14 +105,10 @@ Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+P
99
105
  - `docs/STATUS.md` captures compact current state — not source truth, never replaces source/index-first investigation.
100
106
  - "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`.
101
107
 
102
- ## Small-Task Maintainer (internal)
108
+ ## Subagent Lanes (internal)
103
109
  <!-- RULE: SUBAG-02 -->
104
110
  - 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`.
105
-
106
- ## Post-Edit Sidecar Review (internal)
107
111
  - 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`.
108
-
109
- ## Selective Subagent Policy (internal only)
110
112
  <!-- RULE: SUBAG-01 -->
111
113
  - 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.
112
114
 
@@ -114,6 +116,16 @@ Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+P
114
116
  <!-- RULE: AUTO-01 -->
115
117
  - `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.
116
118
 
119
+ ## Unattended Completion Loop
120
+ <!-- RULE: UNATTENDED-01 -->
121
+ - 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.
122
+ <!-- RULE: UNATTENDED-02 -->
123
+ - `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.
124
+ <!-- RULE: UNATTENDED-03 -->
125
+ - 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.
126
+ <!-- RULE: UNATTENDED-04 -->
127
+ - 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.
128
+
117
129
  ## 3-Tier Model Routing
118
130
  <!-- RULES: TIER-01 TIER-02 -->
119
131
  **Internal orchestration only — end users still just use natural language. No new commands.**
@@ -124,7 +136,7 @@ Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+P
124
136
  | code | `unic-code` | claude-sonnet | Normal coding, local fixes, shared edits, builds, debugging, impact mapping |
125
137
  | smart | `unic-smart` | claude-opus | Release review/audit, escalated deep reasoning after repeated failure |
126
138
 
127
- - A tier takes effect only when work is handed to an agent whose definition binds that model (`model:` frontmatter in `.claude/agents/*.md`; `model:` `@lite`/`@code`/`@smart`/`@vision` in `.omp/agents/*.md` via `modelRoles`) — the main session model never changes mid-turn.
139
+ - 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.
128
140
  - 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`.
129
141
  - `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`.
130
142
 
@@ -1 +1 @@
1
- {"$schema":"https://opencode.ai/config.json","default_agent":"build","share":"disabled","compaction":{"auto":true,"prune":true,"reserved":10000},"watcher":{"ignore":[".git/**","node_modules/**",".cache/**",".ukit/**",".claude/ukit/permission-usage.json",".claude/ukit/permission-audit.log"]},"permission":{"doom_loop":"deny"},"command":{"ukit-route":{"description":"Internal shared UKit route. Run at the start of every non-trivial task to get skill and context hints before writing code.","agent":"build","template":"Run `node .claude/ukit/index/route-task.mjs \"<task>\" --adapter opencode`; reuse `.claude/ukit/skill-router-state.json`."},"ukit-context":{"description":"Internal UKit context.","agent":"build","template":"Run `node .claude/ukit/index/resolve-context.mjs \"<intent>\" [--target <file>]`."},"ukit-verify":{"description":"Internal UKit verify lane.","agent":"build","template":"Run `node .claude/ukit/index/verify-context.mjs \"<intent>\" [--target <file>]`."},"ukit-triage":{"description":"Internal UKit triage.","agent":"build","template":"Run `node .claude/ukit/index/triage.mjs \"<error>\"`."},"ukit-query":{"description":"Internal UKit query.","agent":"build","template":"Run `node .claude/ukit/index/query-index.mjs \"<error|symbol|path>\"`."},"ukit-index":{"description":"Internal UKit index.","agent":"build","template":"Run `node .claude/ukit/index/refresh-index.mjs` (fallback: `node .claude/ukit/index/build-index.mjs`)."},"ukit-handoff-status":{"description":"Handoff dashboard — show current cycle status (read-only).","agent":"build","template":"Read `docs/AI_HANDOFF/INDEX.md`, `docs/AI_HANDOFF/ACTIVE.md`, and `docs/AI_HANDOFF/PLAN.md`. Report: active cycle name, task table with status, any blockers. No writes."},"ukit-handoff-create":{"description":"Create a new handoff cycle — Phase 1+2: write PLAN.md + TASK-xxx.md files.","agent":"build","template":"Read `.claude/commands/ukit/create-handoff.md` for full instructions, then execute. Description: <what to build>"},"ukit-handoff-implement":{"description":"Execute handoff tasks — Phase 3: implement the next Ready task.","agent":"build","template":"Read `.claude/commands/ukit/implement-handoff.md` for full instructions, then execute. Task ID (optional): <TASK-xxx>"},"ukit-handoff-review":{"description":"Review handoff results — Phase 4: verify implementation and give verdict.","agent":"build","template":"Read `.claude/commands/ukit/review-handoff.md` for full instructions, then execute. Task ID (optional): <TASK-xxx>"},"ukit-handoff-clear":{"description":"Archive and reset the current handoff cycle.","agent":"build","template":"Read `.claude/commands/ukit/clear-handoff.md` for full instructions, then execute."}},"agent":{"build":{"description":"UKit build agent. Follow AGENTS.md. For every non-trivial task: run /ukit-route first, use index-first loop, activate matching skill, never claim done after read-only steps. Keep internal ukit-* helpers hidden; users only need ukit install.","permission":{"edit":"allow","task":"allow","skill":"allow","bash":{"*":"ask","pwd":"allow","ls":"allow","ls *":"allow","find *":"allow","rg *":"allow","grep *":"allow","cat *":"allow","sed *":"allow","head *":"allow","tail *":"allow","wc *":"allow","echo *":"allow","printf *":"allow","awk *":"allow","tr *":"allow","cut *":"allow","sort *":"allow","uniq *":"allow","diff *":"allow","jq *":"allow","stat *":"allow","file *":"allow","which *":"allow","date *":"allow","basename *":"allow","dirname *":"allow","realpath *":"allow","xargs *":"allow","mkdir *":"allow","touch *":"allow","cp *":"allow","vitest *":"allow","jest *":"allow","git status":"allow","git status *":"allow","git diff":"allow","git diff *":"allow","git log":"allow","git log *":"allow","git show *":"allow","git grep *":"allow","git rev-parse *":"allow","git branch *":"allow","git stash list":"allow","git ls-files *":"allow","git tag *":"allow","node .claude/ukit/index/*":"allow","node .claude/ukit/runtime/*":"allow","{{runtime.packageManager}} test":"allow","{{runtime.packageManager}} test *":"allow","{{runtime.packageManager}} lint":"allow","{{runtime.packageManager}} lint *":"allow","{{runtime.packageManager}} typecheck":"allow","{{runtime.packageManager}} typecheck *":"allow","{{runtime.packageManager}} build":"allow","{{runtime.packageManager}} build *":"allow","npm run test":"allow","npm run test *":"allow","npm run lint":"allow","npm run lint *":"allow","npm run typecheck":"allow","npm run typecheck *":"allow","npm run build":"allow","npm run build *":"allow","pnpm test":"allow","pnpm test *":"allow","pnpm lint":"allow","pnpm lint *":"allow","pnpm typecheck":"allow","pnpm typecheck *":"allow","pnpm build":"allow","pnpm build *":"allow","pnpm run test":"allow","pnpm run test *":"allow","pnpm run lint":"allow","pnpm run lint *":"allow","pnpm run typecheck":"allow","pnpm run typecheck *":"allow","pnpm run build":"allow","pnpm run build *":"allow","bun test":"allow","bun test *":"allow","bun run test":"allow","bun run test *":"allow","bun run lint":"allow","bun run lint *":"allow","bun run typecheck":"allow","bun run typecheck *":"allow","bun run build":"allow","bun run build *":"allow","git commit":"ask","git commit *":"ask","git push":"ask","git push *":"ask","git clean":"deny","git clean *":"deny","git reset":"deny","git reset *":"deny","rm *":"deny"}}},"plan":{"permission":{"edit":"ask","bash":"ask"}}}}
1
+ {"$schema":"https://opencode.ai/config.json","default_agent":"build","share":"disabled","compaction":{"auto":true,"prune":true,"reserved":10000},"watcher":{"ignore":[".git/**","node_modules/**",".cache/**",".ukit/**",".claude/ukit/permission-usage.json",".claude/ukit/permission-audit.log"]},"permission":{"doom_loop":"deny"},"command":{"ukit-route":{"description":"Internal shared UKit route. Run at the start of every non-trivial task to get skill and context hints before writing code.","agent":"build","template":"Run `node .claude/ukit/index/route-task.mjs \"<task>\" --adapter opencode`; reuse `.claude/ukit/skill-router-state.json`."},"ukit-context":{"description":"Internal UKit context.","agent":"build","template":"Run `node .claude/ukit/index/resolve-context.mjs \"<intent>\" [--target <file>]`."},"ukit-verify":{"description":"Internal UKit verify lane.","agent":"build","template":"Run `node .claude/ukit/index/verify-context.mjs \"<intent>\" [--target <file>]`."},"ukit-triage":{"description":"Internal UKit triage.","agent":"build","template":"Run `node .claude/ukit/index/triage.mjs \"<error>\"`."},"ukit-query":{"description":"Internal UKit query.","agent":"build","template":"Run `node .claude/ukit/index/query-index.mjs \"<error|symbol|path>\"`."},"ukit-index":{"description":"Internal UKit index.","agent":"build","template":"Run `node .claude/ukit/index/refresh-index.mjs` (fallback: `node .claude/ukit/index/build-index.mjs`)."},"ukit-handoff-status":{"description":"Handoff dashboard — show current cycle status (read-only).","agent":"build","template":"Read `docs/AI_HANDOFF/INDEX.md`, `docs/AI_HANDOFF/ACTIVE.md`, and `docs/AI_HANDOFF/PLAN.md`. Report: active cycle name, task table with status, any blockers. No writes."},"ukit-handoff-create":{"description":"Create a new handoff cycle — Phase 1+2: write PLAN.md + TASK-xxx.md files.","agent":"build","template":"Read `.claude/commands/ukit/create-handoff.md` for full instructions, then execute. Description: <what to build>"},"ukit-handoff-implement":{"description":"Execute handoff tasks — Phase 3: implement the next Ready task.","agent":"build","template":"Read `.claude/commands/ukit/implement-handoff.md` for full instructions, then execute. Task ID (optional): <TASK-xxx>"},"ukit-handoff-review":{"description":"Review handoff results — Phase 4: verify implementation and give verdict.","agent":"build","template":"Read `.claude/commands/ukit/review-handoff.md` for full instructions, then execute. Task ID (optional): <TASK-xxx>"},"ukit-handoff-clear":{"description":"Archive and reset the current handoff cycle.","agent":"build","template":"Read `.claude/commands/ukit/clear-handoff.md` for full instructions, then execute."}},"agent":{"build":{"description":"UKit build agent. Follow AGENTS.md. For every non-trivial task: run /ukit-route first, use index-first loop, activate matching skill, never claim done after read-only steps. Keep internal ukit-* helpers hidden; users only need ukit install.","permission":{"edit":"allow","task":"allow","skill":"allow","bash":{"*":"ask","pwd":"allow","ls":"allow","ls *":"allow","find *":"allow","rg *":"allow","grep *":"allow","cat *":"allow","sed *":"allow","head *":"allow","tail *":"allow","wc *":"allow","echo *":"allow","printf *":"allow","awk *":"allow","tr *":"allow","cut *":"allow","sort *":"allow","uniq *":"allow","diff *":"allow","jq *":"allow","stat *":"allow","file *":"allow","which *":"allow","date *":"allow","basename *":"allow","dirname *":"allow","realpath *":"allow","xargs *":"allow","mkdir *":"allow","touch *":"allow","cp *":"allow","vitest *":"allow","jest *":"allow","git status":"allow","git status *":"allow","git diff":"allow","git diff *":"allow","git log":"allow","git log *":"allow","git show *":"allow","git grep *":"allow","git rev-parse *":"allow","git branch *":"allow","git stash list":"allow","git ls-files *":"allow","git tag *":"allow","git add *":"allow","git checkout *":"allow","git switch *":"allow","git restore *":"allow","git mv *":"allow","mv *":"allow","node *":"allow","node .claude/ukit/index/*":"allow","node .claude/ukit/runtime/*":"allow","npx *":"allow","npm test":"allow","npm test *":"allow","{{runtime.packageManager}} test":"allow","{{runtime.packageManager}} test *":"allow","{{runtime.packageManager}} lint":"allow","{{runtime.packageManager}} lint *":"allow","{{runtime.packageManager}} typecheck":"allow","{{runtime.packageManager}} typecheck *":"allow","{{runtime.packageManager}} build":"allow","{{runtime.packageManager}} build *":"allow","npm run test":"allow","npm run test *":"allow","npm run lint":"allow","npm run lint *":"allow","npm run typecheck":"allow","npm run typecheck *":"allow","npm run build":"allow","npm run build *":"allow","pnpm test":"allow","pnpm test *":"allow","pnpm lint":"allow","pnpm lint *":"allow","pnpm typecheck":"allow","pnpm typecheck *":"allow","pnpm build":"allow","pnpm build *":"allow","pnpm run test":"allow","pnpm run test *":"allow","pnpm run lint":"allow","pnpm run lint *":"allow","pnpm run typecheck":"allow","pnpm run typecheck *":"allow","pnpm run build":"allow","pnpm run build *":"allow","bun test":"allow","bun test *":"allow","bun run test":"allow","bun run test *":"allow","bun run lint":"allow","bun run lint *":"allow","bun run typecheck":"allow","bun run typecheck *":"allow","bun run build":"allow","bun run build *":"allow","git commit":"allow","git commit *":"allow","git push":"allow","git push *":"allow","git clean":"deny","git clean *":"deny","git reset":"deny","git reset *":"deny","rm *":"deny"}}},"plan":{"permission":{"edit":"ask","bash":"ask"}}}}
@@ -179,7 +179,7 @@ whose own definition binds that model.
179
179
  | Harness | Agent definitions | How to launch one |
180
180
  |---------|-------------------|-------------------|
181
181
  | Claude Code | `.claude/agents/*.md` (`model:` frontmatter) | Agent tool, `subagent_type: "<name>"` |
182
- | omp | `.omp/agents/*.md` (`model: "@lite"` / `"@code"` / `"@smart"` / `"@vision"`, resolved through `modelRoles` in `.omp/config.yml`) | task-agent `<name>` |
182
+ | omp | `.omp/agents/*.md` (`model: "@smol"` / `"@default"` / `"@slow"` / `"@vision"`, resolved through `modelRoles` in `.omp/config.yml`) | task-agent `<name>` |
183
183
 
184
184
  When a task's contract maps to a tier other than the current session model, hand it to the
185
185
  matching agent instead of doing it inline. Doing everything inline is exactly what makes
@@ -23,6 +23,14 @@
23
23
  <!-- RULE: EXEC-04 -->
24
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.
25
25
 
26
+ ## Stall & Wait Reporting
27
+ <!-- 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.
29
+ <!-- RULE: STALL-02 -->
30
+ - Every stop still says why (Execution Contract EXEC-04) — the stall rules above extend it, they do not replace it.
31
+ <!-- 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.
33
+
26
34
  ## Long-Run Continuity
27
35
  <!-- RULES: LONG-01 LONG-02 -->
28
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.
@@ -66,8 +74,8 @@ For any task needing code context:
66
74
 
67
75
  ## UKit v{{ukit.version}} Shared Runtime
68
76
  - Runtime state lives in `.ukit/storage/`; `.ukit/storage/config.json` holds runtime toggles (compact, token pipeline, router, memory, validation, Safe Patch).
69
- - Reuse `.ukit/storage/memory/` + `ukit memory recall "<current task>"` before asking users to restate decisions; inspect via `ukit status` / `ukit memory export`.
70
- - Route memory: `.claude/ukit/skill-router-state.json` — reuse compact `previous-context`/`recent-output` first. Cache state: `.ukit/storage/cache/output-history.json`, tee/. Missing/corrupt runtime or old `ukit/` root → rerun `ukit install`. Detail: `docs/UKIT_INTERNALS.md`.
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`.
71
79
 
72
80
  ## Prompt Caching
73
81
  <!-- RULES: CTX-01 CTX-02 CTX-03 CTX-04 CTX-05 CTX-06 CTX-07 CTX-08 CTX-09 CTX-10 -->
@@ -81,9 +89,7 @@ For any task needing code context:
81
89
 
82
90
  ## Handoff Quality Gate — OPT-IN
83
91
  <!-- RULE: HAND-01 -->
84
- 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.
85
-
86
- 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.*`.
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.*`.
87
93
 
88
94
  ## Context + Verification Budget
89
95
  <!-- RULE: BUDGET-01 -->
@@ -96,14 +102,10 @@ Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+P
96
102
  - `docs/STATUS.md` captures compact current state — not source truth, never replaces source/index-first investigation.
97
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`.
98
104
 
99
- ## Small-Task Maintainer (internal)
105
+ ## Subagent Lanes (internal)
100
106
  <!-- RULE: SUBAG-02 -->
101
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`.
102
-
103
- ## Post-Edit Sidecar Review (internal)
104
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`.
105
-
106
- ## Selective Subagent Policy (internal only)
107
109
  <!-- RULE: SUBAG-01 -->
108
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.
109
111
 
@@ -111,6 +113,16 @@ Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+P
111
113
  <!-- RULE: AUTO-01 -->
112
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.
113
115
 
116
+ ## Unattended Completion Loop
117
+ <!-- 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.
119
+ <!-- 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.
121
+ <!-- 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.
123
+ <!-- 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.
125
+
114
126
  ## 3-Tier Model Routing
115
127
  <!-- RULES: TIER-01 TIER-02 -->
116
128
  **Internal orchestration only — end users still just use natural language. No new commands.**
@@ -121,7 +133,7 @@ Khi Handoff mode: đọc `docs/AI_HANDOFF/RULES.md` để biết 4 phase (Idea+P
121
133
  | code | `unic-code` | claude-sonnet | Normal coding, local fixes, shared edits, builds, debugging, impact mapping |
122
134
  | smart | `unic-smart` | claude-opus | Release review/audit, escalated deep reasoning after repeated failure |
123
135
 
124
- - A tier takes effect only when work is handed to an agent whose definition binds that model (`model:` frontmatter in `.claude/agents/*.md`; `model:` `@lite`/`@code`/`@smart`/`@vision` in `.omp/agents/*.md` via `modelRoles`) — the main session model never changes mid-turn.
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.
125
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`.
126
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`.
127
139
 
@@ -14,6 +14,7 @@ outputs:
14
14
  - { from: core, heading: Core Rule }
15
15
  - { from: core, heading: Fast Classification }
16
16
  - { from: core, heading: Execution Contract (mandatory) }
17
+ - { from: core, heading: Stall & Wait Reporting }
17
18
  - { from: core, heading: Long-Run Continuity }
18
19
  - { from: core, heading: Index-First Loop }
19
20
  - { from: core, heading: Automatic Skill Activation (mandatory) }
@@ -25,10 +26,9 @@ outputs:
25
26
  - { from: core, heading: Handoff Quality Gate — OPT-IN }
26
27
  - { from: core, heading: Context + Verification Budget }
27
28
  - { from: core, heading: Living Status Workflow }
28
- - { from: core, heading: Small-Task Maintainer (internal) }
29
- - { from: core, heading: Post-Edit Sidecar Review (internal) }
30
- - { from: core, heading: Selective Subagent Policy (internal only) }
29
+ - { from: core, heading: Subagent Lanes (internal) }
31
30
  - { from: core, heading: Adaptive Autonomy }
31
+ - { from: core, heading: Unattended Completion Loop }
32
32
  - { from: core, heading: 3-Tier Model Routing }
33
33
  - { from: core, heading: Skills }
34
34
  - { from: core, heading: Project Snapshot }
@@ -46,6 +46,7 @@ outputs:
46
46
  - { from: core, heading: Core Rule }
47
47
  - { from: core, heading: Fast Classification }
48
48
  - { from: core, heading: Execution Contract (mandatory) }
49
+ - { from: core, heading: Stall & Wait Reporting }
49
50
  - { from: core, heading: Long-Run Continuity }
50
51
  - { from: core, heading: Index-First Loop }
51
52
  - { from: core, heading: Automatic Skill Activation (mandatory) }
@@ -57,10 +58,9 @@ outputs:
57
58
  - { from: core, heading: Handoff Quality Gate — OPT-IN }
58
59
  - { from: core, heading: Context + Verification Budget }
59
60
  - { from: core, heading: Living Status Workflow }
60
- - { from: core, heading: Small-Task Maintainer (internal) }
61
- - { from: core, heading: Post-Edit Sidecar Review (internal) }
62
- - { from: core, heading: Selective Subagent Policy (internal only) }
61
+ - { from: core, heading: Subagent Lanes (internal) }
63
62
  - { from: core, heading: Adaptive Autonomy }
63
+ - { from: core, heading: Unattended Completion Loop }
64
64
  - { from: core, heading: 3-Tier Model Routing }
65
65
  - { from: 'overlay:agents', heading: Session Start — OpenCode }
66
66
  - { from: 'overlay:agents', heading: Project Owner Instructions — Codex and OpenCode }
@@ -88,6 +88,7 @@ outputs:
88
88
  - { from: core, heading: Core Rule }
89
89
  - { from: core, heading: Fast Classification }
90
90
  - { from: core, heading: Execution Contract (mandatory) }
91
+ - { from: core, heading: Stall & Wait Reporting }
91
92
  - { from: core, heading: Long-Run Continuity }
92
93
  - { from: core, heading: Index-First Loop }
93
94
  - { from: core, heading: Automatic Skill Activation (mandatory) }
@@ -99,10 +100,9 @@ outputs:
99
100
  - { from: core, heading: Handoff Quality Gate — OPT-IN }
100
101
  - { from: core, heading: Context + Verification Budget }
101
102
  - { from: core, heading: Living Status Workflow }
102
- - { from: core, heading: Small-Task Maintainer (internal) }
103
- - { from: core, heading: Post-Edit Sidecar Review (internal) }
104
- - { from: core, heading: Selective Subagent Policy (internal only) }
103
+ - { from: core, heading: Subagent Lanes (internal) }
105
104
  - { from: core, heading: Adaptive Autonomy }
105
+ - { from: core, heading: Unattended Completion Loop }
106
106
  - { from: core, heading: 3-Tier Model Routing }
107
107
  - { from: core, heading: Skills }
108
108
  - { from: core, heading: Project Snapshot }
@@ -121,6 +121,7 @@ outputs:
121
121
  - { from: core, heading: Core Rule }
122
122
  - { from: core, heading: Fast Classification }
123
123
  - { from: core, heading: Execution Contract (mandatory) }
124
+ - { from: core, heading: Stall & Wait Reporting }
124
125
  - { from: core, heading: Long-Run Continuity }
125
126
  - { from: core, heading: Index-First Loop }
126
127
  - { from: core, heading: Automatic Skill Activation (mandatory) }
@@ -132,10 +133,9 @@ outputs:
132
133
  - { from: core, heading: Handoff Quality Gate — OPT-IN }
133
134
  - { from: core, heading: Context + Verification Budget }
134
135
  - { from: core, heading: Living Status Workflow }
135
- - { from: core, heading: Small-Task Maintainer (internal) }
136
- - { from: core, heading: Post-Edit Sidecar Review (internal) }
137
- - { from: core, heading: Selective Subagent Policy (internal only) }
136
+ - { from: core, heading: Subagent Lanes (internal) }
138
137
  - { from: core, heading: Adaptive Autonomy }
138
+ - { from: core, heading: Unattended Completion Loop }
139
139
  - { from: core, heading: 3-Tier Model Routing }
140
140
  - { from: 'overlay:agents', heading: Session Start — OpenCode }
141
141
  - { from: 'overlay:agents', heading: Project Owner Instructions — Codex and OpenCode }