litcodex-ai 0.3.16 → 0.3.18

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/README.md CHANGED
@@ -61,7 +61,7 @@ every success criterion passes. Durable loop state lives under `.litcodex/lit-lo
61
61
 
62
62
  LitCodex also ships a sibling family of triggers and phrases — `litwork`, `lit-plan`, `litgoal`,
63
63
  `review-work`, `litresearch`, plus `lit plan` / `lit review` / `lit research` / `lit goal` and the
64
- `lit start work` handoff — alongside a 25-skill library and hook components, all registered as a
64
+ `lit start work` handoff — alongside a 27-skill library and hook components, all registered as a
65
65
  single Codex plugin.
66
66
 
67
67
  The bundled `public-page-reader` skill adds a public-only Node stdlib runtime with safety preflight,
@@ -0,0 +1,83 @@
1
+ <lit-recap-mode>
2
+
3
+ **MANDATORY**: First user-visible line this turn MUST be exactly:
4
+ `🔥 LIT-RECAP ENABLED 🔥`
5
+
6
+ Print that line verbatim, then produce the recap. You are now in lit-recap: the
7
+ read-only work-RECAP surface. Your one job is to merge the durable LitCodex
8
+ ledgers with what you already know from THIS session and present one honest
9
+ Korean work recap under the locked headers below. You summarize; you never
10
+ advance the work.
11
+
12
+ # Read-only contract — 읽기 전용 (절대 규칙)
13
+ lit-recap은 읽기 전용이다. You MUST NOT write, create, edit, delete, or move any
14
+ file, ledger, or state; MUST NOT run any state-mutating command; and MUST NOT
15
+ bind, advance, or complete any goal. Reading files and summarizing is the entire
16
+ job. If the user wants to change or continue the work, point them to the
17
+ matching lit mode (`lit`, `litwork`, `litgoal`) — do not do it here.
18
+
19
+ # Step 1 — Read the durable ledgers (존재하는 것만 읽는다)
20
+ Read whichever of these exist in the project root with your read-only file
21
+ tools; silently skip any that are missing:
22
+
23
+ - `.litcodex/boulder.json` — work ledger: a `works` map (or a single object)
24
+ with `active_plan`, `plan_name`, `status` (`active|completed|paused|abandoned`),
25
+ `session_ids`, `worktree_path`.
26
+ - `.litcodex/lit-loop/brief.md` — the original task brief.
27
+ - `.litcodex/lit-loop/goals.json` — goals: each has `objective`, `status`
28
+ (`pending|in_progress|complete|failed|blocked`) and `successCriteria[]`
29
+ (each: `scenario`, `userModel`, `expectedEvidence`, `capturedEvidence`, `status`).
30
+ - `.litcodex/lit-loop/ledger.jsonl` — append-only event log, one JSON object per
31
+ line (`at`, `kind`, …).
32
+ - `.litcodex/lit-loop/evidence/` — captured real-surface evidence artifacts
33
+ (report their paths; do not modify them).
34
+ - `.litcodex/lit-loop/<sessionId>/…` — per-session copies of the same files,
35
+ when present.
36
+ - `.litcodex/start-work/ledger.jsonl` — start-work task ledger
37
+ (`task-completed` entries with evidence paths).
38
+
39
+ # Step 2 — Fold in the current session (하이브리드)
40
+ The ledgers are durable but blind to the live session. Merge in what actually
41
+ happened in THIS conversation — files touched, commands run, results observed,
42
+ decisions made — and reconcile: when the session state is newer than a ledger
43
+ entry, say so instead of pretending the ledger is current. Never invent items
44
+ that appear in neither source; an empty section stays under its header as
45
+ `없음`.
46
+
47
+ # Step 3 — Output template (헤더는 아래 문구 그대로, verbatim)
48
+
49
+ # 작업 리캡 (lit-recap)
50
+
51
+ ## ✅ 완료된 작업
52
+ - 완료 항목마다 기술 종류 태그를 앞에 붙인다: `[TypeScript]`, `[npm]`, `[docs]`,
53
+ `[test]` 등. 근거(원장 항목 또는 세션 관찰)가 있는 것만 적는다.
54
+
55
+ ## 🔄 진행 중
56
+ - 시작되었지만 끝나지 않은 작업과 현재 상태.
57
+
58
+ ## ⛔ 블로커
59
+ - 진행을 막고 있는 항목. `blocked`/`failed` 상태와 이유를 그대로 보고한다.
60
+
61
+ ## 📁 증거 경로
62
+ - `.litcodex/lit-loop/evidence/` 등 실제 존재하는 증거 파일 경로 목록.
63
+
64
+ ## ➡️ 다음 단계
65
+ - 원장과 세션 상태가 가리키는 가장 작은 다음 행동 1–3개.
66
+
67
+ # Language & brevity switches
68
+ - 기본 언어는 한국어다. Switch the whole recap to English ONLY when the prompt
69
+ carries `--en` / `--english` or asks naturally ("in English", "영어로").
70
+ - If the prompt carries `--brief` or asks naturally ("짧게"), output ONLY the
71
+ `## ⚡ 요약` digest — at most 5 lines covering done / in-progress / blockers /
72
+ next step — instead of the full template.
73
+ - 커밋 해시, 파일 경로, 패키지·명령 이름 같은 기술 토큰은 번역하지 말고 그대로
74
+ (verbatim) 쓴다.
75
+
76
+ # Stop rules
77
+ - Emit the recap and stop. Do NOT start implementing, testing, or planning the
78
+ next step you just recommended.
79
+ - If NO ledger file exists and the session carries no work state, say exactly
80
+ that under `# 작업 리캡 (lit-recap)` (모든 섹션 `없음`) rather than inventing
81
+ history.
82
+
83
+ </lit-recap-mode>
@@ -12,4 +12,6 @@ export declare const LITRESEARCH_DIRECTIVE_MARKER: "<litresearch-mode>";
12
12
  export declare const LITRESEARCH_DIRECTIVE_CLOSE: "</litresearch-mode>";
