@ngockhoale/ukit 3.4.29 → 3.4.30

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 (34) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/manifests/documentation.yaml +88 -0
  3. package/package.json +1 -1
  4. package/src/core/permissionPolicy.js +1 -1
  5. package/src/index/buildIndex.js +244 -4
  6. package/src/index/impactContext.js +91 -11
  7. package/src/index/languageTools.js +126 -0
  8. package/src/index/paths.js +5 -1
  9. package/src/index/playbookRegistry.js +108 -9
  10. package/src/index/queryIndex.js +415 -1
  11. package/src/index/routeCatalog.js +1 -1
  12. package/src/index/taskRouting.js +25 -3
  13. package/template_project/.claude/commands/ukit/handoff-create.md +5 -0
  14. package/template_project/.claude/commands/ukit/handoff-fullstack.md +43 -4
  15. package/template_project/.claude/hooks/block-dangerous.mjs +7 -1
  16. package/template_project/.claude/hooks/handoff-model-guard.sh +235 -21
  17. package/template_project/.claude/hooks/record-execution.mjs +23 -0
  18. package/template_project/.claude/hooks/skill-router.sh +105 -7
  19. package/template_project/.claude/settings.json +21 -1
  20. package/template_project/.claude/ukit/index/cleanup-task-worktree.mjs +1 -1
  21. package/template_project/.claude/ukit/index/impact-context.mjs +70 -15
  22. package/template_project/.claude/ukit/index/land-worktree.mjs +2 -2
  23. package/template_project/.claude/ukit/index/lib/index-core.mjs +883 -14
  24. package/template_project/.claude/ukit/index/playbook-registry.mjs +108 -9
  25. package/template_project/.claude/ukit/index/query-index.mjs +100 -7
  26. package/template_project/.claude/ukit/index/route-catalog.mjs +1 -1
  27. package/template_project/.claude/ukit/index/route-task.mjs +208 -31
  28. package/template_project/.claude/ukit/runtime/execution-ledger.mjs +453 -24
  29. package/template_project/.claude/ukit/runtime/handoff-intent.mjs +122 -6
  30. package/template_project/.claude/ukit/runtime/resumable-run.mjs +417 -0
  31. package/template_project/.claude/ukit/runtime/stop-coordinator.mjs +635 -28
  32. package/template_project/.omp/hooks/pre/ukit-bridge.js +32 -4
  33. package/template_user/playbooks/feature-implementation.md +9 -0
  34. package/template_user/playbooks/migration.md +4 -0
@@ -11,6 +11,7 @@ import { fileURLToPath } from 'node:url';
11
11
  import { spawnSync } from 'node:child_process';
