@ngockhoale/ukit 2.0.2 → 2.0.3

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
@@ -2,6 +2,17 @@
2
2
 
3
3
  All notable changes to UKit are documented here.
4
4
 
5
+ ## 2.0.3 - 2026-08-11
6
+
7
+ ### Added
8
+
9
+ - **`ukit memory propose "<text>" [--category <name>] [--project <id>]`** — the missing first step of the Project Pattern Learning loop. Wires the existing `proposePatternCandidate()` to the CLI so a candidate can actually be created; duplicate proposals of the same text return the existing pending entry instead of stacking.
10
+
11
+ ### Fixed
12
+
13
+ - **Project Pattern Learning was unreachable in every real install.** v2.0.0 shipped `ukit memory list --pending` / `approve` / `reject`, but nothing could create a candidate: `proposePatternCandidate()` had zero production callers, and the `project-learning` skill told the AI to import it from `src/core/memory/store.js` — a path that only exists inside the UKit repo, never in an installed project. The skill now points at the new CLI subcommand, and `tests/cli/memoryCommand.test.js` drives the loop through the CLI only, so a fix that works solely via a direct function import cannot make those tests pass.
14
+ - **The v2.0.0 handoff Interfaces block never shipped.** `Consumes`/`Produces` were added to the repo's own `docs/AI_HANDOFF/RULES.md` and `tasks/_TEMPLATE.md` but not to the `templates/docs/AI_HANDOFF/` copies that `ukit install` actually delivers, so installed projects got handoff docs without the feature the 2.0.0 changelog claims. Same dev-mirror divergence class as the 2.0.2 hard-cap hooks.
15
+
5
16
  ## 2.0.2 - 2026-08-11
6
17
 
7
18
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ngockhoale/ukit",
3
- "version": "2.0.2",
3
+ "version": "2.0.3",
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",
@@ -3,6 +3,7 @@ import {
3
3
  forgetMemoryItem,
4
4
  listMemoryItems,
5
5
  listPendingPatternCandidates,
6
+ proposePatternCandidate,
6
7
  resolvePatternCandidate,
7
8
  runProjectHygiene,
8
9
  } from '../../core/memory/store.js';
@@ -15,6 +16,15 @@ import fs from 'node:fs/promises';
15
16
 
16
17
  const HELP_FLAGS = new Set(['--help', '-h', 'help']);
17
18
 
