@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.
- package/CHANGELOG.md +22 -0
- package/README.md +14 -7
- package/manifests/platform.full.yaml +82 -0
- package/package.json +1 -1
- package/src/cli/commands/doctor.js +4 -0
- package/src/cli/commands/install.js +8 -6
- package/src/cli/commands/uninstall.js +1 -1
- package/src/core/ensureGitignore.js +2 -0
- package/src/core/runtimeConfig.js +256 -4
- package/src/core/uninstall.js +1 -1
- package/src/index/routeCatalog.js +24 -2
- package/src/index/taskRouting.js +163 -1
- package/templates/.claude/agents/ukit-small-task-maintainer.md +72 -0
- package/templates/.claude/skills/docs-quality/SKILL.md +23 -1
- package/templates/.claude/skills/next-step/SKILL.md +86 -0
- package/templates/.claude/skills/update-status/SKILL.md +102 -0
- package/templates/.claude/ukit/.env.example +17 -0
- package/templates/.claude/ukit/index/route-catalog.mjs +24 -2
- package/templates/.claude/ukit/index/route-task.mjs +163 -1
- package/templates/.codex/README.md +9 -1
- package/templates/.codex/settings.json +134 -5
- package/templates/.gitignore +2 -0
- package/templates/AGENTS.md +23 -2
- package/templates/CLAUDE.md +23 -2
- package/templates/docs/INSTALL.md +4 -0
- package/templates/docs/PROJECT.md +6 -4
- package/templates/docs/STATUS.md +81 -0
- package/templates/docs/TASKS.md +79 -0
- package/templates/docs/UKIT_USAGE_GUIDE.md +17 -0
- package/templates/ukit/README.md +1 -1
- package/templates/ukit/storage/config.json +116 -2
package/src/index/taskRouting.js
CHANGED
|
@@ -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
|
{
|