13
13
  export declare const START_WORK_DIRECTIVE_MARKER: "<start-work-mode>";
14
14
  export declare const START_WORK_DIRECTIVE_CLOSE: "</start-work-mode>";
15
+ export declare const LIT_RECAP_DIRECTIVE_MARKER: "<lit-recap-mode>";
16
+ export declare const LIT_RECAP_DIRECTIVE_CLOSE: "</lit-recap-mode>";
15
17
  export type LitLoopDirectiveMarker = typeof LIT_LOOP_DIRECTIVE_MARKER;
@@ -18,3 +18,5 @@ export const LITRESEARCH_DIRECTIVE_MARKER = "<litresearch-mode>";
18
18
  export const LITRESEARCH_DIRECTIVE_CLOSE = "</litresearch-mode>";
19
19
  export const START_WORK_DIRECTIVE_MARKER = "<start-work-mode>";
20
20
  export const START_WORK_DIRECTIVE_CLOSE = "</start-work-mode>";
21
+ export const LIT_RECAP_DIRECTIVE_MARKER = "<lit-recap-mode>";
22
+ export const LIT_RECAP_DIRECTIVE_CLOSE = "</lit-recap-mode>";
@@ -1,6 +1,6 @@
1
1
  import type { LitTriggerToken } from "./trigger.js";
2
2
  /** Lit-family modes. Multiple tokens may map to one mode (lit/litcodex/lit-loop → lit-loop). */
3
- export type LitMode = "lit-loop" | "litwork" | "lit-plan" | "litgoal" | "review-work" | "litresearch" | "start-work";
3
+ export type LitMode = "lit-loop" | "litwork" | "lit-plan" | "litgoal" | "review-work" | "litresearch" | "start-work" | "lit-recap";
4
4
  /** Per-mode routing spec: its marker pair (guard) + resolved directive path (loader). */
