@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
|
@@ -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,131 @@ 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 taskQueueNext = hasTaskQueueNextSignal(lower, raw);
|
|
749
|
+
const docsSpecific = hasDocsSpecificTaskSignal(lower, raw, targetFile, { taskQueueNext });
|
|
750
|
+
const statusUpdate = hasStatusUpdateSignal(lower, raw);
|
|
751
|
+
const openEndedStatus = hasOpenEndedStatusSignal(lower, raw) || taskQueueNext;
|
|
752
|
+
const concreteTask = hasConcreteTaskSignal(lower, raw, targetFile, { taskQueueNext });
|
|
753
|
+
|
|
754
|
+
if (docsSpecific) {
|
|
755
|
+
return 'docs-specific';
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
if (statusUpdate) {
|
|
759
|
+
return 'status-update';
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
if (concreteTask && openEndedStatus) {
|
|
763
|
+
return 'scoped-advice';
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
if (openEndedStatus) {
|
|
767
|
+
return 'open-ended-status';
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
if (concreteTask) {
|
|
771
|
+
if (/\b(bug|debug|error|crash|broken|failing|stack trace|triage|fix|login|timeout)\b/.test(lower)) {
|
|
772
|
+
return 'debug-specific';
|
|
773
|
+
}
|
|
774
|
+
if (/\b(review|audit|diff|pr feedback|code review|kiem tra|soat)\b/.test(lower)) {
|
|
775
|
+
return 'review-specific';
|
|
776
|
+
}
|
|
777
|
+
if (/\b(implement|build|create|add|ship|deliver|refactor|integrate|integration|scaffold|feature)\b/.test(lower)) {
|
|
778
|
+
return 'implement-specific';
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
return null;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
function hasStatusUpdateSignal(lower, raw) {
|
|
786
|
+
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)
|
|
787
|
+
|| /\b(status\.md|project status).{0,64}\b(update|refresh|write|sync|record|capture|summarize|summarise)\b/.test(lower)
|
|
788
|
+
|| /\b(wrap up|handoff|end this session|ending this session|session summary|before final)\b/.test(lower)
|
|
789
|
+
|| /\b(cap nhat|ghi lai|tong ket|chot session|ban giao).{0,64}\b(status|trang thai|viec tiep theo)\b/.test(lower)
|
|
790
|
+
|| /\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);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
function hasOpenEndedStatusSignal(lower, raw) {
|
|
794
|
+
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)
|
|
795
|
+
|| /\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)
|
|
796
|
+
|| /\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);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
function hasTaskQueueNextSignal(lower, raw) {
|
|
800
|
+
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)
|
|
801
|
+
|| /\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);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
function hasConcreteTaskSignal(lower, raw, targetFile, { taskQueueNext = false } = {}) {
|
|
805
|
+
if (targetFile && !isStatusFileTarget(targetFile) && !(taskQueueNext && isTasksFileTarget(targetFile))) {
|
|
806
|
+
return true;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
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)
|
|
810
|
+
|| /\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);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
function hasDocsSpecificTaskSignal(lower, raw, targetFile, { taskQueueNext = false } = {}) {
|
|
814
|
+
if (!targetFile || !isDocsTarget(targetFile)) {
|
|
815
|
+
return /\b(clean tasks|cleanup tasks|prune tasks|dedupe tasks|clear completed tasks|dọn tasks|dọn task)\b/.test(lower)
|
|
816
|
+
|| /\b(dọn tasks|dọn task|dọn danh sách task|xóa task đã xong)\b/.test(raw);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
if (taskQueueNext && isTasksFileTarget(targetFile) && !/\b(clean|cleanup|prune|dedupe|edit|template|wording|format|structure)\b/.test(lower)) {
|
|
820
|
+
return false;
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
const targetName = path.posix.basename(String(targetFile || '').replaceAll('\\', '/')).toLowerCase();
|
|
824
|
+
const explicitStatusUpdate = hasExplicitStatusUpdateSignal(lower, raw);
|
|
825
|
+
|
|
826
|
+
if (!isStatusFileTarget(targetFile)) {
|
|
827
|
+
if (explicitStatusUpdate && !mentionsTargetDoc(lower, targetName)) {
|
|
828
|
+
return false;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
return mentionsTargetDoc(lower, targetName)
|
|
832
|
+
|| /\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)
|
|
833
|
+
|| /\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);
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
return /\b(template|wording|edit|copy|grammar|format|structure|heading|section|docs?)\b/.test(lower)
|
|
837
|
+
|| /\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);
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
function hasExplicitStatusUpdateSignal(lower, raw) {
|
|
841
|
+
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)
|
|
842
|
+
|| /\b(status\.md|project status).{0,64}\b(update|refresh|write|sync|record|capture|summarize|summarise)\b/.test(lower)
|
|
843
|
+
|| /\b(cap nhat|ghi lai|tong ket|chot session|ban giao).{0,64}\b(status|trang thai|viec tiep theo)\b/.test(lower)
|
|
844
|
+
|| /\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);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
function mentionsTargetDoc(lower, targetName) {
|
|
848
|
+
if (!targetName) {
|
|
849
|
+
return false;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
const escaped = targetName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
853
|
+
const withoutExt = escaped.replace(/\\\.md$/i, '');
|
|
854
|
+
return new RegExp(`\\b(?:${escaped}|${withoutExt})\\b`, 'i').test(lower);
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
function isStatusFileTarget(targetFile) {
|
|
858
|
+
return /(?:^|\/)docs\/STATUS\.md$|(?:^|\/)STATUS\.md$/i.test(String(targetFile || ''));
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
function isTasksFileTarget(targetFile) {
|
|
862
|
+
return /(?:^|\/)docs\/TASKS\.md$|(?:^|\/)TASKS\.md$/i.test(String(targetFile || ''));
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
function isDocsTarget(targetFile) {
|
|
866
|
+
const normalized = String(targetFile || '').replaceAll('\\', '/');
|
|
867
|
+
return /(?:^|\/)docs\/.+\.md$|(?:^|\/)(?:README|CHANGELOG|AGENTS|CLAUDE|STATUS)\.md$/i.test(normalized);
|
|
868
|
+
}
|
|
869
|
+
|
|
721
870
|
function shouldUseIndexedContext({ activeSkills = [], targetFile = null } = {}) {
|
|
722
871
|
if (activeSkills.length === 0) {
|
|
723
872
|
return Boolean(targetFile);
|
|
@@ -966,6 +1115,16 @@ function deriveDelegationRecommendation({
|
|
|
966
1115
|
const hasRelatedTests = (preview.relatedTests ?? []).length > 0;
|
|
967
1116
|
const when = contextRecommendation?.command ? 'after-context' : 'now';
|
|
968
1117
|
|
|
1118
|
+
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)
|
|
1119
|
+
&& /\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);
|
|
1120
|
+
if (smallTaskMaintenanceSignal) {
|
|
1121
|
+
return {
|
|
1122
|
+
hint: 'ukit-small-task-maintainer',
|
|
1123
|
+
when,
|
|
1124
|
+
reason: 'Low-risk UKit maintenance decisions should use the configured small-task model without blocking the main AI flow.',
|
|
1125
|
+
};
|
|
1126
|
+
}
|
|
1127
|
+
|
|
969
1128
|
if (routingContext.taskType === 'trivial') {
|
|
970
1129
|
return null;
|
|
971
1130
|
}
|
|
@@ -1055,6 +1214,7 @@ function buildRouteSummary({
|
|
|
1055
1214
|
formatCompactSegment('targets', primaryTargets),
|
|
1056
1215
|
formatCompactSegment('tests', relatedTests),
|
|
1057
1216
|
formatCompactSegment('styles', styleFiles),
|
|
1217
|
+
delegationRecommendation?.hint ? `delegate=${delegationRecommendation.hint}` : null,
|
|
1058
1218
|
policyMode ? `policy=${policyMode}` : null,
|
|
1059
1219
|
].filter(Boolean).join(' | ');
|
|
1060
1220
|
|
|
@@ -1063,6 +1223,7 @@ function buildRouteSummary({
|
|
|
1063
1223
|
fallbackCommands,
|
|
1064
1224
|
preferredOrder,
|
|
1065
1225
|
policyMode,
|
|
1226
|
+
intentMode: routingContext.intentMode ?? null,
|
|
1066
1227
|
delegateHint: delegationRecommendation?.hint ?? null,
|
|
1067
1228
|
nextActionType: nextAction?.type ?? null,
|
|
1068
1229
|
nextActionCommand,
|
|
@@ -1580,6 +1741,7 @@ function compactRoutingContext(routingContext = {}) {
|
|
|
1580
1741
|
adapter: routingContext.adapter ?? 'claude',
|
|
1581
1742
|
lastExplicitUserPromptText: routingContext.lastExplicitUserPromptText ?? '',
|
|
1582
1743
|
taskType: routingContext.taskType ?? null,
|
|
1744
|
+
intentMode: routingContext.intentMode ?? null,
|
|
1583
1745
|
};
|
|
1584
1746
|
}
|
|
1585
1747
|
|
|
@@ -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
|
|
15
|
+
## UKit v1.2.1 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.
|
|
@@ -23,12 +23,15 @@ Auto-generated by UKit for OpenAI Codex.
|
|
|
23
23
|
- Maintainers can inspect runtime state with `ukit status` and `ukit memory export`.
|
|
24
24
|
- Reuse compact `previous-context` / `recent-output` route snapshots before replaying raw history.
|
|
25
25
|
- Threshold-based compact pressure is internal orchestration; Codex users should not need to manage it manually.
|
|
26
|
+
- UKit keeps Claude PreCompact/reinject and OpenCode native auto/prune compaction intact. For Codex Desktop long sessions, UKit can use `UKIT_SMALL_TASK_MODEL` through `ukit-small-task-maintainer` to decide soft auto-compact handoffs. Default `UKIT_CODEX_COMPACT_TARGET=150` means about 150 compact handoff lines (120-150 preferred, hard max 170), not 150 app-context tokens.
|
|
26
27
|
|
|
27
28
|
## Speed / Reading Contract
|
|
28
29
|
|
|
29
30
|
- **Trivial**: no docs.
|
|
30
31
|
- **Simple**: `docs/MEMORY.md` only.
|
|
31
32
|
- **Non-trivial**: `docs/MEMORY.md` + `docs/PROJECT.md` + `docs/CODE_MAP.md`.
|
|
33
|
+
- `docs/STATUS.md`: read for open-ended status/continue prompts or meaningful continuation context; stale status is orientation only.
|
|
34
|
+
- `docs/TASKS.md`: read only for queued-task prompts or when status points at queued work; safely clean exact duplicates/completed overflow by default without deleting unfinished human-authored tasks.
|
|
32
35
|
- Read `docs/WORKLOG.md` only when recent continuation/debug context matters.
|
|
33
36
|
- Source is truth; if docs are stale, update docs and continue.
|
|
34
37
|
|
|
@@ -52,6 +55,9 @@ For clearly non-code specialist lanes, avoid dragging the source-code index into
|
|
|
52
55
|
- Match from prompt wording plus tool/file evidence.
|
|
53
56
|
- Use the smallest useful set, usually 1-2 skills.
|
|
54
57
|
- If docs work is detected, prefer `.codex/skills/docs-quality/SKILL.md`.
|
|
58
|
+
- For open-ended “what next?” / “continue” / project-status / queued-task prompts, prefer `.codex/skills/next-step/SKILL.md` and show a status freshness cue when status is used.
|
|
59
|
+
- For explicit handoff/wrap-up/status updates, prefer `.codex/skills/update-status/SKILL.md`.
|
|
60
|
+
- Concrete debug/implementation/review prompts beat open-ended wording; do not let `next-step` replace the concrete workflow.
|
|
55
61
|
- If routing is complex or ambiguous, prefer `node .codex/ukit/index/route-task.mjs "<prompt>" [--tool-command <cmd>] [--target <file>]`.
|
|
56
62
|
- 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
63
|
- When route memory already includes `previous-context` or `recent-output`, reuse it before widening reads or logs.
|
|
@@ -68,6 +74,8 @@ For clearly non-code specialist lanes, avoid dragging the source-code index into
|
|
|
68
74
|
## Docs Discipline
|
|
69
75
|
|
|
70
76
|
After significant work, update only what changed:
|
|
77
|
+
- `docs/STATUS.md` — compact current state, blockers, verification, next candidates
|
|
78
|
+
- `docs/TASKS.md` — local AI task queue; remove duplicates/prune completed overflow safely, never delete unfinished human intent by default
|
|
71
79
|
- `docs/WORKLOG.md`
|
|
72
80
|
- `docs/MEMORY.md`
|
|
73
81
|
- `docs/CODE_MAP.md`
|
|
@@ -33,9 +33,18 @@
|
|
|
33
33
|
"maxAnalogFiles": 3,
|
|
34
34
|
"maxSharedAbstractions": 2,
|
|
35
35
|
"contextBudgetByTier": {
|
|
36
|
-
"trivial": {
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
"trivial": {
|
|
37
|
+
"minFiles": 1,
|
|
38
|
+
"maxFiles": 2
|
|
39
|
+
},
|
|
40
|
+
"simple": {
|
|
41
|
+
"minFiles": 2,
|
|
42
|
+
"maxFiles": 5
|
|
43
|
+
},
|
|
44
|
+
"non-trivial": {
|
|
45
|
+
"minFiles": 4,
|
|
46
|
+
"maxFiles": 8
|
|
47
|
+
}
|
|
39
48
|
}
|
|
40
49
|
},
|
|
41
50
|
"skillRouter": {
|
|
@@ -65,6 +74,12 @@
|
|
|
65
74
|
],
|
|
66
75
|
"maintenance": [
|
|
67
76
|
"repo-maintenance"
|
|
77
|
+
],
|
|
78
|
+
"nextStep": [
|
|
79
|
+
"next-step"
|
|
80
|
+
],
|
|
81
|
+
"statusUpdate": [
|
|
82
|
+
"update-status"
|
|
68
83
|
]
|
|
69
84
|
},
|
|
70
85
|
"toolSignals": {
|
|
@@ -89,7 +104,8 @@
|
|
|
89
104
|
},
|
|
90
105
|
"routingRule": {
|
|
91
106
|
"endUserShouldNotNeedSkillNames": true,
|
|
92
|
-
"selectSmallestUsefulSkillSet": true
|
|
107
|
+
"selectSmallestUsefulSkillSet": true,
|
|
108
|
+
"concreteTaskBeatsOpenEndedStatus": true
|
|
93
109
|
},
|
|
94
110
|
"delegationBridge": {
|
|
95
111
|
"enabled": true,
|
|
@@ -130,6 +146,119 @@
|
|
|
130
146
|
"askBeforeBroadVerificationWithoutRelatedTests": true,
|
|
131
147
|
"preferCommandOrderFromVerificationPlan": true
|
|
132
148
|
}
|
|
149
|
+
},
|
|
150
|
+
"smallTaskModel": {
|
|
151
|
+
"env": "UKIT_SMALL_TASK_MODEL",
|
|
152
|
+
"default": "unic-lite",
|
|
153
|
+
"agent": "ukit-small-task-maintainer",
|
|
154
|
+
"useFor": [
|
|
155
|
+
"task-cleanup",
|
|
156
|
+
"compact-decision",
|
|
157
|
+
"codex-context-budget",
|
|
158
|
+
"doc-summarization",
|
|
159
|
+
"classification",
|
|
160
|
+
"small-decision",
|
|
161
|
+
"auto-triage",
|
|
162
|
+
"queue-maintenance",
|
|
163
|
+
"workspace-maintenance"
|
|
164
|
+
],
|
|
165
|
+
"keepMainModelFor": [
|
|
166
|
+
"security",
|
|
167
|
+
"risky-code-change",
|
|
168
|
+
"release",
|
|
169
|
+
"data-loss",
|
|
170
|
+
"architecture-decision",
|
|
171
|
+
"deep-reasoning"
|
|
172
|
+
],
|
|
173
|
+
"internalOnly": true,
|
|
174
|
+
"decisionPolicy": {
|
|
175
|
+
"nonBlocking": true,
|
|
176
|
+
"endUserInvisible": true,
|
|
177
|
+
"handBackOnRisk": true,
|
|
178
|
+
"optimizeOrder": [
|
|
179
|
+
"quality",
|
|
180
|
+
"safety",
|
|
181
|
+
"speed",
|
|
182
|
+
"token-discipline"
|
|
183
|
+
],
|
|
184
|
+
"decisions": [
|
|
185
|
+
"fast-vs-slow-lane",
|
|
186
|
+
"safe-vs-risky-lane",
|
|
187
|
+
"skill-routing-needed",
|
|
188
|
+
"step-budget-enough",
|
|
189
|
+
"compact-now-or-later",
|
|
190
|
+
"summarize-docs-or-keep-detail"
|
|
191
|
+
],
|
|
192
|
+
"stepBudgets": {
|
|
193
|
+
"trivial": {
|
|
194
|
+
"maxSteps": 1,
|
|
195
|
+
"verification": "skip-unless-risky"
|
|
196
|
+
},
|
|
197
|
+
"simple": {
|
|
198
|
+
"maxSteps": 2,
|
|
199
|
+
"verification": "targeted-if-covered"
|
|
200
|
+
},
|
|
201
|
+
"nonTrivial": {
|
|
202
|
+
"maxSteps": 4,
|
|
203
|
+
"verification": "targeted-then-widen-on-risk"
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
"executionMode": "sidecar-parallel",
|
|
207
|
+
"mustNotBlockMainTask": true,
|
|
208
|
+
"maxSidecarWaitMs": 0
|
|
209
|
+
},
|
|
210
|
+
"codexContext": {
|
|
211
|
+
"autoCompact": true,
|
|
212
|
+
"budgetTokens": 60000,
|
|
213
|
+
"compactTarget": 150,
|
|
214
|
+
"compactTargetUnit": "lines",
|
|
215
|
+
"targetEnv": "UKIT_CODEX_COMPACT_TARGET",
|
|
216
|
+
"budgetEnv": "UKIT_CODEX_CONTEXT_BUDGET",
|
|
217
|
+
"autoCompactEnv": "UKIT_CODEX_AUTO_COMPACT",
|
|
218
|
+
"mode": "soft-handoff",
|
|
219
|
+
"preserve": [
|
|
220
|
+
"current-goal",
|
|
221
|
+
"non-negotiable-rules",
|
|
222
|
+
"active-files",
|
|
223
|
+
"decisions",
|
|
224
|
+
"unresolved-failures",
|
|
225
|
+
"verification-evidence",
|
|
226
|
+
"next-actions"
|
|
227
|
+
],
|
|
228
|
+
"compactTargetRecommendedRange": [
|
|
229
|
+
120,
|
|
230
|
+
170
|
|
231
|
+
],
|
|
232
|
+
"compactTargetMax": 170
|
|
233
|
+
},
|
|
234
|
+
"agentContext": {
|
|
235
|
+
"preserveClaudePreCompact": true,
|
|
236
|
+
"preserveOpenCodeCompaction": true,
|
|
237
|
+
"codexSoftHandoff": {
|
|
238
|
+
"autoCompact": true,
|
|
239
|
+
"budgetTokens": 60000,
|
|
240
|
+
"compactTarget": 150,
|
|
241
|
+
"compactTargetUnit": "lines",
|
|
242
|
+
"targetEnv": "UKIT_CODEX_COMPACT_TARGET",
|
|
243
|
+
"budgetEnv": "UKIT_CODEX_CONTEXT_BUDGET",
|
|
244
|
+
"autoCompactEnv": "UKIT_CODEX_AUTO_COMPACT",
|
|
245
|
+
"mode": "soft-handoff",
|
|
246
|
+
"preserve": [
|
|
247
|
+
"current-goal",
|
|
248
|
+
"non-negotiable-rules",
|
|
249
|
+
"active-files",
|
|
250
|
+
"decisions",
|
|
251
|
+
"unresolved-failures",
|
|
252
|
+
"verification-evidence",
|
|
253
|
+
"next-actions"
|
|
254
|
+
],
|
|
255
|
+
"compactTargetRecommendedRange": [
|
|
256
|
+
120,
|
|
257
|
+
170
|
|
258
|
+
],
|
|
259
|
+
"compactTargetMax": 170
|
|
260
|
+
}
|
|
261
|
+
}
|
|
133
262
|
}
|
|
134
263
|
},
|
|
135
264
|
"execution": {
|
|
@@ -151,7 +280,7 @@
|
|
|
151
280
|
"autoAllowInWorkspaceOnly": [
|
|
152
281
|
"build",
|
|
153
282
|
"format",
|
|
154
|
-
|
|
283
|
+
"safe file writes"
|
|
155
284
|
]
|
|
156
285
|
},
|
|
157
286
|
"high": {
|
package/templates/.gitignore
CHANGED
package/templates/AGENTS.md
CHANGED
|
@@ -30,7 +30,9 @@
|
|
|
30
30
|
- review / audit / diff / PR feedback → `.claude/skills/code-review/SKILL.md`
|
|
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
|
-
- docs / README / changelog / handoff / editing `docs/` → `.claude/skills/docs-quality/SKILL.md`
|
|
33
|
+
- docs / README / changelog / handoff / editing `docs/` / cleaning `docs/TASKS.md` → `.claude/skills/docs-quality/SKILL.md`
|
|
34
|
+
- open-ended next step / project status / continue with no concrete target / choose queued task → `.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
|
|
46
|
+
## UKit v1.2.1 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,28 @@
|
|
|
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.
|
|
65
|
+
- `docs/TASKS.md`: read only for queued-task prompts or when status points at queued work; safely clean exact duplicates/completed overflow by default without deleting unfinished human-authored tasks.
|
|
62
66
|
- `docs/WORKLOG.md`: only recent, relevant entries for continuation/debugging.
|
|
63
67
|
- 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
68
|
|
|
69
|
+
## Living Status Workflow
|
|
70
|
+
|
|
71
|
+
- `docs/STATUS.md` is compact current state, not a transcript and not source truth.
|
|
72
|
+
- 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).
|
|
73
|
+
- Concrete debug/implementation/review prompts beat open-ended wording; use the concrete skill first and only use status as background.
|
|
74
|
+
- After meaningful work, use `update-status` to record state, verification, blockers, and next candidates; skip trivial/no-state-change tasks.
|
|
75
|
+
- `docs/TASKS.md` is a local AI task queue: prefer `Ready for AI` when asked to pick queued work, and clean duplicates/prune `Done Recently` safely when reading/updating it.
|
|
76
|
+
- Detailed task context files such as `docs/context/<slug>.md` are a future extension, not required baseline workflow.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
## Small-Task Maintainer (internal)
|
|
80
|
+
|
|
81
|
+
- UKit may route low-risk internal decisions to the `ukit-small-task-maintainer` subagent using `UKIT_SMALL_TASK_MODEL` (default `unic-lite`).
|
|
82
|
+
- Use it for safe/reversible UKit chores: dọn `docs/TASKS.md`, queued-task classification, fast-vs-slow/safe-vs-risky lane decisions, skill-routing/step-budget hints, agent context-budget decisions, compact/summary decisions, docs/status summarization, auto-triage, queue maintenance, and small workspace cleanup.
|
|
83
|
+
- Run it as a sidecar/parallel lane only; do not block, replace, or slow the user task. Do not block the main AI flow: if the small-task lane sees security, risky/shared code, release/publish, data-loss, architecture, deep-reasoning risk, weak context, or quality risk, it hands back to the main model instead of asking the end user to decide.
|
|
84
|
+
- This is optional internal orchestration config from `.claude/ukit/.env` / `.ukit/storage/config.json`; never turn it into an end-user workflow. End users still only need `ukit install` and natural-language product work. Always preserve the CoDev priority: quality > safety > speed > token discipline. Keep Claude PreCompact/reinject and OpenCode native auto/prune compaction enabled. For Codex Desktop long sessions, `UKIT_CODEX_COMPACT_TARGET` defaults to 150 compact handoff lines (120-150 preferred, hard max 170), decided internally by the small-task maintainer.
|
|
85
|
+
|
|
65
86
|
## Subagent Policy (internal only)
|
|
66
87
|
|
|
67
88
|
- Default to direct execution for trivial/simple work.
|
package/templates/CLAUDE.md
CHANGED
|
@@ -28,7 +28,9 @@
|
|
|
28
28
|
- review / audit / diff → `.claude/skills/code-review/SKILL.md`
|
|
29
29
|
- bug / error / crash / triage → `.claude/skills/debugging-toolkit/SKILL.md`
|
|
30
30
|
- test / spec / coverage → `.claude/skills/testing-quality/SKILL.md`
|
|
31
|
-
- docs / README / changelog / handoff / editing `docs/` → `.claude/skills/docs-quality/SKILL.md`
|
|
31
|
+
- docs / README / changelog / handoff / editing `docs/` / cleaning `docs/TASKS.md` → `.claude/skills/docs-quality/SKILL.md`
|
|
32
|
+
- open-ended next step / project status / continue with no concrete target / choose queued task → `.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
|
|
45
|
+
## UKit v1.2.1 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,28 @@
|
|
|
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.
|
|
62
|
+
- `docs/TASKS.md`: use only for queued-task prompts or when status points at queued work; safely clean exact duplicates/completed overflow by default without deleting unfinished human-authored tasks.
|
|
59
63
|
- `docs/WORKLOG.md`: only recent relevant entries.
|
|
60
64
|
- Follow routed verification policy: targeted first, widen only when risk/shared scope justifies it, ask before blanket broad runs.
|
|
61
65
|
|
|
66
|
+
## Living Status Workflow
|
|
67
|
+
|
|
68
|
+
- `docs/STATUS.md` captures compact current state, active work, debug threads, blockers, verification, and next candidates.
|
|
69
|
+
- It is not source truth and must not replace source/index-first investigation.
|
|
70
|
+
- For “what next?” / “continue” prompts without a concrete target, use `next-step` and show a freshness cue before relying on the status file.
|
|
71
|
+
- For concrete debug/implementation/review prompts, keep the concrete workflow primary even if the user asks for an approach or next step.
|
|
72
|
+
- After meaningful work, use `update-status`; skip trivial/no-state-change tasks and avoid transcript-style noise.
|
|
73
|
+
- `docs/TASKS.md` is a local AI task queue: prefer `Ready for AI` when asked to pick queued work, and clean duplicates/prune `Done Recently` safely when reading/updating it.
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
## Small-Task Maintainer (internal)
|
|
77
|
+
|
|
78
|
+
- UKit may route low-risk internal decisions to the `ukit-small-task-maintainer` subagent using `UKIT_SMALL_TASK_MODEL` (default `unic-lite`).
|
|
79
|
+
- Use it for safe/reversible UKit chores: dọn `docs/TASKS.md`, queued-task classification, fast-vs-slow/safe-vs-risky lane decisions, skill-routing/step-budget hints, agent context-budget decisions, compact/summary decisions, docs/status summarization, auto-triage, queue maintenance, and small workspace cleanup.
|
|
80
|
+
- Run it as a sidecar/parallel lane only; do not block, replace, or slow the user task. Do not block the main AI flow: if the small-task lane sees security, risky/shared code, release/publish, data-loss, architecture, deep-reasoning risk, weak context, or quality risk, it hands back to the main model instead of asking the end user to decide.
|
|
81
|
+
- This is optional internal orchestration config from `.claude/ukit/.env` / `.ukit/storage/config.json`; never turn it into an end-user workflow. End users still only need `ukit install` and natural-language product work. Always preserve the CoDev priority: quality > safety > speed > token discipline. Keep Claude PreCompact/reinject and OpenCode native auto/prune compaction enabled. For Codex Desktop long sessions, `UKIT_CODEX_COMPACT_TARGET` defaults to 150 compact handoff lines (120-150 preferred, hard max 170), decided internally by the small-task maintainer.
|
|
82
|
+
|
|
62
83
|
## Selective Subagent Policy (internal only)
|
|
63
84
|
|
|
64
85
|
- Keep direct execution as the default for trivial/simple work.
|
|
@@ -47,6 +47,8 @@ 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`
|
|
51
|
+
- `docs/TASKS.md`
|
|
50
52
|
- `docs/WORKLOG.md`
|
|
51
53
|
|
|
52
54
|
### 4) Open your AI tool
|
|
@@ -96,6 +98,8 @@ ukit install
|
|
|
96
98
|
Check that the docs baseline files exist and are filled in:
|
|
97
99
|
- `docs/PROJECT.md`
|
|
98
100
|
- `docs/MEMORY.md`
|
|
101
|
+
- `docs/STATUS.md`
|
|
102
|
+
- `docs/TASKS.md`
|
|
99
103
|
- `docs/WORKLOG.md`
|
|
100
104
|
|
|
101
105
|
---
|
|
@@ -44,7 +44,9 @@
|
|
|
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/
|
|
48
|
-
4.
|
|
49
|
-
5.
|
|
50
|
-
6.
|
|
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/TASKS.md` only when selecting queued AI work, or when status points at queued tasks; apply safe cleanup without deleting unfinished human intent
|
|
49
|
+
5. Read `docs/CODE_MAP.md` if it exists — structural navigation index
|
|
50
|
+
6. Use the installed source-code index / routed helpers to localize the smallest relevant file + test set first
|
|
51
|
+
7. Scan recent `docs/WORKLOG.md` entries if continuing prior work
|
|
52
|
+
8. Verify understanding against source before acting — **docs orient, source is truth; keep the index-first workflow intact**
|