12
12
  import {
13
13
  evaluateCompletion,
14
+ resolveStopPhase,
14
15
  evidencePromptKey,
15
16
  incrementContinuation,
16
17
  markNotified,
@@ -47,6 +48,9 @@ export const HOOK_EVENT_MAP = {
47
48
  'handoff-model-guard.sh',
48
49
  'context-hardcap-gate.sh',
49
50
  ],
51
+ // Delegation + multi-file mutation tools. Only the create-scope guard applies: it denies
52
+ // implementation-capable subagents / source writes while a handoff-create session is live.
53
+ 'MultiEdit|NotebookEdit|Agent|Task': ['handoff-model-guard.sh'],
50
54
  Bash: [
51
55
  'auto-allow-bash.sh',
52
56
  'block-dangerous.mjs',
@@ -60,6 +64,8 @@ export const HOOK_EVENT_MAP = {
60
64
  'Read|Grep|Glob': ['record-execution.mjs'],
61
65
  'Edit|Write': ['post-edit-verify.sh', 'record-execution.mjs', 'task-watchdog.sh'],
62
66
  Bash: ['compress-output.sh', 'record-execution.mjs'],
67
+ // Delegation result: releases the per-task execution claim taken by the pre-call guard.
68
+ 'MultiEdit|NotebookEdit|Agent|Task': ['record-execution.mjs'],
63
69
  },
64
70
  before_agent_start: ['sensitive-data-guard.mjs', 'skill-router.sh', 'vision-router.sh', 'context-window-guard.sh'],
65
71
  'session.compacting': ['reinject-context.sh'],
@@ -87,10 +93,26 @@ const TOOL_NAME_MAP = {
87
93
  eval: 'Bash',
88
94
  bash: 'Bash',
89
95
  shell: 'Bash',
96
+ multi_edit: 'MultiEdit',
97
+ multiedit: 'MultiEdit',
98
+ notebook_edit: 'NotebookEdit',
99
+ notebookedit: 'NotebookEdit',
100
+ // omp delegation surface (observed in real omp sessions): `task` = subagent fan-out with
101
+ // input {context, tasks:[{agent,name,task}]}; `vibe_spawn` starts a worker; `hub` with
102
+ // op:'start' launches an external process (see mapToolName's input-aware branch).
103
+ task: 'Task',
104
+ vibe_spawn: 'Task',
105
+ agent: 'Task',
90
106
  };
91
107
 
92
- export function mapToolName(ompToolName) {
108
+ export function mapToolName(ompToolName, input) {
93
109
  const normalized = String(ompToolName ?? '').trim().toLowerCase().replaceAll('-', '_');
110
+ // `hub` multiplexes wait/send/list/... (harmless) and start/restart (spawns a process that is
111
+ // outside every other guard): only the spawning ops are delegation.
112
+ if (normalized === 'hub') {
113
+ const op = String(input?.op ?? '').toLowerCase();
114
+ return op === 'start' || op === 'restart' ? 'Task' : null;
115
+ }
94
116
  return TOOL_NAME_MAP[normalized] ?? null;
95
117
  }
96
118
 
@@ -104,6 +126,9 @@ function matcherGroupFor(claudeToolName) {
104
126
  if (claudeToolName === 'Bash') {
105
127
  return 'Bash';
106
128
  }
129
+ if (claudeToolName === 'MultiEdit' || claudeToolName === 'NotebookEdit' || claudeToolName === 'Agent' || claudeToolName === 'Task') {
130
+ return 'MultiEdit|NotebookEdit|Agent|Task';
131
+ }
107
132
  return null;
108
133
  }
109
134
 
@@ -828,7 +853,7 @@ export async function runToolCall(pi, event, { projectRoot, context: extensionCo
828
853
  };
829
854
  }
830
855
  }
831
- const mappedToolName = mapToolName(rawToolName);
856
+ const mappedToolName = mapToolName(rawToolName, event.input);
832
857
  // An unmapped tool that LOOKS like a file mutation must not sail past the guards — but
833
858
  // hard-blocking it froze the run whenever omp renamed or added a tool, because the model
834
859
  // cannot add a host adapter mapping mid-run and the block had no recovery path. Run the
@@ -857,7 +882,7 @@ export async function runToolCall(pi, event, { projectRoot, context: extensionCo
857
882
  // so a blocked Bash call cannot create a Stop-hook loop.
858
883
  const group = matcherGroupFor(toolName);
859
884
  const bashFailOpenOverride = process.env.UKIT_OMP_BASH_FAIL_OPEN === '1';
860
- const failClosedOnTransportError = group === 'Edit|Write' || (group === 'Bash' && !bashFailOpenOverride);
885
+ const failClosedOnTransportError = group === 'Edit|Write' || group === 'MultiEdit|NotebookEdit|Agent|Task' || (group === 'Bash' && !bashFailOpenOverride);
861
886
  const result = await runScriptChain(pi, scriptsForToolCall(toolName), payload, {
862
887
  projectRoot,
863
888
  failClosedOnTransportError,
@@ -1141,7 +1166,10 @@ export async function runSessionStop(
1141
1166
  const ledger = suppliedLedger ?? await readExecutionLedger(projectRoot, payload) ?? {};
1142
1167
  let evaluation;
1143
1168
  try {
1144
- evaluation = evaluateCompletion({ state, ledger });
1169
+ // Command authority (RC-A): same shared phase signal the Claude Stop path uses, so a
1170
+ // handoff-create/review session is never pushed toward Edit/Write on omp either.
1171
+ const phase = await resolveStopPhase(payload.transcript_path);
1172
+ evaluation = evaluateCompletion({ state, ledger, phase });
1145
1173
  } catch (error) {
1146
1174
  // BUG-C22-05: fail-closed like the shell gate (continue the turn), but only up
1147
1175
  // to the configured consecutive-crash cap — a persistently broken evaluator
@@ -11,6 +11,15 @@ If the user says "new task", re-route — do not treat the message as the next s
11
11
  4. Implement the smallest change satisfying the predicate.
12
12
  5. Verify against the predicate on the real artifact — not "it compiles".
13
13
  6. Widen once: check the impact surface the route named, no broader.
14
+ Reference reuse: when the ask points at an existing surface ("like the Customer
15
+ page", "giống trang X", "same as module Y"), read that surface first and mirror
16
+ its structure — the reference defines the done predicate, not just inspiration.
17
+ Reuse-first: when the ask names an existing function, helper, or pattern
18
+ ("using validation from Z", "dùng hàm có sẵn"), reuse it — extend or wrap
19
+ before writing new logic, and name the reuse in the report.
20
+ Clone: when the ask duplicates a feature ("clone the Customer page", "nhân bản
21
+ tính năng X"), copy the source feature's structure, rename and adapt each
22
+ surface, and verify the clone against the same predicate class as the original.
14
23
  Reply: what changed, the predicate, the evidence it now holds.
15
24
  Ask the human only for: irreversible writes, a genuine preference call no experiment
16
25
  settles, or a real dead end. Everything else: do it, report it.
@@ -15,6 +15,10 @@ If the user says "new task", re-route — do not treat the message as the next s
15
15
  shape; the pin holds.
16
16
  5. Demonstrate rollback on a safe surface — run it or dry-run it and capture the
17
17
  output; then schedule the legacy path for removal — it does not linger.
18
+ SQL discovery: when the move is a database shape change (column, table, view,
19
+ stored procedure — "sửa cột", ALTER/DROP), pin the current schema and row
20
+ counts before writing DDL, draft the change as a verifiable step, and inspect
21
+ the live schema — never assume it matches the declared migrations.
18
22
  Reply: what moved, the verification evidence on the target, the rollback
19
23
  demonstration, and the legacy-path removal plan.
20
24
  Ask the human only for: irreversible writes, a genuine preference call no experiment