5
5
  export interface LitModeSpec {
6
6
  readonly mode: LitMode;
@@ -14,7 +14,7 @@
14
14
  //
15
15
  // Imports markers + the trigger token type only (no cycle: hook → modes → {markers, trigger}).
16
16
  import { fileURLToPath } from "node:url";
17
- import { LIT_LOOP_DIRECTIVE_CLOSE, LIT_LOOP_DIRECTIVE_MARKER, LIT_PLAN_DIRECTIVE_CLOSE, LIT_PLAN_DIRECTIVE_MARKER, LITGOAL_DIRECTIVE_CLOSE, LITGOAL_DIRECTIVE_MARKER, LITRESEARCH_DIRECTIVE_CLOSE, LITRESEARCH_DIRECTIVE_MARKER, LITWORK_DIRECTIVE_CLOSE, LITWORK_DIRECTIVE_MARKER, REVIEW_WORK_DIRECTIVE_CLOSE, REVIEW_WORK_DIRECTIVE_MARKER, START_WORK_DIRECTIVE_CLOSE, START_WORK_DIRECTIVE_MARKER, } from "./markers.js";
17
+ import { LIT_LOOP_DIRECTIVE_CLOSE, LIT_LOOP_DIRECTIVE_MARKER, LIT_PLAN_DIRECTIVE_CLOSE, LIT_PLAN_DIRECTIVE_MARKER, LIT_RECAP_DIRECTIVE_CLOSE, LIT_RECAP_DIRECTIVE_MARKER, LITGOAL_DIRECTIVE_CLOSE, LITGOAL_DIRECTIVE_MARKER, LITRESEARCH_DIRECTIVE_CLOSE, LITRESEARCH_DIRECTIVE_MARKER, LITWORK_DIRECTIVE_CLOSE, LITWORK_DIRECTIVE_MARKER, REVIEW_WORK_DIRECTIVE_CLOSE, REVIEW_WORK_DIRECTIVE_MARKER, START_WORK_DIRECTIVE_CLOSE, START_WORK_DIRECTIVE_MARKER, } from "./markers.js";
18
18
  /** Resolve a path relative to this module (percent-decoding, space/#/Hangul-safe). */
19
19
  function resolveFromHere(rel) {
20
20
  return fileURLToPath(new URL(rel, import.meta.url));
@@ -67,6 +67,12 @@ export const MODE_BY_TOKEN = Object.freeze({
67
67
  closeMarker: START_WORK_DIRECTIVE_CLOSE,
68
68
  directivePath: resolveFromHere("../directives/start-work.md"),
69
69
  }),
70
+ "lit-recap": Object.freeze({
71
+ mode: "lit-recap",
72
+ openMarker: LIT_RECAP_DIRECTIVE_MARKER,
73
+ closeMarker: LIT_RECAP_DIRECTIVE_CLOSE,
74
+ directivePath: resolveFromHere("../directives/lit-recap.md"),
75
+ }),
70
76
  });
71
77
  /** The mode spec for a matched token. Total over the token union (every token has a spec). */
