@ngockhoale/ukit 1.1.7 → 1.1.8

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 CHANGED
@@ -4,6 +4,17 @@ All notable changes to UKit are documented here.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 1.1.8 - 2026-05-05
8
+
9
+ ### Living Project Status
10
+
11
+ - Added `docs/STATUS.md` as a compact living project-state baseline for active work, debug threads, blockers, verification, and next candidates.
12
+ - Added `next-step` and `update-status` skills so Claude/Codex/OpenCode can use project status automatically without adding any user-facing commands beyond `ukit install`.
13
+ - Made next-step routing freshness-aware: stale or missing status must be treated as orientation only and verified against source/index before recommendations.
14
+ - Added concrete-task precedence so prompts like “fix login bug but not sure next step” stay on the debug/implementation/review workflow instead of being hijacked by global roadmap suggestions.
15
+ - Registered status docs/skills in the manifest with skip semantics for the living doc, and kept source route catalogs aligned with installed helper mirrors.
16
+ - Updated install/routing/manifest regression coverage for open-ended status prompts, explicit handoff updates, concrete debug edge cases, and default skill installation.
17
+
7
18
  ## 1.1.7 - 2026-04-25
8
19
 
9
20
  ### Impact Confidence
package/README.md CHANGED
@@ -32,6 +32,7 @@ ukit install
32
32
  4. Fill in the generated docs baseline:
33
33
  - `docs/PROJECT.md`
34
34
  - `docs/MEMORY.md`
35
+ - `docs/STATUS.md`
35
36
  - `docs/WORKLOG.md`
36
37
  5. Open your AI tool and work in natural language.
37
38
 
@@ -64,9 +65,9 @@ If maintainers roll out a newer CLI build, the in-project workflow still stays t
64
65
  **Project support files**
65
66
  - `.claude/ukit/.ukit/` — installer manifests, metadata, backups
66
67
  - `.ukit/` — hidden shared runtime storage for config, cache, and cross-agent memory
67
- - `docs/` — PROJECT / MEMORY / WORKLOG baseline
68
+ - `docs/` — PROJECT / MEMORY / STATUS / WORKLOG baseline
68
69
 
69
- ## UKit v1.1.7 Runtime
70
+ ## UKit v1.1.8 Runtime
70
71
 
71
72
  UKit now installs a hidden shared local runtime at `.ukit/` for production-oriented state that should survive across agent sessions:
72
73
 
@@ -83,15 +84,17 @@ When long sessions approach the compact threshold, UKit now uses a conservative
83
84
  - compact only safe-zone history/noise
84
85
  - preserve active task, rules, decisions, and current code focus
85
86
 
86
- UKit v1.1.7 keeps the same shared runtime contract while adding impact-confidence routing for shared runtime/template changes:
87
+ UKit v1.1.8 keeps the same shared runtime contract while adding living project status routing for continuity-safe AI sessions:
87
88
 
88
89
  - install globally with `npm install -g @ngockhoale/ukit`
89
90
  - keep using the exact same human workflow inside projects: `ukit install`
90
91
  - preserve the same `ukit` binary, hooks, and install-first orchestration while standardizing the runtime root as hidden `.ukit/`
91
- - route shared index/helper/hook/template edits as higher-impact work instead of treating them like ordinary simple changes
92
- - surface mirror-counterpart and impact-test hints so agents verify source/runtime/template changes with better confidence
92
+ - install `docs/STATUS.md` as a compact living state file for active work, debug threads, blockers, verification, and next candidates
93
+ - auto-route open-ended “what next?” / “continue” prompts to the `next-step` skill with a visible freshness cue when status may be stale
94
+ - auto-route explicit handoff/wrap-up requests to the `update-status` skill while skipping trivial/no-state-change tasks
95
+ - keep concrete debug/implementation/review prompts primary, so project status never replaces source/index-first task work
93
96
 
94
- UKit v1.1.7 also keeps the fast path improvements from the recent runtime releases:
97
+ UKit v1.1.8 also keeps the fast path improvements from the recent runtime releases:
95
98
 
96
99
  - Vietnamese prompts now normalize more effectively for English-heavy code symbols and paths
97
100
  - localized simple direct-target lanes skip extra previous-context / recent-output work when it would not change the next action
@@ -143,6 +143,22 @@ items:
143
143
  packs:
144
144
  - core
145
145
 
146
+ - id: docs-status
147
+ type: config
148
+ sourceTemplate: docs/STATUS.md
149
+ targetPath: docs/STATUS.md
150
+ requires:
151
+ - docs-project
152
+ - docs-memory
153
+ - docs-worklog
154
+ - docs-code-map
155
+ mergeStrategy: skip
156
+ variables:
157
+ - project.name
158
+ enabledByDefault: true
159
+ packs:
160
+ - core
161
+
146
162
  - id: docs-bugfix
147
163
  type: config
148
164
  sourceTemplate: docs/BUGFIX.md
@@ -460,6 +476,32 @@ items:
460
476
  packs:
461
477
  - core
462
478
 
479
+ - id: next-step-skill
480
+ type: skill
481
+ sourceTemplate: .claude/skills/next-step/SKILL.md
482
+ targetPath: .claude/skills/next-step/SKILL.md
483
+ requires:
484
+ - docs-quality-skill
485
+ - docs-status
486
+ mergeStrategy: overwrite_with_backup
487
+ variables: []
488
+ enabledByDefault: true
489
+ packs:
490
+ - core
491
+
492
+ - id: update-status-skill
493
+ type: skill
494
+ sourceTemplate: .claude/skills/update-status/SKILL.md
495
+ targetPath: .claude/skills/update-status/SKILL.md
496
+ requires:
497
+ - docs-quality-skill
498
+ - docs-status
499
+ mergeStrategy: overwrite_with_backup
500
+ variables: []
501
+ enabledByDefault: true
502
+ packs:
503
+ - core
504
+
463
505
  - id: docs-manager-skill
464
506
  type: skill
465
507
  sourceTemplate: .claude/skills/docs-manager
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngockhoale/ukit",
3
- "version": "1.1.7",
3
+ "version": "1.1.8",
4
4
  "description": "Install/update an index-first AI workspace for Claude Code, Antigravity, OpenAI Codex, and OpenCode.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -62,6 +62,7 @@ export async function runDoctor({ packageRoot, projectRoot, argv = [] }) {