19
+ function extractFlag(args, flag) {
20
+ const index = args.indexOf(flag);
21
+ if (index < 0) return { value: null, rest: args };
22
+ return {
23
+ value: args[index + 1] ?? null,
24
+ rest: [...args.slice(0, index), ...args.slice(index + 2)],
25
+ };
26
+ }
27
+
18
28
  async function listAllPendingPatternCandidates(projectRoot, runtimePaths) {
19
29
  let entries = [];
20
30
  try {
@@ -75,6 +85,26 @@ export async function runMemory({ projectRoot, argv = [] }) {
75
85
  return;
76
86
  }
77
87
 
88
+ if (subcommand === 'propose') {
89
+ const projectFlag = extractFlag(rest, '--project');
90
+ const categoryFlag = extractFlag(projectFlag.rest, '--category');
91
+ const text = categoryFlag.rest.join(' ').trim();
92
+ if (!text) {
93
+ throw new Error('Missing pattern text. Usage: ukit memory propose "<text>" [--category <name>] [--project <id>]');
94
+ }
95
+
96
+ const projectId = projectFlag.value ?? (await detectProjectContext(projectRoot)).project.name;
97
+ const candidate = await proposePatternCandidate(projectRoot, projectId, {
98
+ text,
99
+ category: categoryFlag.value,
100
+ detectedFrom: 'cli',
101
+ });
102
+
103
+ console.log(`[UKit] Proposed ${candidate.id} (${candidate.status}) for project ${projectId}.`);
104
+ console.log('[UKit] Review with `ukit memory list --pending`, then `ukit memory approve <id>`.');
105
+ return;
106
+ }
107
+
78
108
  if (subcommand === 'approve' || subcommand === 'reject') {
79
109
  const projectFlagIndex = rest.indexOf('--project');
80
110
  const explicitProjectId = projectFlagIndex >= 0 ? rest[projectFlagIndex + 1] : null;
@@ -186,7 +216,7 @@ export async function runMemory({ projectRoot, argv = [] }) {
186
216
 
187
217
  export function printMemoryHelp() {
188
218
  console.log('UKit Memory Commands');
189
- console.log('Usage: ukit memory <list|search|recall|forget|export|approve|reject|hygiene> [args]');
219
+ console.log('Usage: ukit memory <list|search|recall|forget|export|propose|approve|reject|hygiene> [args]');
190
220
  console.log('');
191
221
  console.log('Subcommands:');
192
222
  console.log(' list List memory items in shared .ukit/storage/memory');
@@ -195,6 +225,7 @@ export function printMemoryHelp() {
195
225
  console.log(' recall <task> Print a compact previous-context block for the current task');
196
226
  console.log(' forget <id> Remove one memory item by id');
197
227
  console.log(' export Print all memory as JSON');
228
+ console.log(' propose "<text>" [--category <name>] [--project <id>] Propose a project convention for human approval');
198
229
  console.log(' approve <id> [--project <id>] Approve a pending pattern candidate into project conventions');
199
230
  console.log(' reject <id> [--project <id>] Reject a pending pattern candidate');
200
231
  console.log(' hygiene [--project <id>] Run decision-conflict resolution + session archiving now');
@@ -18,7 +18,7 @@ One-off patterns are not conventions. Skip this for anything seen only once.
18
18
 
19
19
  ## What NOT to do
20
20
 
21
- Never write directly into `conventions`, and never mention this to the human as if it's already decided. Always propose through Task 10's storage path — call `proposePatternCandidate(projectRoot, projectId, candidate)` from `src/core/memory/store.js` (or, from a plain conversation, tell the human to check `ukit memory list --pending`). Phrase the candidate as one falsifiable sentence:
21
+ Never write directly into `conventions`, and never mention this to the human as if it's already decided. Always propose through the CLI — run `ukit memory propose "<text>" [--category <name>]`, then tell the human to check `ukit memory list --pending`. Phrase the candidate as one falsifiable sentence:
22
22
 
23
23
  - Good: "Use `ControlInput` from `src/components/` instead of raw `<input>` for form fields."
24
24
  - Bad: "This project seems to like custom inputs."
@@ -106,6 +106,8 @@ A task is `ready` only when it has:
106
106
  - Clear target files
107
107
  - Clear action
108
108
  - Dependencies stated
109
+ - **Interfaces** — Consumes/Produces với chữ ký thật (function/endpoint/type), không placeholder;
110
+ `(none)` hợp lệ nếu task không có input/output liên task
109
111
  - **Test Plan** (PLAN.md §4) — happy path + ≥1 edge case (+ regression test nếu fix bug); hoặc `N/A` kèm lý do
110
112
  - Verification command (lệnh executor sẽ chạy)
111
113
  - Acceptance criteria
@@ -2,7 +2,7 @@
2
2
 
3
3
  <!--
4
4
  Template cho mỗi task. Planner copy file này khi split PLAN.md sang task riêng.
5
- File này BẮT BUỘC giữ structure: Goal + Test Cases + Test Files + Verification + Acceptance.
5
+ File này BẮT BUỘC giữ structure: Goal + Test Cases + Test Files + Verification + Acceptance + Interfaces.
6
6
  Mọi AI (planner / executor / reviewer) đọc và ghi vào file NÀY. Không trao đổi ngoài file.
7
7
  -->
8
8
 
@@ -48,6 +48,17 @@ yarn test tests/path/to/file.test.js
48
48
 
49
49
  - (none) <!-- hoặc TASK-xxx phải done trước -->
50
50
 
51
+ ## Interfaces
52
+
53
+ <!--
54
+ Executor thường CHỈ thấy task file này, không thấy task khác. Block này là cách nó biết đúng
55
+ tên/kiểu mà task khác kỳ vọng — tránh lỗi kiểu "TASK-3 gọi clearLayers() nhưng TASK-7 lại gọi
56
+ clearFullLayers()". Ghi chữ ký thật (function/endpoint/type), không ghi placeholder.
57
+ -->
58
+
59
+ - Consumes: `<what this task uses from earlier tasks — exact function/endpoint signatures, types>` <!-- hoặc (none) -->
60
+ - Produces: `<what later tasks rely on from this task — exact function/endpoint signatures, types>` <!-- hoặc (none) -->
61
+
51
62
  ---
52
63
 
53
64
  ## Discussion