72
78
  export function modeForToken(token) {
@@ -39,6 +39,8 @@ function tokenForSkillName(skillName) {
39
39
  return "litgoal";
40
40
  case "litresearch":
41
41
  return "litresearch";
42
+ case "lit-recap":
43
+ return "lit-recap";
42
44
  case "start-work":
43
45
  return "start-work";
44
46
  case "review-work":
@@ -1,5 +1,5 @@
1
1
  /** The accepted bounded lit-family tokens, longest-first (ordering is load-bearing — see below). */
2
- export type LitTriggerToken = "start-work" | "review-work" | "litresearch" | "lit-loop" | "lit-plan" | "litcodex" | "litgoal" | "litwork" | "lit";
2
+ export type LitTriggerToken = "start-work" | "review-work" | "litresearch" | "lit-recap" | "lit-loop" | "lit-plan" | "litcodex" | "litgoal" | "litwork" | "lit";
3
3
  /**
4
4
  * Frozen tuple of the accepted tokens in match-priority (longest-first) order.
5
5
  * Exported so tests and the mode router (modes.ts) can enumerate without re-deriving.
@@ -14,9 +14,12 @@ export declare const LIT_TRIGGER_TOKENS: readonly LitTriggerToken[];
14
14
  *
15
15
  * MUST NOT carry the /g or /y flag: a global regex retains `lastIndex` between calls and would
16
16
  * make `.test()` return alternating results for the same input. Longest-first alternation
17
- * (`start-work|review-work|litresearch|lit-loop|lit-plan|litcodex|litgoal|litwork|lit`) guarantees a longer family token wins over a
18
- * bare `lit` at the same start; the trailing-`-` lookahead means `lit work` (space) is a bare `lit`
19
- * while `litwork` (glued) is the work mode. No nested quantifiers / no backreferences ⇒ ReDoS-free.
17
+ * (`start-work|review-work|litresearch|lit-recap|lit-loop|lit-plan|litcodex|litrecap|litgoal|litwork|recap|리캡|lit`)
18
+ * guarantees a longer family token wins over a bare `lit` at the same start; the trailing-`-`
19
+ * lookahead means `lit work` (space) is a bare `lit` while `litwork` (glued) is the work mode.
20
+ * The `litrecap` / `recap` / `리캡` alternatives are ROUTING ALIASES normalized to the canonical
21
+ * `lit-recap` token by `matchLitTrigger` (they are not members of the token union).
22
+ * No nested quantifiers / no backreferences ⇒ ReDoS-free.
20
23
  */
21
24
  export declare const LIT_TRIGGER_PATTERN: RegExp;
22
25
  /** Structured result of a successful match. */
@@ -2,9 +2,10 @@
2
2
  //
3
3
  // Single source of truth for deciding whether a user prompt activates the LitCodex `lit-loop`
4
4
  // workflow. Pure, side-effect-free, Unicode-aware. Accepts the bounded tokens `lit`, `lit-loop`,
5
- // and `litcodex` (case-insensitive) and rejects every substring collision (`split`, `literal`,
6
- // `litmus`, `lithium`, `glitter`, `flit`, `slit`, `litter`, …) while respecting Korean (Hangul)
7
- // and English boundaries.
5
+ // and `litcodex` (case-insensitive), the sibling mode tokens (incl. `lit-recap` with its
6
+ // `litrecap` / `recap` / `리캡` aliases, all normalized to the single `lit-recap` token), and
7
+ // rejects every substring collision (`split`, `literal`, `litmus`, `lithium`, `glitter`, `flit`,
8
+ // `slit`, `litter`, `recapture`, …) while respecting Korean (Hangul) and English boundaries.
8
9
  //
9
10
  // This module imports NOTHING from `state-store`, `directive`, `guards`, `markers`, or
10
11
  // `codex-hook` (one-way: hook → trigger, never the reverse). It reads no files, touches no state,
@@ -18,6 +19,7 @@ export const LIT_TRIGGER_TOKENS = Object.freeze([
18
19
  "start-work",
19
20
  "review-work",
20
21
  "litresearch",
22
+ "lit-recap",
21
23
  "lit-loop",
22
24
  "lit-plan",
23
25
  "litcodex",
@@ -34,11 +36,14 @@ export const LIT_TRIGGER_TOKENS = Object.freeze([
34
36
  *
35
37
  * MUST NOT carry the /g or /y flag: a global regex retains `lastIndex` between calls and would
36
38
  * make `.test()` return alternating results for the same input. Longest-first alternation
37
- * (`start-work|review-work|litresearch|lit-loop|lit-plan|litcodex|litgoal|litwork|lit`) guarantees a longer family token wins over a
38
- * bare `lit` at the same start; the trailing-`-` lookahead means `lit work` (space) is a bare `lit`
39
- * while `litwork` (glued) is the work mode. No nested quantifiers / no backreferences ⇒ ReDoS-free.
39
+ * (`start-work|review-work|litresearch|lit-recap|lit-loop|lit-plan|litcodex|litrecap|litgoal|litwork|recap|리캡|lit`)
40
+ * guarantees a longer family token wins over a bare `lit` at the same start; the trailing-`-`
41
+ * lookahead means `lit work` (space) is a bare `lit` while `litwork` (glued) is the work mode.
42
+ * The `litrecap` / `recap` / `리캡` alternatives are ROUTING ALIASES normalized to the canonical
43
+ * `lit-recap` token by `matchLitTrigger` (they are not members of the token union).
44
+ * No nested quantifiers / no backreferences ⇒ ReDoS-free.
40
45
  */
41
- export const LIT_TRIGGER_PATTERN = /(?:^|[^\p{L}\p{N}_])(start-work|review-work|litresearch|lit-loop|lit-plan|litcodex|litgoal|litwork|lit)(?![\p{L}\p{N}_-])/iu;
46
+ export const LIT_TRIGGER_PATTERN = /(?:^|[^\p{L}\p{N}_])(start-work|review-work|litresearch|lit-recap|lit-loop|lit-plan|litcodex|litrecap|litgoal|litwork|recap|리캡|lit)(?![\p{L}\p{N}_-])/iu;
42
47
  const NOT_A_STRING = "lit trigger: prompt must be a string";
43
48
  /**
44
49
  * Returns true iff `prompt` contains at least one bounded lit trigger.
@@ -65,14 +70,18 @@ export function matchLitTrigger(prompt) {
65
70
  throw new TypeError(NOT_A_STRING);
66
71
  }
67
72
  const searchable = maskMarkdownCode(prompt);
68
- const scan = /(?:^|[^\p{L}\p{N}_])(start-work|review-work|litresearch|lit-loop|lit-plan|litcodex|litgoal|litwork|lit)(?![\p{L}\p{N}_-])/giu;
73
+ const scan = /(?:^|[^\p{L}\p{N}_])(start-work|review-work|litresearch|lit-recap|lit-loop|lit-plan|litcodex|litrecap|litgoal|litwork|recap|리캡|lit)(?![\p{L}\p{N}_-])/giu;
69
74
  for (const m of searchable.matchAll(scan)) {
70
75
  const raw = m[1];
71
76
  if (raw === undefined) {
72
77
  continue;
73
78
  }
74
79
  const index = (m.index ?? 0) + m[0].length - raw.length;
75
- const token = raw.toLowerCase();
80
+ const lowered = raw.toLowerCase();
81
+ // Canonicalize the recap routing aliases (D1): litrecap / recap / 리캡 → the lit-recap token.
82
+ const token = lowered === "litrecap" || lowered === "recap" || lowered === "리캡"
83
+ ? "lit-recap"
84
+ : lowered;
76
85
  if (isSlashCommandOrPathToken(prompt, index, token)) {
77
86
  continue;
78
87
  }
@@ -94,7 +103,7 @@ export function matchLitTrigger(prompt) {
94
103
  function naturalPhraseAfterLit(prompt, searchable, index, rawLength) {
95
104
  const start = index + rawLength;
96
105
  const rest = searchable.slice(start);
97
- const m = /^(\s+)(start\s+work|plan|review|research|goal)(?![\p{L}\p{N}_-])/iu.exec(rest);
106
+ const m = /^(\s+)(start\s+work|plan|review|research|goal|recap)(?![\p{L}\p{N}_-])/iu.exec(rest);
98
107
  if (m === null || m[1] === undefined || m[2] === undefined) {
99
108
  return null;
100
109
  }
@@ -105,6 +114,7 @@ function naturalPhraseAfterLit(prompt, searchable, index, rawLength) {
105
114
  review: "review-work",
106
115
  research: "litresearch",
107
116
  goal: "litgoal",
117
+ recap: "lit-recap",
108
118
  };
109
119
  const token = tokenByPhrase[normalized];
110
120
  if (token === undefined) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@litcodex/lit-loop",
3
- "version": "0.3.16",
3
+ "version": "0.3.18",
4
4
  "description": "LitCodex Lit-Loop runtime: durable repo-native multi-goal orchestration with embedded success criteria and observable evidence audit.",
5
5
  "type": "module",
6
6
  "bin": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "litcodex-ai",
3
- "version": "0.3.16",
3
+ "version": "0.3.18",
4
4
  "description": "Codex loop harness installer. Run `npx litcodex-ai install` to set up the LitCodex Codex platform: the bare `lit` hook and the durable lit-loop runtime.",
5
5
  "keywords": ["codex", "litcodex", "lit-loop", "ai-agents", "orchestration"],
6
6
  "author": "LitCodex Authors",
@@ -15,7 +15,7 @@
15
15
  },
16
16
  "files": ["bin", "dist", "model-catalog.json", "README.md", "LICENSE"],
17
17
  "dependencies": {
18
- "@litcodex/lit-loop": "0.3.16"
18
+ "@litcodex/lit-loop": "0.3.18"
19
19
  },
20
20
  "bundledDependencies": ["@litcodex/lit-loop"],
21
21
  "scripts": {