@ngockhoale/ukit 1.1.7 → 1.2.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.
@@ -22,11 +22,17 @@ export async function deriveTaskRoute({
22
22
  const normalizedPrompt = String(promptText || '').trim();
23
23
  const normalizedCommand = String(commandText || '').trim();
24
24
  const normalizedTarget = normalizeRelativeFile(absoluteRoot, targetFile);
25
+ const intentMode = deriveIntentMode({
26
+ promptText: normalizedPrompt,
27
+ commandText: normalizedCommand,
28
+ targetFile: normalizedTarget,
29
+ });
25
30
  const activeSkills = await selectActiveSkills({
26
31
  rootDir: absoluteRoot,
27
32
  promptText: normalizedPrompt,
28
33
  commandText: normalizedCommand,
29
34
  targetFile: normalizedTarget,
35
+ intentMode,
30
36
  });
31
37
  const useIndexedContext = shouldUseIndexedContext({
32
38
  activeSkills,
@@ -102,6 +108,7 @@ export async function deriveTaskRoute({
102
108
  targetFile: normalizedTarget,
103
109
  contextIntent,
104
110
  taskType: inferredTaskType,
111
+ intentMode,
105
112
  },
106
113
  contextRecommendation,
107
114
  verificationRecommendation,
@@ -117,6 +124,7 @@ export async function deriveTaskRoute({
117
124
  targetFile: normalizedTarget,
118
125
  contextIntent,
119
126
  taskType: inferredTaskType,
127
+ intentMode,
120
128
  },
121
129
  contextRecommendation,
122
130
  verificationRecommendation,
@@ -167,6 +175,7 @@ export function buildRouteSummary({
167
175
  formatCompactSegment('targets', primaryTargets),
168
176
  formatCompactSegment('tests', relatedTests),
169
177
  formatCompactSegment('styles', styleFiles),
178
+ delegationRecommendation?.hint ? `delegate=${delegationRecommendation.hint}` : null,
170
179
  policyMode ? `policy=${policyMode}` : null,
171
180
  ].filter(Boolean).join(' | ');
172
181
 
@@ -175,6 +184,7 @@ export function buildRouteSummary({
175
184
  fallbackCommands,
176
185
  preferredOrder,
177
186
  policyMode,
187
+ intentMode: routingContext.intentMode ?? null,
178
188
  delegateHint: delegationRecommendation?.hint ?? null,
179
189
  nextActionType: nextAction?.type ?? null,
180
190
  nextActionCommand,
@@ -183,7 +193,7 @@ export function buildRouteSummary({
183
193
  };
184
194
  }
185
195
 
186
- async function selectActiveSkills({ rootDir, promptText, commandText, targetFile }) {
196
+ async function selectActiveSkills({ rootDir, promptText, commandText, targetFile, intentMode = null }) {
187
197
  const routeSignals = {
188
198
  promptRawText: String(promptText || '').toLowerCase(),
189
199
  promptNormalizedText: buildRouteSignalText(promptText),
@@ -194,6 +204,7 @@ async function selectActiveSkills({ rootDir, promptText, commandText, targetFile
194
204
  const scoredEntries = ROUTE_CATALOG
195
205
  .map((entry) => scoreSkillRouteEntry(entry, routeSignals))
196
206
  .filter((entry) => entry.score > 0)
207
+ .filter((entry) => shouldKeepRouteEntryForIntent(entry, intentMode))
197
208
  .sort((a, b) => b.score - a.score || a.order - b.order);
198
209
  const active = [];
199
210
 
@@ -209,6 +220,22 @@ async function selectActiveSkills({ rootDir, promptText, commandText, targetFile
209
220
  return active.map(({ order, ...rest }) => rest);
210
221
  }
211
222
 
223
+ function shouldKeepRouteEntryForIntent(entry, intentMode) {
224
+ if (entry.id === 'next-step' && ['scoped-advice', 'docs-specific'].includes(intentMode)) {
225
+ return false;
226
+ }
227
+
228
+ if (entry.id === 'update-status' && intentMode === 'docs-specific') {
229
+ return false;
230
+ }
231
+
232
+ if (entry.id === 'docs-quality' && ['open-ended-status', 'status-update'].includes(intentMode)) {
233
+ return false;
234
+ }
235
+
236
+ return true;
237
+ }
238
+
212
239
  function scoreSkillRouteEntry(entry, routeSignals = {}) {
213
240
  let score = 0;
214
241
  const reasons = [];
@@ -282,6 +309,131 @@ function getSignalTexts(signalType, routeSignals = {}) {
282
309
  };
283
310
  }
284
311
 
312
+ function deriveIntentMode({ promptText = '', commandText = '', targetFile = null } = {}) {
313
+ const lower = buildRouteSignalText(promptText, commandText);
314
+ const raw = `${promptText ?? ''}\n${commandText ?? ''}`.toLowerCase();
315
+ const taskQueueNext = hasTaskQueueNextSignal(lower, raw);
316
+ const docsSpecific = hasDocsSpecificTaskSignal(lower, raw, targetFile, { taskQueueNext });
317
+ const statusUpdate = hasStatusUpdateSignal(lower, raw);
318
+ const openEndedStatus = hasOpenEndedStatusSignal(lower, raw) || taskQueueNext;
319
+ const concreteTask = hasConcreteTaskSignal(lower, raw, targetFile, { taskQueueNext });
320
+
321
+ if (docsSpecific) {
322
+ return 'docs-specific';
323
+ }
324
+
325
+ if (statusUpdate) {
326
+ return 'status-update';
327
+ }
328
+
329
+ if (concreteTask && openEndedStatus) {
330
+ return 'scoped-advice';
331
+ }
332
+
333
+ if (openEndedStatus) {
334
+ return 'open-ended-status';
335
+ }
336
+
337
+ if (concreteTask) {
338
+ if (/\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|login|timeout)\b/.test(lower)) {
339
+ return 'debug-specific';
340
+ }
341
+ if (/\b(review|audit|diff|pr feedback|code review|kiem tra|soat)\b/.test(lower)) {
342
+ return 'review-specific';
343
+ }
344
+ if (/\b(implement|build|create|add|ship|deliver|refactor|integrate|integration|scaffold|feature)\b/.test(lower)) {
345
+ return 'implement-specific';
346
+ }
347
+ }
348
+
349
+ return null;
350
+ }
351
+
352
+ function hasStatusUpdateSignal(lower, raw) {
353
+ return /\b(update|refresh|write|sync|record|capture|summarize|summarise).{0,64}\b(status\.md|project status|current state|next candidates|session state)\b/.test(lower)
354
+ || /\b(status\.md|project status).{0,64}\b(update|refresh|write|sync|record|capture|summarize|summarise)\b/.test(lower)
355
+ || /\b(wrap up|handoff|end this session|ending this session|session summary|before final)\b/.test(lower)
356
+ || /\b(cap nhat|ghi lai|tong ket|chot session|ban giao).{0,64}\b(status|trang thai|viec tiep theo)\b/.test(lower)
357
+ || /\b(cập nhật|ghi lại|tổng kết|chốt session|bàn giao).{0,64}\b(status|trạng thái|việc tiếp theo)\b/.test(raw);
358
+ }
359
+
360
+ function hasOpenEndedStatusSignal(lower, raw) {
361
+ return /\b(what next|what is next|what's next|next step|next steps|project status|current status|where are we|continue|continue from last session|roadmap|status\.md|task queue|tasks\.md|next queued task|pick next task|work from tasks)\b/.test(lower)
362
+ || /\b(lam gi tiep|buoc tiep theo|tiep theo lam gi|lam tiep|dang o dau|trang thai project|tinh trang project|task tiep theo|viec tiep theo trong tasks)\b/.test(lower)
363
+ || /\b(làm gì tiếp|bước tiếp theo|tiếp theo làm gì|làm tiếp|đang ở đâu|trạng thái project|tình trạng project|task tiếp theo|việc tiếp theo trong tasks)\b/.test(raw);
364
+ }
365
+
366
+ function hasTaskQueueNextSignal(lower, raw) {
367
+ return /\b(task queue|tasks\.md|next queued task|pick next task|work from tasks|next task from tasks|ready for ai)\b/.test(lower)
368
+ || /\b(task tiếp theo|việc tiếp theo trong tasks|làm task trong tasks|lấy task tiếp theo)\b/.test(raw);
369
+ }
370
+
371
+ function hasConcreteTaskSignal(lower, raw, targetFile, { taskQueueNext = false } = {}) {
372
+ if (targetFile && !isStatusFileTarget(targetFile) && !(taskQueueNext && isTasksFileTarget(targetFile))) {
373
+ return true;
374
+ }
375
+
376
+ return /\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|implement|build|create|add|ship|deliver|refactor|integrate|integration|scaffold|feature|review|audit|diff|pr feedback|code review|auth|login|api|endpoint|test|spec)\b/.test(lower)
377
+ || /\b(sửa|fix|lỗi|bug|debug|implement|cài|thêm|review|kiểm tra|soát|đăng nhập)\b/.test(raw);
378
+ }
379
+
380
+ function hasDocsSpecificTaskSignal(lower, raw, targetFile, { taskQueueNext = false } = {}) {
381
+ if (!targetFile || !isDocsTarget(targetFile)) {
382
+ return /\b(clean tasks|cleanup tasks|prune tasks|dedupe tasks|clear completed tasks|dọn tasks|dọn task)\b/.test(lower)
383
+ || /\b(dọn tasks|dọn task|dọn danh sách task|xóa task đã xong)\b/.test(raw);
384
+ }
385
+
386
+ if (taskQueueNext && isTasksFileTarget(targetFile) && !/\b(clean|cleanup|prune|dedupe|edit|template|wording|format|structure)\b/.test(lower)) {
387
+ return false;
388
+ }
389
+
390
+ const targetName = path.posix.basename(String(targetFile || '').replaceAll('\\', '/')).toLowerCase();
391
+ const explicitStatusUpdate = hasExplicitStatusUpdateSignal(lower, raw);
392
+
393
+ if (!isStatusFileTarget(targetFile)) {
394
+ if (explicitStatusUpdate && !mentionsTargetDoc(lower, targetName)) {
395
+ return false;
396
+ }
397
+
398
+ return mentionsTargetDoc(lower, targetName)
399
+ || /\b(edit|write|improve|document|docs?|readme|changelog|worklog|memory|code map|template|wording|copy|grammar|format|structure|heading|section|handoff notes?)\b/.test(lower)
400
+ || /\b(câu chữ|chỉnh|sửa chữ|ngữ pháp|định dạng|cấu trúc|tài liệu|ghi chú bàn giao)\b/.test(raw);
401
+ }
402
+
403
+ return /\b(template|wording|edit|copy|grammar|format|structure|heading|section|docs?)\b/.test(lower)
404
+ || /\b(mẫu|câu chữ|chỉnh|sửa chữ|ngữ pháp|định dạng|cấu trúc|tài liệu)\b/.test(raw);
405
+ }
406
+
407
+ function hasExplicitStatusUpdateSignal(lower, raw) {
408
+ return /\b(update|refresh|write|sync|record|capture|summarize|summarise).{0,64}\b(status\.md|project status|current state|next candidates|session state)\b/.test(lower)
409
+ || /\b(status\.md|project status).{0,64}\b(update|refresh|write|sync|record|capture|summarize|summarise)\b/.test(lower)
410
+ || /\b(cap nhat|ghi lai|tong ket|chot session|ban giao).{0,64}\b(status|trang thai|viec tiep theo)\b/.test(lower)
411
+ || /\b(cập nhật|ghi lại|tổng kết|chốt session|bàn giao).{0,64}\b(status|trạng thái|việc tiếp theo)\b/.test(raw);
412
+ }
413
+
414
+ function mentionsTargetDoc(lower, targetName) {
415
+ if (!targetName) {
416
+ return false;
417
+ }
418
+
419
+ const escaped = targetName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
420
+ const withoutExt = escaped.replace(/\\\.md$/i, '');
421
+ return new RegExp(`\\b(?:${escaped}|${withoutExt})\\b`, 'i').test(lower);
422
+ }
423
+
424
+ function isStatusFileTarget(targetFile) {
425
+ return /(?:^|\/)docs\/STATUS\.md$|(?:^|\/)STATUS\.md$/i.test(String(targetFile || ''));
426
+ }
427
+
428
+ function isTasksFileTarget(targetFile) {
429
+ return /(?:^|\/)docs\/TASKS\.md$|(?:^|\/)TASKS\.md$/i.test(String(targetFile || ''));
430
+ }
431
+
432
+ function isDocsTarget(targetFile) {
433
+ const normalized = String(targetFile || '').replaceAll('\\', '/');
434
+ return /(?:^|\/)docs\/.+\.md$|(?:^|\/)(?:README|CHANGELOG|AGENTS|CLAUDE|STATUS)\.md$/i.test(normalized);
435
+ }
436
+
285
437
  function shouldUseIndexedContext({ activeSkills = [], targetFile = null } = {}) {
286
438
  if (activeSkills.length === 0) {
287
439
  return Boolean(targetFile);
@@ -453,6 +605,16 @@ function deriveDelegationRecommendation({
453
605
  const hasRelatedTests = (preview.relatedTests ?? []).length > 0;
454
606
  const when = contextRecommendation?.command ? 'after-context' : 'now';
455
607
 
608
+ const smallTaskMaintenanceSignal = /\b(?:ukit|docs\/tasks\.md|tasks\.md|task queue|queued tasks?|compact(?:ion)?|summari[sz](?:e|ation)|doc(?:ument)? summary|cleanup|clean up|dọn rác|dọn dẹp|auto[- ]?triage|queue maintenance|small decision|ra quyết định)\b/.test(lower)
609
+ && /\b(?:task|queue|compact(?:ion)?|summari[sz](?:e|ation)|doc(?:ument)?s?|cleanup|clean up|dọn rác|dọn dẹp|classif(?:y|ication)|triage|maintenance|small decision|ra quyết định)\b/.test(lower);
610
+ if (smallTaskMaintenanceSignal) {
611
+ return {
612
+ hint: 'ukit-small-task-maintainer',
613
+ when,
614
+ reason: 'Low-risk UKit maintenance decisions should use the configured small-task model without blocking the main AI flow.',
615
+ };
616
+ }
617
+
456
618
  if (routingContext.taskType === 'trivial') {
457
619
  return null;
458
620
  }
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: ukit-small-task-maintainer
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: inherit
5
+ color: cyan
6
+ tools: ["Read", "Grep", "Glob", "Edit", "Write"]
7
+ ---
8
+
9
+ You are UKit's internal small-task maintainer. You run as a sidecar/parallel/non-blocking lane for safe, reversible UKit orchestration chores so the end user can stay focused on product work and only remember `ukit install`. You must follow `docs/UKIT_CODEV_PRINCIPLES.md`: hide complexity, preserve output quality, and never trade correctness for speed or token savings.
10
+
11
+ ## Model Policy
12
+
13
+ - Use the model selected by `UKIT_SMALL_TASK_MODEL` when the host supports model selection for this subagent.
14
+ - Default intended model: `unic-lite`.
15
+ - If the host cannot bind a model from env directly, still follow this role and report that the configured model is a hint.
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
+
18
+ ## Use For
19
+
20
+ - Cleaning and deduplicating `docs/TASKS.md`.
21
+ - Pruning stale local AI queue/status noise.
22
+ - Classifying queued items by readiness/risk.
23
+ - Deciding whether compacting or summarizing context/docs is appropriate.
24
+ - Summarizing `docs/STATUS.md`, `docs/TASKS.md`, `docs/WORKLOG.md`, or memory snippets into compact handoff notes.
25
+ - Deciding fast vs slow lane, safe vs risky lane, whether a skill should be activated, and whether the current prompt has enough steps planned.
26
+ - Choosing compact-now vs compact-later and summarize-vs-keep-detail for UKit context hygiene.
27
+ - Keeping agent context compact without removing existing lanes: Claude PreCompact/reinject stays active, OpenCode native auto/prune compaction stays active, and Codex Desktop soft handoffs use `UKIT_CODEX_COMPACT_TARGET` (default 150 lines; preferred 120-150; hard max 170) while preserving critical state.
28
+ - Small, reversible UKit runtime maintenance decisions.
29
+
30
+ ## Never Use For
31
+
32
+ - Security/auth/permission/secrets work.
33
+ - Release, tag, publish, package ownership, or irreversible registry decisions.
34
+ - Data deletion beyond clearly safe local queue/doc cleanup.
35
+ - Architecture decisions, roadmap trade-offs, or deep product reasoning.
36
+ - Product code changes or risky/shared implementation edits.
37
+ - Any action where the consequence is not easy to inspect and undo.
38
+
39
+ ## Workflow
40
+
41
+ 1. Read the smallest relevant local state file first.
42
+ 2. Identify whether the requested action is safe and reversible.
43
+ 3. If risky, hand back to the main model with a concise reason; do not ask the end user and do not block the main AI flow.
44
+ 4. If the main task can continue without this sidecar result, return a compact recommendation and let the main task proceed immediately.
45
+ 5. If safe, make the smallest cleanup/summary/classification/routing decision.
46
+ 6. Follow the CoDev priority order: output quality first, then safety, then speed, then token discipline. Spend tokens/steps when they protect correctness.
47
+ 7. Use small step budgets: trivial = 1 step, simple = up to 2 steps, non-trivial = up to 4 planned steps before the main model reassesses.
48
+ 8. For long sessions, preserve existing Claude/OpenCode auto-compact behavior; for Codex Desktop, target a compact handoff of about 120-150 lines, never above 170 lines for this lane, not a full transcript replay.
49
+ 9. Preserve user-owned content; do not delete unclear tasks.
50
+ 10. Report exactly what changed or what decision was made.
51
+
52
+ ## Output Format
53
+
54
+ ```
55
+ STATUS: DONE | SKIPPED | HAND_BACK
56
+ MODEL_HINT: UKIT_SMALL_TASK_MODEL=<value-or-default>
57
+ SUMMARY: [one sentence]
58
+ CHANGES:
59
+ - [file/area]: [what changed]
60
+ HAND_BACK_REASON: [only if HAND_BACK]
61
+ NEXT: [small follow-up or "none"]
62
+ ```
63
+
64
+ ## Guardrails
65
+
66
+ - Keep UKit invisible: never ask end users to remember this agent, model name, or config path.
67
+ - Never block AI decision-making; escalate to the main model instead of waiting for user input when risk exceeds this lane.
68
+ - Never block, replace, or slow the user's main task; this lane is a sidecar hint/maintenance worker only.
69
+ - Prefer no-op over destructive cleanup when uncertain.
70
+ - Do not invent product requirements.
71
+ - Never choose cheap/fast if it risks wrong context, weak verification, over-compaction, or lower answer quality.
72
+ - Do not widen reads beyond local UKit state unless the main model explicitly scoped the handoff.
@@ -61,7 +61,7 @@ Docs should **not** become:
61
61
 
62
62
  - update README / docs after code changes
63
63
  - fix source-vs-doc drift
64
- - improve `docs/PROJECT.md`, `docs/MEMORY.md`, `docs/WORKLOG.md`, `docs/CODE_MAP.md`
64
+ - improve `docs/PROJECT.md`, `docs/MEMORY.md`, `docs/STATUS.md`, `docs/TASKS.md`, `docs/WORKLOG.md`, `docs/CODE_MAP.md`
65
65
  - prepare durable handoff notes
66
66
  - tighten or remove stale setup instructions
67
67
  - document newly discovered module boundaries, dangerous areas, or bug patterns
@@ -97,6 +97,28 @@ Use for durable knowledge:
97
97
 
98
98
  Prefer short entries that future sessions can scan in seconds.
99
99
 
100
+ #### `docs/STATUS.md`
101
+ Use for compact current state:
102
+ - current focus / active work
103
+ - live debug threads, blockers, and verification status
104
+ - next candidates for open-ended continuation
105
+
106
+ Do **not** treat it as source truth or duplicate full session history here.
107
+
108
+ #### `docs/TASKS.md`
109
+ Use for:
110
+ - local AI task queue items the human or an AI may hand to another AI/agent later
111
+ - `Inbox` ideas that still need acceptance/verification details
112
+ - `Ready for AI` tasks that are specific enough to implement without scanning the whole repo
113
+
114
+ Default cleanup when reading/updating it:
115
+ - remove exact duplicates
116
+ - prune `Done Recently` to 10 compact lines
117
+ - move stale/vague/blocked tasks to `Deferred / Needs Human Review`
118
+ - only delete unfinished human-authored tasks when explicitly asked and clearly obsolete/duplicated
119
+
120
+ Do **not** treat it as a roadmap, project history, or source truth. It is local working state.
121
+
100
122
  #### `docs/WORKLOG.md`
101
123
  Use for session-level execution history:
102
124
  - what changed
@@ -0,0 +1,86 @@
1
+ ---
2
+ name: next-step
3
+ description: Use when the user asks what to do next, asks for project status, says continue/làm tiếp without a concrete target, or needs a lightweight session-start orientation from docs/STATUS.md and optional docs/TASKS.md. Do not use as the primary skill for concrete debug, implementation, review, or docs tasks.
4
+ ---
5
+
6
+ # Next Step
7
+
8
+ ## Purpose
9
+
10
+ Suggest the next useful project action without scanning the whole repository.
11
+
12
+ This skill is for open-ended continuity prompts such as:
13
+ - "what next?", "project status?", "where are we?"
14
+ - "continue", "continue from last session"
15
+ - "làm gì tiếp?", "làm tiếp", "project đang ở đâu?"
16
+
17
+ It is **not** a replacement for concrete workflows. If the user names a bug, feature, file, test, PR, or review target, keep the concrete workflow primary and use this skill only as background if useful.
18
+
19
+ ## Hard Guardrails
20
+
21
+ - End users should not need to know this skill name.
22
+ - Do not ask users to run a `next-step` command. The human workflow remains `ukit install` + natural language.
23
+ - `docs/STATUS.md` is orientation, not truth. Source code, tests, and the UKit index win.
24
+ - `docs/TASKS.md` is a local AI task queue, not a roadmap and not source truth.
25
+ - Concrete task beats open-ended wording. Example: "I'm fixing login bug but unsure next step" is a debug approach question, not a global roadmap request.
26
+ - Do not scan the whole repo unless `docs/STATUS.md` is missing/stale and the user still wants project-level direction.
27
+ - When reading `docs/TASKS.md`, perform only safe cleanup by default: remove exact duplicates, prune `Done Recently` to 10 lines, and move stale/vague items to `Deferred / Needs Human Review`; do not delete unfinished human-authored tasks unless explicitly asked and clearly obsolete/duplicated.
28
+
29
+ ## Freshness Check
30
+
31
+ Before relying on status content, check both:
32
+ 1. filesystem modified time for `docs/STATUS.md` (fallback: root `STATUS.md` if present)
33
+ 2. the `Last meaningful update` field inside the file
34
+
35
+ Use this cue in your response:
36
+
37
+ - 🟢 fresh: modified within 24h
38
+ - 🟡 possibly stale: 24-72h old
39
+ - 🔴 stale: older than 72h
40
+ - ⚪ missing: no status file yet
41
+
42
+ If stale or missing, downgrade confidence and verify with the smallest current tree/index/context signal before recommending work.
43
+
44
+ ## Input Order
45
+
46
+ Read only what is needed:
47
+ 1. `docs/STATUS.md` (or existing root `STATUS.md` fallback)
48
+ 2. `docs/TASKS.md` only for queued-task prompts, “continue” with no active status, or when status points at queued work
49
+ 3. `docs/CODE_MAP.md` only when navigation is needed
50
+ 4. `docs/MEMORY.md` only when constraints/decisions affect the suggestion
51
+ 5. routed index/tree summary only if status/tasks are stale, missing, or contradicted
52
+
53
+ ## Output Shape
54
+
55
+ Keep output compact:
56
+
57
+ ```md
58
+ STATUS freshness: 🟡 possibly stale
59
+ - last modified: YYYY-MM-DD HH:mm
60
+ - confidence: medium-low
61
+
62
+ Suggested next steps:
63
+ 1. Candidate — why now — likely files — verification — risk
64
+ 2. Candidate — why now — likely files — verification — risk
65
+
66
+ Queued tasks (if `docs/TASKS.md` was used):
67
+ - Ready: task title — acceptance — verification
68
+ - Deferred/blocked: compact note only if relevant
69
+
70
+ Recommended: ...
71
+ Why: ...
72
+ First check: ...
73
+ ```
74
+
75
+ ## Intent Handling
76
+
77
+ - `open-ended-status`: read status and suggest 1-3 candidates.
78
+ - `queued-task-selection`: read `docs/TASKS.md`, prefer `Ready for AI`, and suggest the best next task with acceptance/verification.
79
+ - `continue-existing-work`: prefer Active Work / Current Debug Threads, then `Ready for AI`, then Next Candidates.
80
+ - `scoped-advice`: do not produce a global roadmap; hand off to the concrete skill and suggest the immediate approach only.
81
+ - `debug-specific`, `implement-specific`, `review-specific`: do not use this skill as primary.
82
+
83
+ ## Missing or Stale Status
84
+
85
+ If missing, suggest creating/updating `docs/STATUS.md` after the current task, but do not block the user.
86
+ If stale, say so visibly and treat old Next Candidates as hypotheses, not fact.
@@ -0,0 +1,102 @@
1
+ ---
2
+ name: update-status
3
+ description: Use near the end of a meaningful session or explicit handoff/status request to update docs/STATUS.md with compact current state, verification, blockers, and next candidates. Skip trivial/no-state-change tasks.
4
+ ---
5
+
6
+ # Update Status
7
+
8
+ ## Purpose
9
+
10
+ Keep `docs/STATUS.md` useful as a compact living state document for future AI sessions.
11
+
12
+ This skill should run when:
13
+ - the user explicitly asks to update status / handoff / wrap up
14
+ - meaningful source/docs/tests/package state changed
15
+ - a task is paused, blocked, completed, or has a new verified next action
16
+ - a bug root cause, verification result, or durable blocker was discovered
17
+
18
+ Do **not** run for trivial typo-only edits, pure Q&A, or exploration with no durable finding.
19
+
20
+ ## Hard Guardrails
21
+
22
+ - End users should not need to know this skill name.
23
+ - Do not ask users to run a `update-status` command. The human workflow remains `ukit install` + natural language.
24
+ - Keep `docs/STATUS.md` compact. It is not `docs/WORKLOG.md` and not a raw session transcript.
25
+ - Keep `docs/TASKS.md` compact when the completed/active work is related to queued tasks; this queue is local working state and should stay gitignored.
26
+ - Source code and tests are truth. If status/tasks conflict with source, update the docs to match source or mark uncertainty.
27
+ - Do not invent verification. Record only commands actually run and their outcome.
28
+ - Preserve user edits and rewrite the smallest relevant section.
29
+
30
+ ## Update Decision
31
+
32
+ Before editing, ask internally:
33
+
34
+ 1. Did project state actually change?
35
+ 2. Is any work still active/blocked?
36
+ 3. Was a root cause, decision, blocker, or next action confirmed?
37
+ 4. What verification ran?
38
+ 5. Will future sessions be faster if this is recorded?
39
+ 6. Did any `docs/TASKS.md` queued task become done, duplicate, stale, or blocked?
40
+
41
+ If all answers are no, skip the update and mention that no status change was needed.
42
+
43
+ ## Freshness Fields
44
+
45
+ When updating meaningful state, update the header:
46
+
47
+ ```md
48
+ ## Freshness
49
+
50
+ - Last meaningful update: YYYY-MM-DD HH:mm
51
+ - Updated by: Claude / Codex / OpenCode / human
52
+ - Status confidence: high / medium / low
53
+ - Stale after: 72h
54
+ ```
55
+
56
+ Confidence guide:
57
+ - `high`: implementation/fix verified by targeted tests or stronger
58
+ - `medium`: state changed but verification was partial or docs-only
59
+ - `low`: investigation/hypothesis only, blocked, or stale recovery
60
+
61
+ ## Section Rules
62
+
63
+ - `Snapshot`: only current focus, health, branch/state, release/version.
64
+ - `Active Work`: only live unfinished work.
65
+ - `Current Debug Threads`: compact bug state; detailed context should link to future `docs/context/<slug>.md` files when available.
66
+ - `Decisions Pending`: unresolved choices only.
67
+ - `Next Candidates`: max 3-5 actionable candidates.
68
+ - `Recently Completed`: max 10 compact lines; detailed session history belongs in `docs/WORKLOG.md`.
69
+
70
+ ## What to Record
71
+
72
+ Prefer concrete bullets:
73
+
74
+ - files changed or likely involved
75
+ - verification commands and pass/fail/blocked result
76
+ - current blocker
77
+ - next action that can be started immediately
78
+ - uncertainty labels (`unknown`, `unverified`, `suspected`) when needed
79
+
80
+ Avoid:
81
+
82
+ - raw command output
83
+ - every file opened/read
84
+ - speculative TODO spam
85
+ - duplicate history already better suited for WORKLOG
86
+ - global roadmap changes caused by a concrete one-file task
87
+
88
+ ## Future Context Note
89
+
90
+ Do not create task-scoped `CONTEXT.md` by default unless the project already has that convention. If detailed bug/feature context is needed, note it as a v1.2 candidate or link to an existing `docs/context/<slug>.md` file.
91
+
92
+ ## TASKS.md Cleanup
93
+
94
+ When the session touched queued work or the user asks to clean/dọn tasks:
95
+
96
+ - Read `docs/TASKS.md` if it exists; do not create noisy task entries just to summarize the session.
97
+ - Auto-remove exact duplicate tasks.
98
+ - Auto-prune `Done Recently` to max 10 compact lines.
99
+ - Remove a task from active sections only after all are true: it is done, verification is recorded, and completion is summarized in `docs/WORKLOG.md` or `Done Recently`.
100
+ - Move stale, vague, or blocked tasks to `Deferred / Needs Human Review` instead of deleting uncertain human intent.
101
+ - Do not delete non-completed human-authored tasks unless the user explicitly asked for cleanup and the task is clearly obsolete or duplicated.
102
+ - Report the cleanup in one compact line: removed duplicates, moved deferred, pruned done, or no safe cleanup.
@@ -0,0 +1,17 @@
1
+ # UKit optional local runtime overrides.
2
+ # Copy to .claude/ukit/.env only if you need machine-local overrides.
3
+ # This is internal orchestration config; normal teammates still only need `ukit install`.
4
+
5
+ # Lightweight model for the internal UKit small-task maintainer subagent.
6
+ # Used for safe UKit decisions such as task cleanup, compact decisions,
7
+ # doc summarization, classification, auto-triage, and queue maintenance.
8
+ # It follows UKit CoDev principles: quality > speed > token savings.
9
+ # Risky/shared/security/release/data-loss/architecture work must keep the main model.
10
+ UKIT_SMALL_TASK_MODEL=unic-lite
11
+
12
+ # Codex Desktop soft auto-compact handoff budget.
13
+ # Target is compact handoff length (lines), not full app context tokens.
14
+ # 120-150 is preferred; 170 lines is the hard max for this lane.
15
+ UKIT_CODEX_AUTO_COMPACT=true
16
+ UKIT_CODEX_CONTEXT_BUDGET=60000
17
+ UKIT_CODEX_COMPACT_TARGET=150
@@ -223,8 +223,30 @@ export const ROUTE_CATALOG = [
223
223
  path: '.claude/skills/docs-quality/SKILL.md',
224
224
  order: 12,
225
225
  signals: [
226
- { type: 'prompt', regex: /\b(docs|documentation|readme|changelog|handoff|worklog|memory|code map)\b/i, score: 4 },
227
- { type: 'file', regex: /\bdocs\/|readme\.md$|project\.md$|memory\.md$|worklog\.md$|code_map\.md$/i, score: 4 },
226
+ { type: 'prompt', regex: /\b(docs|documentation|readme|changelog|handoff|worklog|memory|code map|status\.md|tasks\.md|task queue|clean tasks|cleanup tasks|dọn tasks|dọn task)\b/i, score: 4 },
227
+ { type: 'file', regex: /\bdocs\/|readme\.md$|project\.md$|memory\.md$|status\.md$|tasks\.md$|worklog\.md$|code_map\.md$/i, score: 4 },
228
+ ],
229
+ },
230
+ {
231
+ id: 'next-step',
232
+ path: '.claude/skills/next-step/SKILL.md',
233
+ order: 12.1,
234
+ contextMode: 'standalone',
235
+ signals: [
236
+ { type: 'prompt', regex: /\b(what(?:'s| is)? next|next steps?|project status|current status|where are we|continue(?: from)?(?: last session)?|roadmap|status\.md|task queue|tasks\.md|next queued task|pick next task|work from tasks)\b/i, score: 7 },
237
+ { type: 'prompt', regex: /\b(làm gì tiếp|bước tiếp theo|tiếp theo làm gì|làm tiếp|đang ở đâu|trạng thái project|tình trạng project|task tiếp theo|việc tiếp theo trong tasks)\b/i, score: 7 },
238
+ ],
239
+ },
240
+ {
241
+ id: 'update-status',
242
+ path: '.claude/skills/update-status/SKILL.md',
243
+ order: 12.2,
244
+ contextMode: 'standalone',
245
+ signals: [
246
+ { type: 'prompt', regex: /\b(update|refresh|write|sync|record|capture|summari[sz]e).{0,48}\b(status\.md|project status|current state|next candidates?|session state)\b/i, score: 9 },
247
+ { type: 'prompt', regex: /\b(status\.md|project status).{0,48}\b(update|refresh|write|sync|record|capture|summari[sz]e)\b/i, score: 9 },
248
+ { type: 'prompt', regex: /\b(wrap up|handoff|end(?:ing)? this session|session summary|before final)\b/i, score: 7 },
249
+ { type: 'prompt', regex: /\b(cập nhật|ghi lại|tổng kết|chốt session|bàn giao).{0,48}\b(status|trạng thái|việc tiếp theo)\b/i, score: 9 },
228
250
  ],
229
251
  },
230
252
  {