62
62
  sessionMemoryDirExists: await pathExists(runtimePaths.sessionsDir),
63
63
  docsProjectExists: await pathExists(path.join(projectRoot, 'docs', 'PROJECT.md')),
64
64
  docsMemoryExists: await pathExists(path.join(projectRoot, 'docs', 'MEMORY.md')),
65
+ docsStatusExists: await pathExists(path.join(projectRoot, 'docs', 'STATUS.md')),
65
66
  docsWorklogExists: await pathExists(path.join(projectRoot, 'docs', 'WORKLOG.md')),
66
67
  allProvidersConfigured: providers.allSupported,
67
68
  ...(codexAdapterTracked
@@ -103,6 +104,7 @@ export async function runDoctor({ packageRoot, projectRoot, argv = [] }) {
103
104
  console.log(`[UKit] ${ok(checks.sessionMemoryDirExists)} .ukit/storage/memory/sessions/`);
104
105
  console.log(`[UKit] ${ok(checks.docsProjectExists)} docs/PROJECT.md`);
105
106
  console.log(`[UKit] ${ok(checks.docsMemoryExists)} docs/MEMORY.md`);
107
+ console.log(`[UKit] ${ok(checks.docsStatusExists)} docs/STATUS.md`);
106
108
  console.log(`[UKit] ${ok(checks.docsWorklogExists)} docs/WORKLOG.md`);
107
109
  if (codexAdapterTracked) {
108
110
  console.log(`[UKit] ${ok(checks.codexReadmeExists)} .codex/README.md`);
@@ -244,9 +244,10 @@ export async function runInstall({ packageRoot, projectRoot, packageVersion, arg
244
244
  const docsPaths = [
245
245
  path.join(projectRoot, 'docs', 'PROJECT.md'),
246
246
  path.join(projectRoot, 'docs', 'MEMORY.md'),
247
+ path.join(projectRoot, 'docs', 'STATUS.md'),
247
248
  path.join(projectRoot, 'docs', 'WORKLOG.md'),
248
249
  ];
249
- const docsLabels = ['docs/PROJECT.md', 'docs/MEMORY.md', 'docs/WORKLOG.md'];
250
+ const docsLabels = ['docs/PROJECT.md', 'docs/MEMORY.md', 'docs/STATUS.md', 'docs/WORKLOG.md'];
250
251
  const missingDocs = [];
251
252
  for (let i = 0; i < docsPaths.length; i++) {
252
253
  if (!(await pathExists(docsPaths[i]))) {
@@ -257,7 +258,7 @@ export async function runInstall({ packageRoot, projectRoot, packageVersion, arg
257
258
  if (missingDocs.length > 0) {
258
259
  console.log(`[UKit] Missing docs — fill these in before first use: ${missingDocs.join(', ')}`);
259
260
  } else {
260
- console.log('[UKit] Docs baseline ready: docs/PROJECT.md, docs/MEMORY.md, docs/WORKLOG.md');
261
+ console.log('[UKit] Docs baseline ready: docs/PROJECT.md, docs/MEMORY.md, docs/STATUS.md, docs/WORKLOG.md');
261
262
  console.log('[UKit] Fill them once with real project context for the best results.');
262
263
  }
263
264
 
@@ -47,5 +47,5 @@ export async function runUninstall({ projectRoot, argv = [] }) {
47
47
  }
48
48
 
49
49
  console.log(`[UKit] Uninstall complete. Removed ${result.removed}/${result.attempted} managed paths.`);
50
- console.log('[UKit] Note: docs/PROJECT.md, docs/MEMORY.md, docs/WORKLOG.md contain user content and were preserved. Delete manually if needed.');
50
+ console.log('[UKit] Note: docs/PROJECT.md, docs/MEMORY.md, docs/STATUS.md, docs/WORKLOG.md contain user content and were preserved. Delete manually if needed.');
51
51
  }
@@ -42,7 +42,7 @@ export function buildDefaultRuntimeConfig(overrides = {}) {
42
42
  const safeOverrides = isPlainObject(overrides) ? overrides : {};
43
43
 
44
44
  return mergeObjects({
45
- version: '1.1.7',
45
+ version: '1.1.8',
46
46
  agent: 'claude-code',
47
47
  compact: {
48
48
  enabled: true,
@@ -200,7 +200,7 @@ export async function uninstallUkit({ projectRoot, dryRun = false }) {
200
200
  }
201
201
  } else {
202
202
  // Old format (no files list): fall back to hardcoded managed paths.
203
- // NOTE: docs/PROJECT.md, MEMORY.md, WORKLOG.md are intentionally excluded.
203
+ // NOTE: docs/PROJECT.md, MEMORY.md, STATUS.md, WORKLOG.md are intentionally excluded.
204
204
  // These are user-created content (mergeStrategy: skip) — deleting them
205
205
  // would cause data loss. Users must remove them manually if desired.
206
206
  const fallback = buildFallbackPaths(projectRoot);
@@ -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)\b/i, score: 4 },
227
+ { type: 'file', regex: /\bdocs\/|readme\.md$|project\.md$|memory\.md$|status\.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)\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)\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
  {
@@ -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,
@@ -175,6 +183,7 @@ export function buildRouteSummary({
175
183
  fallbackCommands,
176
184
  preferredOrder,
177
185
  policyMode,
186
+ intentMode: routingContext.intentMode ?? null,
178
187
  delegateHint: delegationRecommendation?.hint ?? null,
179
188
  nextActionType: nextAction?.type ?? null,
180
189
  nextActionCommand,
@@ -183,7 +192,7 @@ export function buildRouteSummary({
183
192
  };
184
193
  }
185
194
 
186
- async function selectActiveSkills({ rootDir, promptText, commandText, targetFile }) {
195
+ async function selectActiveSkills({ rootDir, promptText, commandText, targetFile, intentMode = null }) {
187
196
  const routeSignals = {
188
197
  promptRawText: String(promptText || '').toLowerCase(),
189
198
  promptNormalizedText: buildRouteSignalText(promptText),
@@ -194,6 +203,7 @@ async function selectActiveSkills({ rootDir, promptText, commandText, targetFile
194
203
  const scoredEntries = ROUTE_CATALOG
195
204
  .map((entry) => scoreSkillRouteEntry(entry, routeSignals))
196
205
  .filter((entry) => entry.score > 0)
206
+ .filter((entry) => shouldKeepRouteEntryForIntent(entry, intentMode))
197
207
  .sort((a, b) => b.score - a.score || a.order - b.order);
198
208
  const active = [];
199
209
 
@@ -209,6 +219,22 @@ async function selectActiveSkills({ rootDir, promptText, commandText, targetFile
209
219
  return active.map(({ order, ...rest }) => rest);
210
220
  }
211
221
 
222
+ function shouldKeepRouteEntryForIntent(entry, intentMode) {
223
+ if (entry.id === 'next-step' && ['scoped-advice', 'docs-specific'].includes(intentMode)) {
224
+ return false;
225
+ }
226
+
227
+ if (entry.id === 'update-status' && intentMode === 'docs-specific') {
228
+ return false;
229
+ }
230
+
231
+ if (entry.id === 'docs-quality' && ['open-ended-status', 'status-update'].includes(intentMode)) {
232
+ return false;
233
+ }
234
+
235
+ return true;
236
+ }
237
+
212
238
  function scoreSkillRouteEntry(entry, routeSignals = {}) {
213
239
  let score = 0;
214
240
  const reasons = [];
@@ -282,6 +308,116 @@ function getSignalTexts(signalType, routeSignals = {}) {
282
308
  };
283
309
  }
284
310
 
311
+ function deriveIntentMode({ promptText = '', commandText = '', targetFile = null } = {}) {
312
+ const lower = buildRouteSignalText(promptText, commandText);
313
+ const raw = `${promptText ?? ''}\n${commandText ?? ''}`.toLowerCase();
314
+ const docsSpecific = hasDocsSpecificTaskSignal(lower, raw, targetFile);
315
+ const statusUpdate = hasStatusUpdateSignal(lower, raw);
316
+ const openEndedStatus = hasOpenEndedStatusSignal(lower, raw);
317
+ const concreteTask = hasConcreteTaskSignal(lower, raw, targetFile);
318
+
319
+ if (docsSpecific) {
320
+ return 'docs-specific';
321
+ }
322
+
323
+ if (statusUpdate) {
324
+ return 'status-update';
325
+ }
326
+
327
+ if (concreteTask && openEndedStatus) {
328
+ return 'scoped-advice';
329
+ }
330
+
331
+ if (openEndedStatus) {
332
+ return 'open-ended-status';
333
+ }
334
+
335
+ if (concreteTask) {
336
+ if (/\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|login|timeout)\b/.test(lower)) {
337
+ return 'debug-specific';
338
+ }
339
+ if (/\b(review|audit|diff|pr feedback|code review|kiem tra|soat)\b/.test(lower)) {
340
+ return 'review-specific';
341
+ }
342
+ if (/\b(implement|build|create|add|ship|deliver|refactor|integrate|integration|scaffold|feature)\b/.test(lower)) {
343
+ return 'implement-specific';
344
+ }
345
+ }
346
+
347
+ return null;
348
+ }
349
+
350
+ function hasStatusUpdateSignal(lower, raw) {
351
+ 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)
352
+ || /\b(status\.md|project status).{0,64}\b(update|refresh|write|sync|record|capture|summarize|summarise)\b/.test(lower)
353
+ || /\b(wrap up|handoff|end this session|ending this session|session summary|before final)\b/.test(lower)
354
+ || /\b(cap nhat|ghi lai|tong ket|chot session|ban giao).{0,64}\b(status|trang thai|viec tiep theo)\b/.test(lower)
355
+ || /\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);
356
+ }
357
+
358
+ function hasOpenEndedStatusSignal(lower, raw) {
359
+ 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)\b/.test(lower)
360
+ || /\b(lam gi tiep|buoc tiep theo|tiep theo lam gi|lam tiep|dang o dau|trang thai project|tinh trang project)\b/.test(lower)
361
+ || /\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)\b/.test(raw);
362
+ }
363
+
364
+ function hasConcreteTaskSignal(lower, raw, targetFile) {
365
+ if (targetFile && !isStatusFileTarget(targetFile)) {
366
+ return true;
367
+ }
368
+
369
+ 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)
370
+ || /\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);
371
+ }
372
+
373
+ function hasDocsSpecificTaskSignal(lower, raw, targetFile) {
374
+ if (!targetFile || !isDocsTarget(targetFile)) {
375
+ return false;
376
+ }
377
+
378
+ const targetName = path.posix.basename(String(targetFile || '').replaceAll('\\', '/')).toLowerCase();
379
+ const explicitStatusUpdate = hasExplicitStatusUpdateSignal(lower, raw);
380
+
381
+ if (!isStatusFileTarget(targetFile)) {
382
+ if (explicitStatusUpdate && !mentionsTargetDoc(lower, targetName)) {
383
+ return false;
384
+ }
385
+
386
+ return mentionsTargetDoc(lower, targetName)
387
+ || /\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)
388
+ || /\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);
389
+ }
390
+
391
+ return /\b(template|wording|edit|copy|grammar|format|structure|heading|section|docs?)\b/.test(lower)
392
+ || /\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);
393
+ }
394
+
395
+ function hasExplicitStatusUpdateSignal(lower, raw) {
396
+ 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)
397
+ || /\b(status\.md|project status).{0,64}\b(update|refresh|write|sync|record|capture|summarize|summarise)\b/.test(lower)
398
+ || /\b(cap nhat|ghi lai|tong ket|chot session|ban giao).{0,64}\b(status|trang thai|viec tiep theo)\b/.test(lower)
399
+ || /\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);
400
+ }
401
+
402
+ function mentionsTargetDoc(lower, targetName) {
403
+ if (!targetName) {
404
+ return false;
405
+ }
406
+
407
+ const escaped = targetName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
408
+ const withoutExt = escaped.replace(/\\\.md$/i, '');
409
+ return new RegExp(`\\b(?:${escaped}|${withoutExt})\\b`, 'i').test(lower);
410
+ }
411
+
412
+ function isStatusFileTarget(targetFile) {
413
+ return /(?:^|\/)docs\/STATUS\.md$|(?:^|\/)STATUS\.md$/i.test(String(targetFile || ''));
414
+ }
415
+
416
+ function isDocsTarget(targetFile) {
417
+ const normalized = String(targetFile || '').replaceAll('\\', '/');
418
+ return /(?:^|\/)docs\/.+\.md$|(?:^|\/)(?:README|CHANGELOG|AGENTS|CLAUDE|STATUS)\.md$/i.test(normalized);
419
+ }
420
+
285
421
  function shouldUseIndexedContext({ activeSkills = [], targetFile = null } = {}) {
286
422
  if (activeSkills.length === 0) {
287
423
  return Boolean(targetFile);
@@ -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/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,14 @@ 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
+
100
108
  #### `docs/WORKLOG.md`
101
109
  Use for session-level execution history:
102
110
  - what changed
@@ -0,0 +1,78 @@
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. 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
+ - 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.
25
+ - Do not scan the whole repo unless `docs/STATUS.md` is missing/stale and the user still wants project-level direction.
26
+
27
+ ## Freshness Check
28
+
29
+ Before relying on status content, check both:
30
+ 1. filesystem modified time for `docs/STATUS.md` (fallback: root `STATUS.md` if present)
31
+ 2. the `Last meaningful update` field inside the file
32
+
33
+ Use this cue in your response:
34
+
35
+ - 🟢 fresh: modified within 24h
36
+ - 🟡 possibly stale: 24-72h old
37
+ - 🔴 stale: older than 72h
38
+ - ⚪ missing: no status file yet
39
+
40
+ If stale or missing, downgrade confidence and verify with the smallest current tree/index/context signal before recommending work.
41
+
42
+ ## Input Order
43
+
44
+ Read only what is needed:
45
+ 1. `docs/STATUS.md` (or existing root `STATUS.md` fallback)
46
+ 2. `docs/CODE_MAP.md` only when navigation is needed
47
+ 3. `docs/MEMORY.md` only when constraints/decisions affect the suggestion
48
+ 4. routed index/tree summary only if status is stale, missing, or contradicted
49
+
50
+ ## Output Shape
51
+
52
+ Keep output compact:
53
+
54
+ ```md
55
+ STATUS freshness: 🟡 possibly stale
56
+ - last modified: YYYY-MM-DD HH:mm
57
+ - confidence: medium-low
58
+
59
+ Suggested next steps:
60
+ 1. Candidate — why now — likely files — verification — risk
61
+ 2. Candidate — why now — likely files — verification — risk
62
+
63
+ Recommended: ...
64
+ Why: ...
65
+ First check: ...
66
+ ```
67
+
68
+ ## Intent Handling
69
+
70
+ - `open-ended-status`: read status and suggest 1-3 candidates.
71
+ - `continue-existing-work`: prefer Active Work / Current Debug Threads, then Next Candidates.
72
+ - `scoped-advice`: do not produce a global roadmap; hand off to the concrete skill and suggest the immediate approach only.
73
+ - `debug-specific`, `implement-specific`, `review-specific`: do not use this skill as primary.
74
+
75
+ ## Missing or Stale Status
76
+
77
+ If missing, suggest creating/updating `docs/STATUS.md` after the current task, but do not block the user.
78
+ If stale, say so visibly and treat old Next Candidates as hypotheses, not fact.
@@ -0,0 +1,88 @@
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
+ - Source code and tests are truth. If status conflicts with source, update status to match source or mark uncertainty.
26
+ - Do not invent verification. Record only commands actually run and their outcome.
27
+ - Preserve user edits and rewrite the smallest relevant section.
28
+
29
+ ## Update Decision
30
+
31
+ Before editing, ask internally:
32
+
33
+ 1. Did project state actually change?
34
+ 2. Is any work still active/blocked?
35
+ 3. Was a root cause, decision, blocker, or next action confirmed?
36
+ 4. What verification ran?
37
+ 5. Will future sessions be faster if this is recorded?
38
+
39
+ If all answers are no, skip the update and mention that no status change was needed.
40
+
41
+ ## Freshness Fields
42
+
43
+ When updating meaningful state, update the header:
44
+
45
+ ```md
46
+ ## Freshness
47
+
48
+ - Last meaningful update: YYYY-MM-DD HH:mm
49
+ - Updated by: Claude / Codex / OpenCode / human
50
+ - Status confidence: high / medium / low
51
+ - Stale after: 72h
52
+ ```
53
+
54
+ Confidence guide:
55
+ - `high`: implementation/fix verified by targeted tests or stronger
56
+ - `medium`: state changed but verification was partial or docs-only
57
+ - `low`: investigation/hypothesis only, blocked, or stale recovery
58
+
59
+ ## Section Rules
60
+
61
+ - `Snapshot`: only current focus, health, branch/state, release/version.
62
+ - `Active Work`: only live unfinished work.
63
+ - `Current Debug Threads`: compact bug state; detailed context should link to future `docs/context/<slug>.md` files when available.
64
+ - `Decisions Pending`: unresolved choices only.
65
+ - `Next Candidates`: max 3-5 actionable candidates.
66
+ - `Recently Completed`: max 10 compact lines; detailed session history belongs in `docs/WORKLOG.md`.
67
+
68
+ ## What to Record
69
+
70
+ Prefer concrete bullets:
71
+
72
+ - files changed or likely involved
73
+ - verification commands and pass/fail/blocked result
74
+ - current blocker
75
+ - next action that can be started immediately
76
+ - uncertainty labels (`unknown`, `unverified`, `suspected`) when needed
77
+
78
+ Avoid:
79
+
80
+ - raw command output
81
+ - every file opened/read
82
+ - speculative TODO spam
83
+ - duplicate history already better suited for WORKLOG
84
+ - global roadmap changes caused by a concrete one-file task
85
+
86
+ ## Future Context Note
87
+
88
+ Do not create task-scoped `CONTEXT.md` as part of v1.1.8 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.
@@ -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)\b/i, score: 4 },
227
+ { type: 'file', regex: /\bdocs\/|readme\.md$|project\.md$|memory\.md$|status\.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)\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)\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
  {
@@ -230,11 +230,17 @@ async function prepareTaskRoute({
230
230
  const normalizedPrompt = String(promptText || '').trim();
231
231
  const normalizedCommand = String(commandText || '').trim();
232
232
  const normalizedTarget = normalizeRelativeFile(absoluteRoot, targetFile);
233
+ const intentMode = deriveIntentMode({
234
+ promptText: normalizedPrompt,
235
+ commandText: normalizedCommand,
236
+ targetFile: normalizedTarget,
237
+ });
233
238
  const activeSkills = await selectActiveSkills({
234
239
  rootDir: absoluteRoot,
235
240
  promptText: normalizedPrompt,
236
241
  commandText: normalizedCommand,
237
242
  targetFile: normalizedTarget,
243
+ intentMode,
238
244
  });
239
245
  const selectedIds = activeSkills.map((entry) => entry.id);
240
246
  const contextIntent = deriveContextIntent({
@@ -262,6 +268,7 @@ async function prepareTaskRoute({
262
268
  targetFile: normalizedTarget,
263
269
  contextIntent,
264
270
  taskType: inferredTaskType,
271
+ intentMode,
265
272
  },
266
273
  };
267
274
  }
@@ -624,7 +631,7 @@ async function readHelperCacheSnapshot({
624
631
  };
625
632
  }
626
633
 
627
- async function selectActiveSkills({ rootDir, promptText, commandText, targetFile }) {
634
+ async function selectActiveSkills({ rootDir, promptText, commandText, targetFile, intentMode = null }) {
628
635
  const routeSignals = {
629
636
  promptRawText: String(promptText || '').toLowerCase(),
630
637
  promptNormalizedText: buildNormalizedRouteSignalText(promptText),
@@ -635,6 +642,7 @@ async function selectActiveSkills({ rootDir, promptText, commandText, targetFile
635
642
  const scoredEntries = ROUTE_CATALOG
636
643
  .map((entry) => scoreSkillRouteEntry(entry, routeSignals))
637
644
  .filter((entry) => entry.score > 0)
645
+ .filter((entry) => shouldKeepRouteEntryForIntent(entry, intentMode))
638
646
  .sort((a, b) => b.score - a.score || a.order - b.order);
639
647
  const active = [];
640
648
 
@@ -650,6 +658,22 @@ async function selectActiveSkills({ rootDir, promptText, commandText, targetFile
650
658
  return active.map(({ order, ...rest }) => rest);
651
659
  }
652
660
 
661
+ function shouldKeepRouteEntryForIntent(entry, intentMode) {
662
+ if (entry.id === 'next-step' && ['scoped-advice', 'docs-specific'].includes(intentMode)) {
663
+ return false;
664
+ }
665
+
666
+ if (entry.id === 'update-status' && intentMode === 'docs-specific') {
667
+ return false;
668
+ }
669
+
670
+ if (entry.id === 'docs-quality' && ['open-ended-status', 'status-update'].includes(intentMode)) {
671
+ return false;
672
+ }
673
+
674
+ return true;
675
+ }
676
+
653
677
  function scoreSkillRouteEntry(entry, routeSignals = {}) {
654
678
  let score = 0;
655
679
  const reasons = [];
@@ -718,6 +742,116 @@ function getSignalTexts(signalType, routeSignals = {}) {
718
742
  };
719
743
  }
720
744
 
745
+ function deriveIntentMode({ promptText = '', commandText = '', targetFile = null } = {}) {
746
+ const lower = buildNormalizedRouteSignalText(promptText, commandText);
747
+ const raw = `${promptText ?? ''}\n${commandText ?? ''}`.toLowerCase();
748
+ const docsSpecific = hasDocsSpecificTaskSignal(lower, raw, targetFile);
749
+ const statusUpdate = hasStatusUpdateSignal(lower, raw);
750
+ const openEndedStatus = hasOpenEndedStatusSignal(lower, raw);
751
+ const concreteTask = hasConcreteTaskSignal(lower, raw, targetFile);
752
+
753
+ if (docsSpecific) {
754
+ return 'docs-specific';
755
+ }
756
+
757
+ if (statusUpdate) {
758
+ return 'status-update';
759
+ }
760
+
761
+ if (concreteTask && openEndedStatus) {
762
+ return 'scoped-advice';
763
+ }
764
+
765
+ if (openEndedStatus) {
766
+ return 'open-ended-status';
767
+ }
768
+
769
+ if (concreteTask) {
770
+ if (/\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|login|timeout)\b/.test(lower)) {
771
+ return 'debug-specific';
772
+ }
773
+ if (/\b(review|audit|diff|pr feedback|code review|kiem tra|soat)\b/.test(lower)) {
774
+ return 'review-specific';
775
+ }
776
+ if (/\b(implement|build|create|add|ship|deliver|refactor|integrate|integration|scaffold|feature)\b/.test(lower)) {
777
+ return 'implement-specific';
778
+ }
779
+ }
780
+
781
+ return null;
782
+ }
783
+
784
+ function hasStatusUpdateSignal(lower, raw) {
785
+ 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)
786
+ || /\b(status\.md|project status).{0,64}\b(update|refresh|write|sync|record|capture|summarize|summarise)\b/.test(lower)
787
+ || /\b(wrap up|handoff|end this session|ending this session|session summary|before final)\b/.test(lower)
788
+ || /\b(cap nhat|ghi lai|tong ket|chot session|ban giao).{0,64}\b(status|trang thai|viec tiep theo)\b/.test(lower)
789
+ || /\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);
790
+ }
791
+
792
+ function hasOpenEndedStatusSignal(lower, raw) {
793
+ 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)\b/.test(lower)
794
+ || /\b(lam gi tiep|buoc tiep theo|tiep theo lam gi|lam tiep|dang o dau|trang thai project|tinh trang project)\b/.test(lower)
795
+ || /\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)\b/.test(raw);
796
+ }
797
+
798
+ function hasConcreteTaskSignal(lower, raw, targetFile) {
799
+ if (targetFile && !isStatusFileTarget(targetFile)) {
800
+ return true;
801
+ }
802
+
803
+ 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)
804
+ || /\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);
805
+ }
806
+
807
+ function hasDocsSpecificTaskSignal(lower, raw, targetFile) {
808
+ if (!targetFile || !isDocsTarget(targetFile)) {
809
+ return false;
810
+ }
811
+
812
+ const targetName = path.posix.basename(String(targetFile || '').replaceAll('\\', '/')).toLowerCase();
813
+ const explicitStatusUpdate = hasExplicitStatusUpdateSignal(lower, raw);
814
+
815
+ if (!isStatusFileTarget(targetFile)) {
816
+ if (explicitStatusUpdate && !mentionsTargetDoc(lower, targetName)) {
817
+ return false;
818
+ }
819
+
820
+ return mentionsTargetDoc(lower, targetName)
821
+ || /\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)
822
+ || /\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);
823
+ }
824
+
825
+ return /\b(template|wording|edit|copy|grammar|format|structure|heading|section|docs?)\b/.test(lower)
826
+ || /\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);
827
+ }
828
+
829
+ function hasExplicitStatusUpdateSignal(lower, raw) {
830
+ 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)
831
+ || /\b(status\.md|project status).{0,64}\b(update|refresh|write|sync|record|capture|summarize|summarise)\b/.test(lower)
832
+ || /\b(cap nhat|ghi lai|tong ket|chot session|ban giao).{0,64}\b(status|trang thai|viec tiep theo)\b/.test(lower)
833
+ || /\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);
834
+ }
835
+
836
+ function mentionsTargetDoc(lower, targetName) {
837
+ if (!targetName) {
838
+ return false;
839
+ }
840
+
841
+ const escaped = targetName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
842
+ const withoutExt = escaped.replace(/\\\.md$/i, '');
843
+ return new RegExp(`\\b(?:${escaped}|${withoutExt})\\b`, 'i').test(lower);
844
+ }
845
+
846
+ function isStatusFileTarget(targetFile) {
847
+ return /(?:^|\/)docs\/STATUS\.md$|(?:^|\/)STATUS\.md$/i.test(String(targetFile || ''));
848
+ }
849
+
850
+ function isDocsTarget(targetFile) {
851
+ const normalized = String(targetFile || '').replaceAll('\\', '/');
852
+ return /(?:^|\/)docs\/.+\.md$|(?:^|\/)(?:README|CHANGELOG|AGENTS|CLAUDE|STATUS)\.md$/i.test(normalized);
853
+ }
854
+
721
855
  function shouldUseIndexedContext({ activeSkills = [], targetFile = null } = {}) {
722
856
  if (activeSkills.length === 0) {
723
857
  return Boolean(targetFile);
@@ -1063,6 +1197,7 @@ function buildRouteSummary({
1063
1197
  fallbackCommands,
1064
1198
  preferredOrder,
1065
1199
  policyMode,
1200
+ intentMode: routingContext.intentMode ?? null,
1066
1201
  delegateHint: delegationRecommendation?.hint ?? null,
1067
1202
  nextActionType: nextAction?.type ?? null,
1068
1203
  nextActionCommand,
@@ -1580,6 +1715,7 @@ function compactRoutingContext(routingContext = {}) {
1580
1715
  adapter: routingContext.adapter ?? 'claude',
1581
1716
  lastExplicitUserPromptText: routingContext.lastExplicitUserPromptText ?? '',
1582
1717
  taskType: routingContext.taskType ?? null,
1718
+ intentMode: routingContext.intentMode ?? null,
1583
1719
  };
1584
1720
  }
1585
1721
 
@@ -12,7 +12,7 @@ Auto-generated by UKit for OpenAI Codex.
12
12
  - Do not make end users memorize skill names, helper scripts, or routing internals unless they are debugging UKit itself.
13
13
  - **Treat helper commands as internal orchestration. Do not ask end users to run them.**
14
14
 
15
- ## UKit v1.1.7 Shared Runtime
15
+ ## UKit v1.1.8 Shared Runtime
16
16
 
17
17
  - Shared runtime state lives in `.ukit/storage/`.
18
18
  - Treat `.ukit/storage/config.json` as the source of compact, token-pipeline, router, memory, and validation toggles.
@@ -29,6 +29,7 @@ Auto-generated by UKit for OpenAI Codex.
29
29
  - **Trivial**: no docs.
30
30
  - **Simple**: `docs/MEMORY.md` only.
31
31
  - **Non-trivial**: `docs/MEMORY.md` + `docs/PROJECT.md` + `docs/CODE_MAP.md`.
32
+ - `docs/STATUS.md`: read for open-ended status/continue prompts or meaningful continuation context; stale status is orientation only.
32
33
  - Read `docs/WORKLOG.md` only when recent continuation/debug context matters.
33
34
  - Source is truth; if docs are stale, update docs and continue.
34
35
 
@@ -52,6 +53,9 @@ For clearly non-code specialist lanes, avoid dragging the source-code index into
52
53
  - Match from prompt wording plus tool/file evidence.
53
54
  - Use the smallest useful set, usually 1-2 skills.
54
55
  - If docs work is detected, prefer `.codex/skills/docs-quality/SKILL.md`.
56
+ - For open-ended “what next?” / “continue” / project-status prompts, prefer `.codex/skills/next-step/SKILL.md` and show a status freshness cue.
57
+ - For explicit handoff/wrap-up/status updates, prefer `.codex/skills/update-status/SKILL.md`.
58
+ - Concrete debug/implementation/review prompts beat open-ended wording; do not let `next-step` replace the concrete workflow.
55
59
  - If routing is complex or ambiguous, prefer `node .codex/ukit/index/route-task.mjs "<prompt>" [--tool-command <cmd>] [--target <file>]`.
56
60
  - That helper should keep shared route memory in `.claude/ukit/skill-router-state.json` so Claude and Codex continue from the same compact route state.
57
61
  - When route memory already includes `previous-context` or `recent-output`, reuse it before widening reads or logs.
@@ -68,6 +72,7 @@ For clearly non-code specialist lanes, avoid dragging the source-code index into
68
72
  ## Docs Discipline
69
73
 
70
74
  After significant work, update only what changed:
75
+ - `docs/STATUS.md` — compact current state, blockers, verification, next candidates
71
76
  - `docs/WORKLOG.md`
72
77
  - `docs/MEMORY.md`
73
78
  - `docs/CODE_MAP.md`
@@ -65,6 +65,12 @@
65
65
  ],
66
66
  "maintenance": [
67
67
  "repo-maintenance"
68
+ ],
69
+ "nextStep": [
70
+ "next-step"
71
+ ],
72
+ "statusUpdate": [
73
+ "update-status"
68
74
  ]
69
75
  },
70
76
  "toolSignals": {
@@ -89,7 +95,8 @@
89
95
  },
90
96
  "routingRule": {
91
97
  "endUserShouldNotNeedSkillNames": true,
92
- "selectSmallestUsefulSkillSet": true
98
+ "selectSmallestUsefulSkillSet": true,
99
+ "concreteTaskBeatsOpenEndedStatus": true
93
100
  },
94
101
  "delegationBridge": {
95
102
  "enabled": true,
@@ -31,6 +31,8 @@
31
31
  - bug / error / crash / triage / failing path → `.claude/skills/debugging-toolkit/SKILL.md`
32
32
  - test / spec / coverage / fixture → `.claude/skills/testing-quality/SKILL.md`
33
33
  - docs / README / changelog / handoff / editing `docs/` → `.claude/skills/docs-quality/SKILL.md`
34
+ - open-ended next step / project status / continue with no concrete target → `.claude/skills/next-step/SKILL.md`
35
+ - explicit handoff / wrap up / update `docs/STATUS.md` → `.claude/skills/update-status/SKILL.md`
34
36
  - auth / security / token / permission / validation / risky shell-path-delete-db work → `.claude/skills/discover-security/SKILL.md`
35
37
  - stale workspace / reinstall / cleanup / maintenance → `.claude/skills/repo-maintenance/SKILL.md`
36
38
 
@@ -41,7 +43,7 @@
41
43
  - If a concrete verification lane is needed, prefer `node .claude/ukit/index/verify-context.mjs ...`.
42
44
  - These helper/index commands are internal orchestration. Run them yourself when needed; never turn them into required end-user workflow.
43
45
 
44
- ## UKit v1.1.7 Shared Runtime
46
+ ## UKit v1.1.8 Shared Runtime
45
47
 
46
48
  - Shared runtime state lives in `.ukit/storage/`.
47
49
  - Treat `.ukit/storage/config.json` as the source of runtime toggles for compact, token pipeline, router, memory, and validation behavior.
@@ -59,9 +61,18 @@
59
61
  - **Trivial**: no docs, no index query unless the file target is unclear.
60
62
  - **Simple**: default to `docs/MEMORY.md` only; pull related files/tests with the resolver.
61
63
  - **Non-trivial**: read `docs/MEMORY.md` + `docs/PROJECT.md` + `docs/CODE_MAP.md`.
64
+ - `docs/STATUS.md`: read for open-ended status/continue prompts or meaningful continuation context; treat stale status as orientation only and verify against source/index.
62
65
  - `docs/WORKLOG.md`: only recent, relevant entries for continuation/debugging.
63
66
  - Follow routed verification policy: targeted first when localized, widen in order for shared/risky scope, ask before blanket broad runs when no related-test evidence exists.
64
67
 
68
+ ## Living Status Workflow
69
+
70
+ - `docs/STATUS.md` is compact current state, not a transcript and not source truth.
71
+ - When the user asks “what next?”, “continue”, or “project đang ở đâu?” without a concrete target, use the `next-step` skill and show a freshness cue (fresh / possibly stale / stale / missing).
72
+ - Concrete debug/implementation/review prompts beat open-ended wording; use the concrete skill first and only use status as background.
73
+ - After meaningful work, use `update-status` to record state, verification, blockers, and next candidates; skip trivial/no-state-change tasks.
74
+ - Detailed task context files such as `docs/context/<slug>.md` are a future extension, not required baseline workflow.
75
+
65
76
  ## Subagent Policy (internal only)
66
77
 
67
78
  - Default to direct execution for trivial/simple work.
@@ -29,6 +29,8 @@
29
29
  - bug / error / crash / triage → `.claude/skills/debugging-toolkit/SKILL.md`
30
30
  - test / spec / coverage → `.claude/skills/testing-quality/SKILL.md`
31
31
  - docs / README / changelog / handoff / editing `docs/` → `.claude/skills/docs-quality/SKILL.md`
32
+ - open-ended next step / project status / continue with no concrete target → `.claude/skills/next-step/SKILL.md`
33
+ - explicit handoff / wrap up / update `docs/STATUS.md` → `.claude/skills/update-status/SKILL.md`
32
34
  - auth / security / token / permission / validation → `.claude/skills/discover-security/SKILL.md`
33
35
  - stale workspace / reinstall / cleanup → `.claude/skills/repo-maintenance/SKILL.md`
34
36
 
@@ -40,7 +42,7 @@
40
42
  - **Do not ask normal contributors to run internal helper commands**; run them yourself or tell them to rerun `ukit install`.
41
43
  - Do not ask normal contributors to memorize `ukit doctor`, `ukit diff`, `ukit uninstall`, or `ukit index ...` unless they explicitly need maintainer/debug help.
42
44
 
43
- ## UKit v1.1.7 Shared Runtime
45
+ ## UKit v1.1.8 Shared Runtime
44
46
 
45
47
  - Shared runtime state lives in `.ukit/storage/`.
46
48
  - Treat `.ukit/storage/config.json` as the source of runtime toggles for compact, token pipeline, router, memory, and validation behavior.
@@ -56,9 +58,18 @@
56
58
  - **Trivial**: no docs.
57
59
  - **Simple**: `docs/MEMORY.md` only, plus resolver-selected files/tests.
58
60
  - **Non-trivial**: `docs/MEMORY.md` + `docs/PROJECT.md` + `docs/CODE_MAP.md`.
61
+ - `docs/STATUS.md`: use for open-ended status/continue prompts or meaningful continuation context; stale status is orientation only.
59
62
  - `docs/WORKLOG.md`: only recent relevant entries.
60
63
  - Follow routed verification policy: targeted first, widen only when risk/shared scope justifies it, ask before blanket broad runs.
61
64
 
65
+ ## Living Status Workflow
66
+
67
+ - `docs/STATUS.md` captures compact current state, active work, debug threads, blockers, verification, and next candidates.
68
+ - It is not source truth and must not replace source/index-first investigation.
69
+ - For “what next?” / “continue” prompts without a concrete target, use `next-step` and show a freshness cue before relying on the status file.
70
+ - For concrete debug/implementation/review prompts, keep the concrete workflow primary even if the user asks for an approach or next step.
71
+ - After meaningful work, use `update-status`; skip trivial/no-state-change tasks and avoid transcript-style noise.
72
+
62
73
  ## Selective Subagent Policy (internal only)
63
74
 
64
75
  - Keep direct execution as the default for trivial/simple work.
@@ -47,6 +47,7 @@ End users do not need to manage any of that manually.
47
47
  Complete these files before first serious use:
48
48
  - `docs/PROJECT.md`
49
49
  - `docs/MEMORY.md`
50
+ - `docs/STATUS.md`
50
51
  - `docs/WORKLOG.md`
51
52
 
52
53
  ### 4) Open your AI tool
@@ -96,6 +97,7 @@ ukit install
96
97
  Check that the docs baseline files exist and are filled in:
97
98
  - `docs/PROJECT.md`
98
99
  - `docs/MEMORY.md`
100
+ - `docs/STATUS.md`
99
101
  - `docs/WORKLOG.md`
100
102
 
101
103
  ---
@@ -44,7 +44,8 @@
44
44
 
45
45
  1. Run `ukit memory recall "<current task>"` for non-trivial work; reuse relevant `## Previous Context` before asking the user to restate prior decisions
46
46
  2. Read `docs/MEMORY.md` — architecture decisions, active constraints, known bugs
47
- 3. Read `docs/CODE_MAP.md` if it exists structural navigation index
48
- 4. Use the installed source-code index / routed helpers to localize the smallest relevant file + test set first
49
- 5. Scan recent `docs/WORKLOG.md` entries if continuing prior work
50
- 6. Verify understanding against source before acting — **docs orient, source is truth; keep the index-first workflow intact**
47
+ 3. Read `docs/STATUS.md` for open-ended status/continue prompts or meaningful continuation context; treat stale status as orientation only
48
+ 4. Read `docs/CODE_MAP.md` if it exists structural navigation index
49
+ 5. Use the installed source-code index / routed helpers to localize the smallest relevant file + test set first
50
+ 6. Scan recent `docs/WORKLOG.md` entries if continuing prior work
51
+ 7. Verify understanding against source before acting — **docs orient, source is truth; keep the index-first workflow intact**
@@ -0,0 +1,81 @@
1
+ # Project Status — {{project.name}}
2
+
3
+ > Living project state for AI sessions.
4
+ > Keep this compact: current state only, not a session transcript.
5
+ > Source code, tests, and the UKit index remain ground truth.
6
+
7
+ ## Freshness
8
+
9
+ - Last meaningful update: TODO YYYY-MM-DD HH:mm
10
+ - Updated by: TODO
11
+ - Status confidence: low
12
+ - Stale after: 72h
13
+
14
+ If this file is stale, AI must treat it as orientation only and verify against source/index before recommending or editing.
15
+
16
+ ## Snapshot
17
+
18
+ - Current focus: TODO
19
+ - Health: unknown
20
+ - Branch/state: TODO
21
+ - Release/version: TODO
22
+
23
+ ## Active Work
24
+
25
+ <!-- Keep only live work. Move finished work to Recently Completed or WORKLOG.md. -->
26
+
27
+ ### TODO work item
28
+
29
+ - Status: planned / in-progress / blocked / done
30
+ - Goal: TODO
31
+ - Done: TODO
32
+ - Remaining: TODO
33
+ - Files involved: TODO
34
+ - Verification: TODO
35
+ - Next action: TODO
36
+
37
+ ## Current Debug Threads
38
+
39
+ <!-- Detailed bug context belongs in docs/context/<task>.md when that exists. STATUS should only link/summarize. -->
40
+
41
+ ### TODO debug thread
42
+
43
+ - Status: investigating / root cause found / fixed / blocked
44
+ - Symptom: TODO
45
+ - Root cause: unknown
46
+ - Evidence: TODO
47
+ - Changed files: TODO
48
+ - Verification: TODO
49
+ - Remaining risk: TODO
50
+ - Next action: TODO
51
+
52
+ ## Decisions Pending
53
+
54
+ - [ ] TODO decision
55
+ - Context: TODO
56
+ - Options: TODO
57
+ - Recommended: TODO
58
+
59
+ ## Next Candidates
60
+
61
+ 1. TODO candidate
62
+ - Why now: TODO
63
+ - Expected files: TODO
64
+ - Verification: TODO
65
+ - Risk: TODO
66
+
67
+ ## Recently Completed
68
+
69
+ <!-- Max 10 compact lines. Use docs/WORKLOG.md for session history. -->
70
+
71
+ - TODO YYYY-MM-DD — summary — verification
72
+
73
+ ## Notes for Next AI Session
74
+
75
+ - Read first: docs/STATUS.md, then docs/CODE_MAP.md only if navigation is needed.
76
+ - Avoid: treating this file as source truth when it is stale or contradicted by code/tests.
77
+ - Known traps: keep concrete debug/implementation prompts on their specific workflow; do not turn them into global roadmap suggestions.
78
+
79
+ ## Future Candidate: Task Context Files
80
+
81
+ v1.2 candidate: task-scoped `docs/context/<slug>.md` files for granular bug/feature context. Keep this out of v1.1.8 scope unless a project already uses that folder.
@@ -14,6 +14,7 @@ UKit should handle:
14
14
  - hidden skill selection
15
15
  - source-code indexing
16
16
  - compact context selection
17
+ - living project status for open-ended continuation prompts
17
18
  - targeted verification
18
19
  - optional internal delegation when it is actually useful
19
20
 
@@ -127,6 +128,21 @@ Expected UKit behavior:
127
128
  2. use DuraOne references only when the repo actually matches that domain/shape
128
129
  3. keep the user away from manual skill selection
129
130
 
131
+ ### F) Continue / what next
132
+
133
+ User says:
134
+
135
+ ```text
136
+ Project đang ở đâu, làm gì tiếp?
137
+ ```
138
+
139
+ Expected UKit behavior:
140
+ 1. auto-load the hidden next-step lane
141
+ 2. read `docs/STATUS.md` first and show whether it is fresh, possibly stale, stale, or missing
142
+ 3. suggest only a few actionable next candidates
143
+ 4. if status is stale, verify with source/index before treating any candidate as authoritative
144
+ 5. if the prompt names a concrete bug/feature/review target, keep the concrete workflow primary instead of producing a global roadmap
145
+
130
146
  ---
131
147
 
132
148
  ## What users should NOT need to do
@@ -1,6 +1,6 @@
1
1
  # UKit Shared Runtime
2
2
 
3
- This folder stores shared UKit runtime state for v1.1.7 features.
3
+ This folder stores shared UKit runtime state for v1.1.8 features.
4
4
 
5
5
  - `storage/config.json` — runtime feature flags and defaults
6
6
  - `storage/cache/` — prompt-cache, compact history, compact pressure state, output summaries, and preserved raw tool outputs under `storage/cache/tee/`
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.7",
2
+ "version": "1.1.8",
3
3
  "agent": "claude-code",
4
4
  "compact": {
5
5
  "enabled": true,