@orderful/droid 0.34.1 → 0.35.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.
@@ -61,7 +61,7 @@
61
61
  {
62
62
  "name": "droid-codex",
63
63
  "description": "Shared organizational knowledge - PRDs, tech designs, domains, proposals, patterns, and explored topics. Use when loading project context, searching codex, capturing decisions, or creating new entries.",
64
- "version": "0.1.10",
64
+ "version": "0.2.1",
65
65
  "source": {
66
66
  "source": "github",
67
67
  "repo": "orderful/droid",
package/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # @orderful/droid
2
2
 
3
+ ## 0.35.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#211](https://github.com/Orderful/droid/pull/211) [`6df8a25`](https://github.com/Orderful/droid/commit/6df8a2511a1680bec65618d0f5e6e684811cd922) Thanks [@frytyler](https://github.com/frytyler)! - Bump codex tool version to force reinstall with fixed subdirectory copying
8
+
9
+ Users who installed codex 0.2.0 before the fix would be missing references/review/ subdirectory. Bumping to 0.2.1 ensures they get the complete installation with all reference files.
10
+
11
+ - [#211](https://github.com/Orderful/droid/pull/211) [`6df8a25`](https://github.com/Orderful/droid/commit/6df8a2511a1680bec65618d0f5e6e684811cd922) Thanks [@frytyler](https://github.com/frytyler)! - Fix skill installation not copying reference and script subdirectories
12
+
13
+ The installSkill() function was only copying top-level files from references/ and scripts/ directories, causing subdirectories to be skipped. This blocked the /codex review feature which relies on references/review/workflow.md.
14
+
15
+ Added a generic copyDirectoryRecursive() helper that preserves directory structure while maintaining the existing file type filters (.md for references, .ts/.js/.py for scripts). Applied to both references/ and scripts/ copying.
16
+
17
+ ## 0.35.0
18
+
19
+ ### Minor Changes
20
+
21
+ - [#209](https://github.com/Orderful/droid/pull/209) [`74cbdbb`](https://github.com/Orderful/droid/commit/74cbdbba131741412f3a5d490472ff8b4c22e286) Thanks [@frytyler](https://github.com/frytyler)! - feat(codex): add review skill for conversational document reviews
22
+
23
+ New capability for reviewing structured documents (tech designs, PRDs) conversationally in the CLI.
24
+
25
+ Features:
26
+ - Generic review workflow for structured docs
27
+ - Tech design document type support
28
+ - Section-based navigation ("Show me the rollout section")
29
+ - Context search in thought docs ("Why was X rejected?")
30
+ - MVP scope (read-only, CLI navigation)
31
+
32
+ Commands:
33
+ - `/codex review {type} --pr {number}` - Load and review a PR
34
+
3
35
  ## 0.34.1
4
36
 
5
37
  ### Patch Changes
package/dist/bin/droid.js CHANGED
@@ -1305,6 +1305,22 @@ function updateAllSkills() {
1305
1305
  }
1306
1306
  return result;
1307
1307
  }
1308
+ function copyDirectoryRecursive(source, target, fileFilter) {
1309
+ if (!existsSync6(target)) {
1310
+ mkdirSync4(target, { recursive: true });
1311
+ }
1312
+ const entries = readdirSync5(source, { withFileTypes: true });
1313
+ for (const entry of entries) {
1314
+ const sourcePath = join7(source, entry.name);
1315
+ const targetPath = join7(target, entry.name);
1316
+ if (entry.isDirectory()) {
1317
+ copyDirectoryRecursive(sourcePath, targetPath, fileFilter);
1318
+ } else if (entry.isFile() && fileFilter(entry.name)) {
1319
+ const content = readFileSync6(sourcePath, "utf-8");
1320
+ writeFileSync4(targetPath, content);
1321
+ }
1322
+ }
1323
+ }
1308
1324
  function installSkill(skillName) {
1309
1325
  const config = loadConfig();
1310
1326
  const skillPath = findSkillPath(skillName);
@@ -1418,34 +1434,20 @@ function installSkill(skillName) {
1418
1434
  const referencesSource = join7(skillDir, "references");
1419
1435
  if (existsSync6(referencesSource)) {
1420
1436
  const targetReferencesDir = join7(targetSkillDir, "references");
1421
- if (!existsSync6(targetReferencesDir)) {
1422
- mkdirSync4(targetReferencesDir, { recursive: true });
1423
- }
1424
- const referenceFiles = readdirSync5(referencesSource).filter(
1437
+ copyDirectoryRecursive(
1438
+ referencesSource,
1439
+ targetReferencesDir,
1425
1440
  (f) => f.endsWith(".md")
1426
1441
  );
1427
- for (const file of referenceFiles) {
1428
- const sourcePath = join7(referencesSource, file);
1429
- const targetPath = join7(targetReferencesDir, file);
1430
- const content = readFileSync6(sourcePath, "utf-8");
1431
- writeFileSync4(targetPath, content);
1432
- }
1433
1442
  }
1434
1443
  const scriptsSource = join7(skillDir, "scripts");
1435
1444
  if (existsSync6(scriptsSource)) {
1436
1445
  const targetScriptsDir = join7(targetSkillDir, "scripts");
1437
- if (!existsSync6(targetScriptsDir)) {
1438
- mkdirSync4(targetScriptsDir, { recursive: true });
1439
- }
1440
- const scriptFiles = readdirSync5(scriptsSource).filter(
1446
+ copyDirectoryRecursive(
1447
+ scriptsSource,
1448
+ targetScriptsDir,
1441
1449
  (f) => f.endsWith(".ts") || f.endsWith(".js") || f.endsWith(".py")
1442
1450
  );
1443
- for (const file of scriptFiles) {
1444
- const sourcePath = join7(scriptsSource, file);
1445
- const targetPath = join7(targetScriptsDir, file);
1446
- const content = readFileSync6(sourcePath, "utf-8");
1447
- writeFileSync4(targetPath, content);
1448
- }
1449
1451
  }
1450
1452
  const activePlatforms = getActivePlatforms(config);
1451
1453
  const targetPlatforms = activePlatforms.length > 0 ? activePlatforms : [config.platform];
package/dist/index.js CHANGED
@@ -1262,6 +1262,22 @@ function updateAllSkills() {
1262
1262
  }
1263
1263
  return result;
1264
1264
  }
1265
+ function copyDirectoryRecursive(source, target, fileFilter) {
1266
+ if (!existsSync6(target)) {
1267
+ mkdirSync4(target, { recursive: true });
1268
+ }
1269
+ const entries = readdirSync5(source, { withFileTypes: true });
1270
+ for (const entry of entries) {
1271
+ const sourcePath = join7(source, entry.name);
1272
+ const targetPath = join7(target, entry.name);
1273
+ if (entry.isDirectory()) {
1274
+ copyDirectoryRecursive(sourcePath, targetPath, fileFilter);
1275
+ } else if (entry.isFile() && fileFilter(entry.name)) {
1276
+ const content = readFileSync6(sourcePath, "utf-8");
1277
+ writeFileSync4(targetPath, content);
1278
+ }
1279
+ }
1280
+ }
1265
1281
  function installSkill(skillName) {
1266
1282
  const config = loadConfig();
1267
1283
  const skillPath = findSkillPath(skillName);
@@ -1375,34 +1391,20 @@ function installSkill(skillName) {
1375
1391
  const referencesSource = join7(skillDir, "references");
1376
1392
  if (existsSync6(referencesSource)) {
1377
1393
  const targetReferencesDir = join7(targetSkillDir, "references");
1378
- if (!existsSync6(targetReferencesDir)) {
1379
- mkdirSync4(targetReferencesDir, { recursive: true });
1380
- }
1381
- const referenceFiles = readdirSync5(referencesSource).filter(
1394
+ copyDirectoryRecursive(
1395
+ referencesSource,
1396
+ targetReferencesDir,
1382
1397
  (f) => f.endsWith(".md")
1383
1398
  );
1384
- for (const file of referenceFiles) {
1385
- const sourcePath = join7(referencesSource, file);
1386
- const targetPath = join7(targetReferencesDir, file);
1387
- const content = readFileSync6(sourcePath, "utf-8");
1388
- writeFileSync4(targetPath, content);
1389
- }
1390
1399
  }
1391
1400
  const scriptsSource = join7(skillDir, "scripts");
1392
1401
  if (existsSync6(scriptsSource)) {
1393
1402
  const targetScriptsDir = join7(targetSkillDir, "scripts");
1394
- if (!existsSync6(targetScriptsDir)) {
1395
- mkdirSync4(targetScriptsDir, { recursive: true });
1396
- }
1397
- const scriptFiles = readdirSync5(scriptsSource).filter(
1403
+ copyDirectoryRecursive(
1404
+ scriptsSource,
1405
+ targetScriptsDir,
1398
1406
  (f) => f.endsWith(".ts") || f.endsWith(".js") || f.endsWith(".py")
1399
1407
  );
1400
- for (const file of scriptFiles) {
1401
- const sourcePath = join7(scriptsSource, file);
1402
- const targetPath = join7(targetScriptsDir, file);
1403
- const content = readFileSync6(sourcePath, "utf-8");
1404
- writeFileSync4(targetPath, content);
1405
- }
1406
1408
  }
1407
1409
  const activePlatforms = getActivePlatforms(config);
1408
1410
  const targetPlatforms = activePlatforms.length > 0 ? activePlatforms : [config.platform];
@@ -1 +1 @@
1
- {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/lib/skills.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "droid-codex",
3
- "version": "0.1.10",
3
+ "version": "0.2.1",
4
4
  "description": "Shared organizational knowledge - PRDs, tech designs, domains, proposals, patterns, and explored topics. Use when loading project context, searching codex, capturing decisions, or creating new entries.",
5
5
  "author": {
6
6
  "name": "Orderful",
@@ -1,6 +1,6 @@
1
1
  name: codex
2
2
  description: "Shared organizational knowledge - PRDs, tech designs, domains, proposals, patterns, and explored topics. Use when loading project context, searching codex, capturing decisions, or creating new entries."
3
- version: 0.1.10
3
+ version: 0.2.1
4
4
  status: beta
5
5
 
6
6
  includes:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: codex
3
- description: "Shared organizational knowledge - PRDs, tech designs, patterns, and explored topics. Use when loading project context ('load transaction-templates'), searching codex ('search webhook'), capturing decisions ('codex decision'), or adding explored topics ('add topic'). User prompts like 'check the codex', 'what's in the codex about X', 'load the PRD for Y'."
4
- argument-hint: "[projects | domains | proposals | patterns | topics | {name} | search {query} | new {type} {name} | decision {text}]"
3
+ description: "Shared organizational knowledge - PRDs, tech designs, patterns, and explored topics. Use when loading project context ('load transaction-templates'), searching codex ('search webhook'), reviewing documents ('review tech-design'), capturing decisions ('codex decision'), or adding explored topics ('add topic'). User prompts like 'check the codex', 'what's in the codex about X', 'load the PRD for Y'."
4
+ argument-hint: "[projects | domains | proposals | patterns | topics | {name} | search {query} | review {type} | new {type} {name} | decision {text}]"
5
5
  allowed-tools:
6
6
  [
7
7
  Read,
@@ -173,6 +173,7 @@ The codex has five categories:
173
173
  | `/codex search {query}` | Search and load entry (searches all categories) |
174
174
  | `/codex search {query} -- {instruction}` | Search, load, then execute follow-up instruction |
175
175
  | `/codex {category} search {query}` | Search within a specific category only |
176
+ | `/codex review {type} --pr {number}` | Conversational review of a document PR |
176
177
  | `/codex new {category} {name}` | Scaffold new entry (project/domain/proposal/pattern/topic) |
177
178
  | `/codex decision {text}` | Append to active project's DECISIONS.md |
178
179
  | `/codex snapshot {type} {file} {name}` | Import PDF/markdown to codex (uses agent) |
@@ -360,6 +361,20 @@ Artifacts are supplementary documents that support a project but aren't core doc
360
361
 
361
362
  Artifacts get lighter frontmatter with `type: artifact` and source like `interview`, `transcript`, `notes`, `meeting`, `research`, `spike`, or `analysis`.
362
363
 
364
+ ## Reviewing Documents
365
+
366
+ **Trigger:** `/codex review {type} --pr {number}`
367
+
368
+ **Procedure:**
369
+
370
+ 1. **Run preamble:** `droid config --get tools.codex | droid exec codex git-preamble --config -`
371
+ 2. **Fetch PR info:** `gh pr view {number} --json files,title`
372
+ 3. **Filter & Load:** Identify the primary document (e.g., `TECH-DESIGN.md`) and context (e.g., `thought-doc.md`) based on the `{type}` definition.
373
+ 4. **Interactive Review:** Guide the user through the document sections.
374
+
375
+ Full procedure: `references/review/workflow.md`
376
+ Type definitions: `references/review/{type}.md`
377
+
363
378
  ## Creating New Entries
364
379
 
365
380
  **Trigger:** `/codex new {category} {name}`
@@ -0,0 +1,34 @@
1
+ # Tech Design Document Type
2
+
3
+ Configuration for reviewing Tech Design documents via `/codex review tech-design`.
4
+
5
+ ## File Patterns
6
+
7
+ | Role | Pattern | Description |
8
+ | --- | --- | --- |
9
+ | **Primary** | `**/TECH-DESIGN.md` | The main document being reviewed. Sections are parsed from here. |
10
+ | **Context** | `**/thought-doc.md` | Backstory, alternatives, and trade-offs. Used for "why" questions. |
11
+
12
+ *Note: In the MVP, we assume a single TECH-DESIGN.md per PR.*
13
+
14
+ ## Section Parsing
15
+ Sections in `TECH-DESIGN.md` are defined by H2 headers (`## `). H3 headers (`###`) are treated as content within sections for MVP.
16
+
17
+ **The tool dynamically discovers ALL sections present in the document.** It does not filter for specific section names.
18
+
19
+ **Common sections** (examples, not exhaustive):
20
+ - TL;DR
21
+ - Problem
22
+ - Scope
23
+ - Solution
24
+ - Key Decisions
25
+ - Risks
26
+ - Rollout
27
+ - Implementation Phases
28
+
29
+ Authors may include additional sections (e.g., "Security", "Performance", "Alternatives Considered") and the tool will present them for navigation.
30
+
31
+ ## Consistency Checks (Deferred)
32
+ *Future feature: Rules to automatically check consistency.*
33
+ - "Risks" section must list mitigations
34
+ - "Implementation Phases" must match "Rollout" steps
@@ -0,0 +1,250 @@
1
+ # Generic Document Review Workflow
2
+
3
+ The `/codex review` command provides a conversational interface for reviewing structured documents (tech designs, PRDs, etc.) directly in the CLI.
4
+
5
+ ## 1. Loading the PR
6
+
7
+ **Trigger:** `/codex review {type} --pr {number}`
8
+
9
+ **Step 1: Preamble**
10
+ Run the git preamble to ensure we are on a clean state (though we're mostly reading).
11
+ ```bash
12
+ droid config --get tools.codex | droid exec codex git-preamble --config -
13
+ ```
14
+
15
+ **Step 2: Fetch PR Details**
16
+ Get the PR metadata to validate it exists and get the file list.
17
+
18
+ ```bash
19
+ # Get codex repo path from config
20
+ codex_repo=$(droid config --get tools.codex.codex_dir)
21
+
22
+ # Fetch PR info
23
+ gh pr view {number} --json files,title,url,headRefName --repo "$codex_repo"
24
+ ```
25
+
26
+ Check exit code: if non-zero, PR not found (see Error Handling below).
27
+
28
+ **Step 3: Checkout PR Branch**
29
+ Check out the PR to read files easily.
30
+
31
+ ```bash
32
+ cd "$codex_repo"
33
+ gh pr checkout {number}
34
+ ```
35
+
36
+ This creates/switches to the PR branch locally.
37
+
38
+ **Step 4: Identify Files**
39
+ Match the file list against patterns in `references/review/{type}.md`.
40
+
41
+ For tech-design:
42
+ - **Primary:** `**/TECH-DESIGN.md`
43
+ - **Context:** `**/thought-doc.md` (optional)
44
+
45
+ Find files using:
46
+ ```bash
47
+ find . -name "TECH-DESIGN.md" -type f
48
+ find . -name "thought-doc.md" -type f
49
+ ```
50
+
51
+ **Step 5: Read Content**
52
+ Read identified files using the Read tool. Count lines for display.
53
+
54
+ ```bash
55
+ wc -l {path_to_primary} # Get line count
56
+ ```
57
+
58
+ **Error Handling:**
59
+
60
+ **PR not found:**
61
+ ```bash
62
+ gh pr view {number} --repo "$codex_repo"
63
+ # Check exit code
64
+ if [ $? -ne 0 ]; then
65
+ echo "❌ PR #{number} not found in codex repo"
66
+ exit 1
67
+ fi
68
+ ```
69
+
70
+ **TECH-DESIGN.md not found:**
71
+ If `find . -name "TECH-DESIGN.md"` returns nothing:
72
+ ```
73
+ ❌ No TECH-DESIGN.md found in PR #{number}
74
+
75
+ This PR doesn't appear to contain a tech design document.
76
+ ```
77
+
78
+ **thought-doc.md missing (optional):**
79
+ If not found, continue without it:
80
+ ```
81
+ ⚠️ No thought-doc.md found - context search will be limited
82
+ ```
83
+
84
+ **gh CLI fails:**
85
+ ```
86
+ ❌ Failed to fetch PR details. Is gh CLI authenticated?
87
+
88
+ Try: gh auth status
89
+ ```
90
+
91
+ ## 2. Parsing Structure
92
+
93
+ **Step 1: Parse Sections**
94
+ Read the **Primary** document and extract H2 headers (lines starting with `## `).
95
+
96
+ Extract using pattern: `^##\s+(.+)$`
97
+ - Match lines starting with `##` followed by whitespace
98
+ - Capture everything after as the section name
99
+ - Strip leading/trailing whitespace
100
+ - Ignore H3 headers (`###`) for MVP - treat as content within sections
101
+
102
+ Example parsing:
103
+ ```
104
+ ## TL;DR → Section: "TL;DR"
105
+ ## Problem → Section: "Problem"
106
+ ### Sub-problem → (ignored, part of Problem section)
107
+ ## Solution → Section: "Solution"
108
+ ```
109
+
110
+ **Step 2: Display Overview**
111
+ Output a dynamic summary based on the actual PR content:
112
+
113
+ ```
114
+ 📋 Review: {PR Title} (PR #{number})
115
+
116
+ Documents loaded:
117
+ ✓ {path_to_primary} ({line_count} lines)
118
+ ✓ {path_to_context} ({line_count} lines) [if found]
119
+
120
+ Structure ({count} sections):
121
+ 1. {First section name}
122
+ 2. {Second section name}
123
+ ...
124
+ {N}. {Last section name}
125
+
126
+ What would you like to do?
127
+ - Show me a specific section (e.g., "show me the {example section}")
128
+ - Ask questions about decisions (e.g., "why was X rejected?")
129
+ - Walk through section by section
130
+ ```
131
+
132
+ **Note:** All values are dynamic:
133
+ - PR title comes from `gh pr view`
134
+ - File paths come from what's actually in the PR
135
+ - Section count and names come from parsing the TECH-DESIGN.md H2 headers
136
+ - If thought-doc.md not found, only show the primary document
137
+
138
+ **Example output:**
139
+ ```
140
+ 📋 Review: Transaction Templates Tech Design (PR #128)
141
+
142
+ Documents loaded:
143
+ ✓ projects/transaction-templates/TECH-DESIGN.md (250 lines)
144
+ ✓ projects/transaction-templates/artifacts/thought-doc.md (380 lines)
145
+
146
+ Structure (8 sections):
147
+ 1. TL;DR
148
+ 2. Problem
149
+ 3. Scope
150
+ 4. Solution
151
+ 5. Key Decisions
152
+ 6. Risks
153
+ 7. Rollout
154
+ 8. Implementation Phases
155
+
156
+ What would you like to do?
157
+ - Show me a specific section (e.g., "show me the rollout")
158
+ - Ask questions about decisions (e.g., "why was X rejected?")
159
+ - Walk through section by section
160
+ ```
161
+
162
+ **Step 3: Wait for User Request**
163
+ User can now navigate conversationally.
164
+
165
+ ## 3. Conversational Navigation
166
+
167
+ Map user requests to actions:
168
+
169
+ **"Show me {section}"**
170
+ 1. Match the section name (see Section Matching below)
171
+ 2. Read the Primary file
172
+ 3. Extract content between `## {Match}` and the next `## ` header
173
+ 4. Display the section content
174
+
175
+ **Section Matching Algorithm:**
176
+
177
+ Use case-insensitive substring matching:
178
+
179
+ 1. Normalize user input and section names to lowercase
180
+ 2. Check if user input is substring of any section name
181
+ 3. If single match: use it
182
+ 4. If multiple matches: pick the first one (or ask user to clarify)
183
+ 5. If no matches: list available sections
184
+
185
+ **Examples:**
186
+ - User: "show rollout" → matches "Rollout"
187
+ - User: "security" → matches "Security Considerations"
188
+ - User: "risks" → matches "Risks"
189
+ - User: "key decisions" → matches "Key Decisions"
190
+
191
+ **"Walk me through it"**
192
+ 1. Start with the first section
193
+ 2. Display content
194
+ 3. Ask "Continue to {Next Section}?"
195
+ 4. Repeat until user stops or end of document
196
+
197
+ **"Jump to {section}"**
198
+ Same as "Show me {section}".
199
+
200
+ ## 4. Contextual Search (Thought Docs)
201
+
202
+ **Trigger Detection:**
203
+
204
+ If user query contains any of: "why", "rejected", "alternative", "decision", "reason", "chose", "didn't"
205
+ → Enter context search mode
206
+
207
+ **Term Extraction:**
208
+
209
+ Extract key phrases from the question:
210
+ - Strip question words: "why was", "why did we", "what about"
211
+ - Extract 2-4 word phrases: "event-based approach", "webhook pattern", "async processing"
212
+ - If user mentions specific terms in quotes, use those exactly
213
+
214
+ **Examples:**
215
+ - "Why was event-based rejected?" → search for "event-based"
216
+ - "Why did we choose sync over async?" → search for "sync" and "async"
217
+ - "What about the webhook approach?" → search for "webhook"
218
+
219
+ **Search Process:**
220
+
221
+ 1. Search the **Context** document (e.g., `thought-doc.md`) first:
222
+ ```bash
223
+ grep -C 5 -i "{term}" {path_to_context}
224
+ ```
225
+
226
+ 2. Display results with context (5 lines before/after)
227
+
228
+ 3. If multiple matches found: show first 3 matches
229
+
230
+ 4. If no match in context doc: search Primary document
231
+
232
+ 5. If still no match: "No mentions of '{term}' found in design docs"
233
+
234
+ **Display Format:**
235
+
236
+ ```
237
+ Searching thought doc for "event-based"...
238
+
239
+ Found in Key Decisions section:
240
+
241
+ > Event-based was rejected because of complexity in guaranteeing
242
+ > order and handling failures. The synchronous API approach is
243
+ > simpler and sufficient for the MVP requirements. We considered
244
+ > event streaming but decided it was premature optimization.
245
+
246
+ Anything else?
247
+ ```
248
+
249
+ ## 5. Posting Feedback (MVP: Deferred)
250
+ *For MVP, we just display content. Users can use `gh pr comment` manually if they want, but the tool focuses on reading.*
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@orderful/droid",
3
- "version": "0.34.1",
3
+ "version": "0.35.1",
4
4
  "description": "AI workflow toolkit for sharing skills, commands, and agents across the team",
5
5
  "type": "module",
6
6
  "bin": {
package/src/lib/skills.ts CHANGED
@@ -393,6 +393,39 @@ export function updateAllSkills(): {
393
393
  return result;
394
394
  }
395
395
 
396
+ /**
397
+ * Recursively copy a directory and all its contents
398
+ * @param source Source directory path
399
+ * @param target Target directory path
400
+ * @param fileFilter Function that returns true if the file should be copied
401
+ */
402
+ function copyDirectoryRecursive(
403
+ source: string,
404
+ target: string,
405
+ fileFilter: (filename: string) => boolean,
406
+ ): void {
407
+ if (!existsSync(target)) {
408
+ mkdirSync(target, { recursive: true });
409
+ }
410
+
411
+ const entries = readdirSync(source, { withFileTypes: true });
412
+
413
+ for (const entry of entries) {
414
+ const sourcePath = join(source, entry.name);
415
+ const targetPath = join(target, entry.name);
416
+
417
+ if (entry.isDirectory()) {
418
+ // Recursively copy subdirectory
419
+ copyDirectoryRecursive(sourcePath, targetPath, fileFilter);
420
+ } else if (entry.isFile() && fileFilter(entry.name)) {
421
+ // Copy file if it passes the filter
422
+ const content = readFileSync(sourcePath, 'utf-8');
423
+ writeFileSync(targetPath, content);
424
+ }
425
+ // Ignore files that don't pass the filter
426
+ }
427
+ }
428
+
396
429
  /**
397
430
  * Install a skill
398
431
  */
@@ -553,36 +586,20 @@ export function installSkill(skillName: string): {
553
586
  const referencesSource = join(skillDir, 'references');
554
587
  if (existsSync(referencesSource)) {
555
588
  const targetReferencesDir = join(targetSkillDir, 'references');
556
- if (!existsSync(targetReferencesDir)) {
557
- mkdirSync(targetReferencesDir, { recursive: true });
558
- }
559
- const referenceFiles = readdirSync(referencesSource).filter((f) =>
589
+ copyDirectoryRecursive(referencesSource, targetReferencesDir, (f) =>
560
590
  f.endsWith('.md'),
561
591
  );
562
- for (const file of referenceFiles) {
563
- const sourcePath = join(referencesSource, file);
564
- const targetPath = join(targetReferencesDir, file);
565
- const content = readFileSync(sourcePath, 'utf-8');
566
- writeFileSync(targetPath, content);
567
- }
568
592
  }
569
593
 
570
594
  // Copy scripts if present (deterministic CLI scripts for the skill)
571
595
  const scriptsSource = join(skillDir, 'scripts');
572
596
  if (existsSync(scriptsSource)) {
573
597
  const targetScriptsDir = join(targetSkillDir, 'scripts');
574
- if (!existsSync(targetScriptsDir)) {
575
- mkdirSync(targetScriptsDir, { recursive: true });
576
- }
577
- const scriptFiles = readdirSync(scriptsSource).filter(
598
+ copyDirectoryRecursive(
599
+ scriptsSource,
600
+ targetScriptsDir,
578
601
  (f) => f.endsWith('.ts') || f.endsWith('.js') || f.endsWith('.py'),
579
602
  );
580
- for (const file of scriptFiles) {
581
- const sourcePath = join(scriptsSource, file);
582
- const targetPath = join(targetScriptsDir, file);
583
- const content = readFileSync(sourcePath, 'utf-8');
584
- writeFileSync(targetPath, content);
585
- }
586
603
  }
587
604
 
588
605
  // Get active platforms for multi-platform install
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "droid-codex",
3
- "version": "0.1.10",
3
+ "version": "0.2.1",
4
4
  "description": "Shared organizational knowledge - PRDs, tech designs, domains, proposals, patterns, and explored topics. Use when loading project context, searching codex, capturing decisions, or creating new entries.",
5
5
  "author": {
6
6
  "name": "Orderful",
@@ -1,6 +1,6 @@
1
1
  name: codex
2
2
  description: "Shared organizational knowledge - PRDs, tech designs, domains, proposals, patterns, and explored topics. Use when loading project context, searching codex, capturing decisions, or creating new entries."
3
- version: 0.1.10
3
+ version: 0.2.1
4
4
  status: beta
5
5
 
6
6
  includes:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: codex
3
- description: "Shared organizational knowledge - PRDs, tech designs, patterns, and explored topics. Use when loading project context ('load transaction-templates'), searching codex ('search webhook'), capturing decisions ('codex decision'), or adding explored topics ('add topic'). User prompts like 'check the codex', 'what's in the codex about X', 'load the PRD for Y'."
4
- argument-hint: "[projects | domains | proposals | patterns | topics | {name} | search {query} | new {type} {name} | decision {text}]"
3
+ description: "Shared organizational knowledge - PRDs, tech designs, patterns, and explored topics. Use when loading project context ('load transaction-templates'), searching codex ('search webhook'), reviewing documents ('review tech-design'), capturing decisions ('codex decision'), or adding explored topics ('add topic'). User prompts like 'check the codex', 'what's in the codex about X', 'load the PRD for Y'."
4
+ argument-hint: "[projects | domains | proposals | patterns | topics | {name} | search {query} | review {type} | new {type} {name} | decision {text}]"
5
5
  allowed-tools:
6
6
  [
7
7
  Read,
@@ -173,6 +173,7 @@ The codex has five categories:
173
173
  | `/codex search {query}` | Search and load entry (searches all categories) |
174
174
  | `/codex search {query} -- {instruction}` | Search, load, then execute follow-up instruction |
175
175
  | `/codex {category} search {query}` | Search within a specific category only |
176
+ | `/codex review {type} --pr {number}` | Conversational review of a document PR |
176
177
  | `/codex new {category} {name}` | Scaffold new entry (project/domain/proposal/pattern/topic) |
177
178
  | `/codex decision {text}` | Append to active project's DECISIONS.md |
178
179
  | `/codex snapshot {type} {file} {name}` | Import PDF/markdown to codex (uses agent) |
@@ -360,6 +361,20 @@ Artifacts are supplementary documents that support a project but aren't core doc
360
361
 
361
362
  Artifacts get lighter frontmatter with `type: artifact` and source like `interview`, `transcript`, `notes`, `meeting`, `research`, `spike`, or `analysis`.
362
363
 
364
+ ## Reviewing Documents
365
+
366
+ **Trigger:** `/codex review {type} --pr {number}`
367
+
368
+ **Procedure:**
369
+
370
+ 1. **Run preamble:** `droid config --get tools.codex | droid exec codex git-preamble --config -`
371
+ 2. **Fetch PR info:** `gh pr view {number} --json files,title`
372
+ 3. **Filter & Load:** Identify the primary document (e.g., `TECH-DESIGN.md`) and context (e.g., `thought-doc.md`) based on the `{type}` definition.
373
+ 4. **Interactive Review:** Guide the user through the document sections.
374
+
375
+ Full procedure: `references/review/workflow.md`
376
+ Type definitions: `references/review/{type}.md`
377
+
363
378
  ## Creating New Entries
364
379
 
365
380
  **Trigger:** `/codex new {category} {name}`
@@ -0,0 +1,34 @@
1
+ # Tech Design Document Type
2
+
3
+ Configuration for reviewing Tech Design documents via `/codex review tech-design`.
4
+
5
+ ## File Patterns
6
+
7
+ | Role | Pattern | Description |
8
+ | --- | --- | --- |
9
+ | **Primary** | `**/TECH-DESIGN.md` | The main document being reviewed. Sections are parsed from here. |
10
+ | **Context** | `**/thought-doc.md` | Backstory, alternatives, and trade-offs. Used for "why" questions. |
11
+
12
+ *Note: In the MVP, we assume a single TECH-DESIGN.md per PR.*
13
+
14
+ ## Section Parsing
15
+ Sections in `TECH-DESIGN.md` are defined by H2 headers (`## `). H3 headers (`###`) are treated as content within sections for MVP.
16
+
17
+ **The tool dynamically discovers ALL sections present in the document.** It does not filter for specific section names.
18
+
19
+ **Common sections** (examples, not exhaustive):
20
+ - TL;DR
21
+ - Problem
22
+ - Scope
23
+ - Solution
24
+ - Key Decisions
25
+ - Risks
26
+ - Rollout
27
+ - Implementation Phases
28
+
29
+ Authors may include additional sections (e.g., "Security", "Performance", "Alternatives Considered") and the tool will present them for navigation.
30
+
31
+ ## Consistency Checks (Deferred)
32
+ *Future feature: Rules to automatically check consistency.*
33
+ - "Risks" section must list mitigations
34
+ - "Implementation Phases" must match "Rollout" steps
@@ -0,0 +1,250 @@
1
+ # Generic Document Review Workflow
2
+
3
+ The `/codex review` command provides a conversational interface for reviewing structured documents (tech designs, PRDs, etc.) directly in the CLI.
4
+
5
+ ## 1. Loading the PR
6
+
7
+ **Trigger:** `/codex review {type} --pr {number}`
8
+
9
+ **Step 1: Preamble**
10
+ Run the git preamble to ensure we are on a clean state (though we're mostly reading).
11
+ ```bash
12
+ droid config --get tools.codex | droid exec codex git-preamble --config -
13
+ ```
14
+
15
+ **Step 2: Fetch PR Details**
16
+ Get the PR metadata to validate it exists and get the file list.
17
+
18
+ ```bash
19
+ # Get codex repo path from config
20
+ codex_repo=$(droid config --get tools.codex.codex_dir)
21
+
22
+ # Fetch PR info
23
+ gh pr view {number} --json files,title,url,headRefName --repo "$codex_repo"
24
+ ```
25
+
26
+ Check exit code: if non-zero, PR not found (see Error Handling below).
27
+
28
+ **Step 3: Checkout PR Branch**
29
+ Check out the PR to read files easily.
30
+
31
+ ```bash
32
+ cd "$codex_repo"
33
+ gh pr checkout {number}
34
+ ```
35
+
36
+ This creates/switches to the PR branch locally.
37
+
38
+ **Step 4: Identify Files**
39
+ Match the file list against patterns in `references/review/{type}.md`.
40
+
41
+ For tech-design:
42
+ - **Primary:** `**/TECH-DESIGN.md`
43
+ - **Context:** `**/thought-doc.md` (optional)
44
+
45
+ Find files using:
46
+ ```bash
47
+ find . -name "TECH-DESIGN.md" -type f
48
+ find . -name "thought-doc.md" -type f
49
+ ```
50
+
51
+ **Step 5: Read Content**
52
+ Read identified files using the Read tool. Count lines for display.
53
+
54
+ ```bash
55
+ wc -l {path_to_primary} # Get line count
56
+ ```
57
+
58
+ **Error Handling:**
59
+
60
+ **PR not found:**
61
+ ```bash
62
+ gh pr view {number} --repo "$codex_repo"
63
+ # Check exit code
64
+ if [ $? -ne 0 ]; then
65
+ echo "❌ PR #{number} not found in codex repo"
66
+ exit 1
67
+ fi
68
+ ```
69
+
70
+ **TECH-DESIGN.md not found:**
71
+ If `find . -name "TECH-DESIGN.md"` returns nothing:
72
+ ```
73
+ ❌ No TECH-DESIGN.md found in PR #{number}
74
+
75
+ This PR doesn't appear to contain a tech design document.
76
+ ```
77
+
78
+ **thought-doc.md missing (optional):**
79
+ If not found, continue without it:
80
+ ```
81
+ ⚠️ No thought-doc.md found - context search will be limited
82
+ ```
83
+
84
+ **gh CLI fails:**
85
+ ```
86
+ ❌ Failed to fetch PR details. Is gh CLI authenticated?
87
+
88
+ Try: gh auth status
89
+ ```
90
+
91
+ ## 2. Parsing Structure
92
+
93
+ **Step 1: Parse Sections**
94
+ Read the **Primary** document and extract H2 headers (lines starting with `## `).
95
+
96
+ Extract using pattern: `^##\s+(.+)$`
97
+ - Match lines starting with `##` followed by whitespace
98
+ - Capture everything after as the section name
99
+ - Strip leading/trailing whitespace
100
+ - Ignore H3 headers (`###`) for MVP - treat as content within sections
101
+
102
+ Example parsing:
103
+ ```
104
+ ## TL;DR → Section: "TL;DR"
105
+ ## Problem → Section: "Problem"
106
+ ### Sub-problem → (ignored, part of Problem section)
107
+ ## Solution → Section: "Solution"
108
+ ```
109
+
110
+ **Step 2: Display Overview**
111
+ Output a dynamic summary based on the actual PR content:
112
+
113
+ ```
114
+ 📋 Review: {PR Title} (PR #{number})
115
+
116
+ Documents loaded:
117
+ ✓ {path_to_primary} ({line_count} lines)
118
+ ✓ {path_to_context} ({line_count} lines) [if found]
119
+
120
+ Structure ({count} sections):
121
+ 1. {First section name}
122
+ 2. {Second section name}
123
+ ...
124
+ {N}. {Last section name}
125
+
126
+ What would you like to do?
127
+ - Show me a specific section (e.g., "show me the {example section}")
128
+ - Ask questions about decisions (e.g., "why was X rejected?")
129
+ - Walk through section by section
130
+ ```
131
+
132
+ **Note:** All values are dynamic:
133
+ - PR title comes from `gh pr view`
134
+ - File paths come from what's actually in the PR
135
+ - Section count and names come from parsing the TECH-DESIGN.md H2 headers
136
+ - If thought-doc.md not found, only show the primary document
137
+
138
+ **Example output:**
139
+ ```
140
+ 📋 Review: Transaction Templates Tech Design (PR #128)
141
+
142
+ Documents loaded:
143
+ ✓ projects/transaction-templates/TECH-DESIGN.md (250 lines)
144
+ ✓ projects/transaction-templates/artifacts/thought-doc.md (380 lines)
145
+
146
+ Structure (8 sections):
147
+ 1. TL;DR
148
+ 2. Problem
149
+ 3. Scope
150
+ 4. Solution
151
+ 5. Key Decisions
152
+ 6. Risks
153
+ 7. Rollout
154
+ 8. Implementation Phases
155
+
156
+ What would you like to do?
157
+ - Show me a specific section (e.g., "show me the rollout")
158
+ - Ask questions about decisions (e.g., "why was X rejected?")
159
+ - Walk through section by section
160
+ ```
161
+
162
+ **Step 3: Wait for User Request**
163
+ User can now navigate conversationally.
164
+
165
+ ## 3. Conversational Navigation
166
+
167
+ Map user requests to actions:
168
+
169
+ **"Show me {section}"**
170
+ 1. Match the section name (see Section Matching below)
171
+ 2. Read the Primary file
172
+ 3. Extract content between `## {Match}` and the next `## ` header
173
+ 4. Display the section content
174
+
175
+ **Section Matching Algorithm:**
176
+
177
+ Use case-insensitive substring matching:
178
+
179
+ 1. Normalize user input and section names to lowercase
180
+ 2. Check if user input is substring of any section name
181
+ 3. If single match: use it
182
+ 4. If multiple matches: pick the first one (or ask user to clarify)
183
+ 5. If no matches: list available sections
184
+
185
+ **Examples:**
186
+ - User: "show rollout" → matches "Rollout"
187
+ - User: "security" → matches "Security Considerations"
188
+ - User: "risks" → matches "Risks"
189
+ - User: "key decisions" → matches "Key Decisions"
190
+
191
+ **"Walk me through it"**
192
+ 1. Start with the first section
193
+ 2. Display content
194
+ 3. Ask "Continue to {Next Section}?"
195
+ 4. Repeat until user stops or end of document
196
+
197
+ **"Jump to {section}"**
198
+ Same as "Show me {section}".
199
+
200
+ ## 4. Contextual Search (Thought Docs)
201
+
202
+ **Trigger Detection:**
203
+
204
+ If user query contains any of: "why", "rejected", "alternative", "decision", "reason", "chose", "didn't"
205
+ → Enter context search mode
206
+
207
+ **Term Extraction:**
208
+
209
+ Extract key phrases from the question:
210
+ - Strip question words: "why was", "why did we", "what about"
211
+ - Extract 2-4 word phrases: "event-based approach", "webhook pattern", "async processing"
212
+ - If user mentions specific terms in quotes, use those exactly
213
+
214
+ **Examples:**
215
+ - "Why was event-based rejected?" → search for "event-based"
216
+ - "Why did we choose sync over async?" → search for "sync" and "async"
217
+ - "What about the webhook approach?" → search for "webhook"
218
+
219
+ **Search Process:**
220
+
221
+ 1. Search the **Context** document (e.g., `thought-doc.md`) first:
222
+ ```bash
223
+ grep -C 5 -i "{term}" {path_to_context}
224
+ ```
225
+
226
+ 2. Display results with context (5 lines before/after)
227
+
228
+ 3. If multiple matches found: show first 3 matches
229
+
230
+ 4. If no match in context doc: search Primary document
231
+
232
+ 5. If still no match: "No mentions of '{term}' found in design docs"
233
+
234
+ **Display Format:**
235
+
236
+ ```
237
+ Searching thought doc for "event-based"...
238
+
239
+ Found in Key Decisions section:
240
+
241
+ > Event-based was rejected because of complexity in guaranteeing
242
+ > order and handling failures. The synchronous API approach is
243
+ > simpler and sufficient for the MVP requirements. We considered
244
+ > event streaming but decided it was premature optimization.
245
+
246
+ Anything else?
247
+ ```
248
+
249
+ ## 5. Posting Feedback (MVP: Deferred)
250
+ *For MVP, we just display content. Users can use `gh pr comment` manually if they want, but the tool focuses on reading.*