@justinforfun/redo-skill 0.1.2 → 0.1.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/README.md CHANGED
@@ -16,6 +16,8 @@ The installer supports:
16
16
  - Codex CLI
17
17
  - Claude Code
18
18
 
19
+ The installer detects supported tools on the local machine. Detected tools are selected by default; tools that are not detected are left unselected but can still be chosen. If you choose an undetected tool, the installer asks for confirmation before writing to its default directory.
20
+
19
21
  ## Invocation
20
22
 
21
23
  ```text
@@ -44,6 +46,8 @@ For each technology, `redo` reconstructs:
44
46
  - Candidate options and their costs
45
47
  - Why the chosen design won
46
48
  - Key trade-offs
49
+ - Transferable design patterns in sibling systems
50
+ - Boundary cases and counterexamples
47
51
  - Technical debt introduced
48
52
  - Debt that was later resolved
49
53
  - Pain points that still remain
package/bin/install.js CHANGED
@@ -4,6 +4,7 @@ import fs from 'node:fs/promises';
4
4
  import os from 'node:os';
5
5
  import path from 'node:path';
6
6
  import process from 'node:process';
7
+ import { execFile } from 'node:child_process';
7
8
  import { fileURLToPath } from 'node:url';
8
9
 
9
10
  import chalk from 'chalk';
@@ -28,7 +29,15 @@ const targets = [
28
29
  destination: path.join(os.homedir(), '.agents', 'skills', 'redo')
29
30
  }
30
31
  ],
31
- trigger: '$redo kafka, redo kafka, or select redo from the skill picker'
32
+ trigger: '$redo kafka, redo kafka, or select redo from the skill picker',
33
+ detectors: [
34
+ {
35
+ type: 'path',
36
+ value: path.join(os.homedir(), '.agents'),
37
+ label: '~/.agents'
38
+ }
39
+ ],
40
+ missingReason: 'Codex local skill directory was not detected.'
32
41
  },
33
42
  {
34
43
  id: 'codex-cli',
@@ -41,7 +50,20 @@ const targets = [
41
50
  destination: path.join(process.env.CODEX_HOME || path.join(os.homedir(), '.codex'), 'skills', 'redo')
42
51
  }
43
52
  ],
44
- trigger: '$redo kafka, redo kafka, or /skills then choose redo'
53
+ trigger: '$redo kafka, redo kafka, or /skills then choose redo',
54
+ detectors: [
55
+ {
56
+ type: 'command',
57
+ value: 'codex',
58
+ label: 'codex command'
59
+ },
60
+ {
61
+ type: 'path',
62
+ value: process.env.CODEX_HOME || path.join(os.homedir(), '.codex'),
63
+ label: process.env.CODEX_HOME ? 'CODEX_HOME' : '~/.codex'
64
+ }
65
+ ],
66
+ missingReason: 'codex command and Codex CLI home directory were not detected.'
45
67
  },
46
68
  {
47
69
  id: 'claude-code',
@@ -59,7 +81,20 @@ const targets = [
59
81
  destination: path.join(os.homedir(), '.claude', 'commands', 'redo.md')
60
82
  }
61
83
  ],
62
- trigger: '/redo kafka'
84
+ trigger: '/redo kafka',
85
+ detectors: [
86
+ {
87
+ type: 'command',
88
+ value: 'claude',
89
+ label: 'claude command'
90
+ },
91
+ {
92
+ type: 'path',
93
+ value: path.join(os.homedir(), '.claude'),
94
+ label: '~/.claude'
95
+ }
96
+ ],
97
+ missingReason: 'claude command and Claude Code home directory were not detected.'
63
98
  }
64
99
  ];
65
100
 
@@ -116,21 +151,114 @@ async function ensureSourceSkillExists() {
116
151
  }
117
152
 
118
153
  async function promptTargets() {
154
+ const detectedTargets = await detectTargets();
155
+ const availableTargets = detectedTargets.filter((target) => target.available);
156
+
157
+ if (availableTargets.length === 0) {
158
+ console.log(chalk.yellow('No supported AI tools were detected. Nothing installed.'));
159
+ console.log(chalk.dim('Install Codex, Codex CLI, or Claude Code first, then run this installer again.'));
160
+ return [];
161
+ }
162
+
119
163
  const answers = await inquirer.prompt([
120
164
  {
121
165
  type: 'checkbox',
122
166
  name: 'targetIds',
123
167
  message: 'Select AI tools to install redo for:',
124
- choices: targets.map((target) => ({
125
- name: `${target.name} ${chalk.dim('- ' + target.description)}`,
168
+ choices: detectedTargets.map((target) => ({
169
+ name: formatTargetChoice(target),
126
170
  value: target.id,
127
- checked: true
171
+ checked: target.available,
172
+ disabled: false
128
173
  })),
129
174
  validate: (values) => (values.length > 0 ? true : 'Select at least one tool.')
130
175
  }
131
176
  ]);
132
177
 
133
- return targets.filter((target) => answers.targetIds.includes(target.id));
178
+ const selectedTargets = detectedTargets.filter((target) => answers.targetIds.includes(target.id));
179
+ return promptUndetectedTargetConfirmation(selectedTargets);
180
+ }
181
+
182
+ async function detectTargets() {
183
+ return Promise.all(
184
+ targets.map(async (target) => {
185
+ const detection = await detectTarget(target);
186
+ return {
187
+ ...target,
188
+ ...detection
189
+ };
190
+ })
191
+ );
192
+ }
193
+
194
+ async function detectTarget(target) {
195
+ for (const detector of target.detectors) {
196
+ if (detector.type === 'path' && (await exists(detector.value))) {
197
+ return {
198
+ available: true,
199
+ detectionLabel: detector.label
200
+ };
201
+ }
202
+
203
+ if (detector.type === 'command' && (await commandExists(detector.value))) {
204
+ return {
205
+ available: true,
206
+ detectionLabel: detector.label
207
+ };
208
+ }
209
+ }
210
+
211
+ return {
212
+ available: false,
213
+ detectionLabel: null
214
+ };
215
+ }
216
+
217
+ function formatTargetChoice(target) {
218
+ const description = chalk.dim('- ' + target.description);
219
+
220
+ if (target.available) {
221
+ return `${target.name} ${description} ${chalk.green('(detected: ' + target.detectionLabel + ')')}`;
222
+ }
223
+
224
+ return `${target.name} ${description} ${chalk.yellow('(not detected)')}`;
225
+ }
226
+
227
+ async function commandExists(command) {
228
+ const lookupCommand = process.platform === 'win32' ? 'where' : 'which';
229
+
230
+ return new Promise((resolve) => {
231
+ execFile(lookupCommand, [command], (error) => {
232
+ resolve(!error);
233
+ });
234
+ });
235
+ }
236
+
237
+ async function promptUndetectedTargetConfirmation(selectedTargets) {
238
+ const confirmedTargets = [];
239
+
240
+ for (const target of selectedTargets) {
241
+ if (target.available) {
242
+ confirmedTargets.push(target);
243
+ continue;
244
+ }
245
+
246
+ const destinationSummary = target.tasks.map((task) => task.destination).join(', ');
247
+ const answers = await inquirer.prompt([
248
+ {
249
+ type: 'confirm',
250
+ name: 'installAnyway',
251
+ message: `${target.name} was not detected. Install to ${destinationSummary} anyway?`,
252
+ default: false
253
+ }
254
+ ]);
255
+
256
+ if (answers.installAnyway) {
257
+ confirmedTargets.push(target);
258
+ }
259
+ }
260
+
261
+ return confirmedTargets;
134
262
  }
135
263
 
136
264
  async function promptConflictActions(plan) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@justinforfun/redo-skill",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Install the redo skill for Codex, Codex CLI, and Claude Code.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -16,6 +16,8 @@ The installer supports:
16
16
  - Codex CLI
17
17
  - Claude Code
18
18
 
19
+ The installer detects supported tools on the local machine. Detected tools are selected by default; tools that are not detected are left unselected but can still be chosen. If you choose an undetected tool, the installer asks for confirmation before writing to its default directory.
20
+
19
21
  ## Invocation
20
22
 
21
23
  ```text
@@ -44,6 +46,8 @@ For each technology, `redo` reconstructs:
44
46
  - Candidate options and their costs
45
47
  - Why the chosen design won
46
48
  - Key trade-offs
49
+ - Transferable design patterns in sibling systems
50
+ - Boundary cases and counterexamples
47
51
  - Technical debt introduced
48
52
  - Debt that was later resolved
49
53
  - Pain points that still remain
@@ -36,6 +36,8 @@ redo <topic> [--lang zh|en]
36
36
  - `--lang en` forces English output.
37
37
  - If `--lang` is absent, respond in the user's current conversation language.
38
38
 
39
+ The selected output language applies to the entire answer. Localize every user-facing section name, heading, table label, fixed phrase, and summary label into that language. Do not leak English template labels such as "Stage", "Debt introduced", "One-sentence version", "Transferable Pattern", "Counterexample", or "Sources" unless the user asked for English.
40
+
39
41
  ## Evidence Requirements
40
42
 
41
43
  For real technologies, do not rely only on memory when dates, versions, authorship, current status, or historical claims matter.
@@ -45,6 +47,7 @@ For real technologies, do not rely only on memory when dates, versions, authorsh
45
47
  - Distinguish sourced facts from inference. It is acceptable to infer engineering motivations, but label them as inference when the source does not explicitly say so.
46
48
  - Prefer primary sources over secondary commentary. Good sources include official docs, release notes, KIPs/RFCs/PEPs/design proposals, original papers, maintainers' posts, and authoritative engineering retrospectives.
47
49
  - Research relevant papers separately when the topic has an academic or foundational design lineage. Papers often explain why the original abstraction was plausible, what constraints the designers optimized for, and which trade-offs were known from the beginning. Do not only search release notes and blog posts.
50
+ - Avoid weak secondary sources when primary sources exist. Do not cite SEO summaries, generic tutorials, or casual comparison posts for core historical claims if official design docs, papers, or maintainer explanations are available.
48
51
  - Avoid source dumping. Cite the key sources used, and when useful, say which stages they support.
49
52
 
50
53
  ## Output Contract
@@ -59,7 +62,11 @@ Then produce the sections below.
59
62
 
60
63
  ### 1. Evolution Stages
61
64
 
62
- Choose stages by engineering decision pressure, not by release chronology. For mature infrastructure, databases, runtimes, frameworks, languages, and major tools, a good answer usually has 7-9 stages. Do not compress a major "debt repayment" stage into the debt map if it changed how users operate the system.
65
+ Choose stages by engineering decision pressure, not by release chronology. Causal order is more important than strict release order, but time should generally move forward. If a later concern appears before an earlier release, explain why the causal dependency is being presented that way.
66
+
67
+ For mature infrastructure, databases, runtimes, frameworks, languages, and major tools, a good answer usually has 7-9 stages. Do not compress a major "debt repayment" stage into the debt map if it changed how users operate the system. If you use more than 8 stages, the extra stage must earn its place by explaining a current frontier, current user-facing pain, or important debt repayment that would otherwise be invisible.
68
+
69
+ A stage can be a partial mitigation, not only a new feature. If a prior debt became painful at scale and later received a named fix, protocol change, runtime change, scheduler change, storage change, migration path, or operational redesign, make that fix its own stage. Do not hide it only in the debt map.
63
70
 
64
71
  For mature systems, check whether the stage list covers these arcs where relevant:
65
72
 
@@ -68,6 +75,7 @@ For mature systems, check whether the stage list covers these arcs where relevan
68
75
  - Coordination, metadata, scheduling, ownership, or state management.
69
76
  - Semantics/correctness guarantees.
70
77
  - Ecosystem or higher-level abstraction.
78
+ - Major mitigation of a previously introduced operational pain.
71
79
  - Scale, cloud-native, elasticity, or operations.
72
80
  - Cost/storage/performance pressure.
73
81
  - Current unresolved frontier.
@@ -98,6 +106,8 @@ Stage quality rules:
98
106
  - The chosen option must say why it was rational under the constraints of that stage, even if it later caused problems.
99
107
  - The rejected options must be plausible choices real engineers would have considered.
100
108
  - The debt line must create a traceable debt ID such as D1, D2, D3. Reuse these IDs in the debt map.
109
+ - Use clean top-level debt IDs: D1, D2, D3, and so on. If one stage introduces multiple meaningful debts, assign the next clean IDs instead of ad-hoc labels such as D2-4 or D3b.
110
+ - When a stage primarily repays earlier debt, explicitly say which debt IDs it repays and what new debt it introduces.
101
111
  - Avoid hindsight moralizing. The point is to recreate the decision pressure, not to mock past designs.
102
112
 
103
113
  ### 2. Throughline
@@ -115,11 +125,59 @@ Then add:
115
125
  |---|---|---|---|
116
126
  ```
117
127
 
118
- The throughline should produce a sentence the reader can repeat in a design review.
128
+ Use this structure so the section is stable:
129
+
130
+ ```markdown
131
+ ## Throughline
132
+
133
+ <one paragraph naming the recurring philosophy>
134
+
135
+ The cost: <one sentence naming the recurring price>
136
+
137
+ | Repeated choice | What it avoided | What it made harder | Outcome |
138
+ |---|---|---|---|
139
+
140
+ **Design-review sentence:** "<one memorable sentence>"
141
+ ```
142
+
143
+ ### 3. Transferable Pattern and Boundaries
144
+
145
+ After the throughline, add a section that helps the reader generalize the core design idea beyond the topic. This is not a random "similar tools" list. It should identify the reusable engineering philosophy, show where other systems apply the same idea, and show where the idea breaks down.
146
+
147
+ Use this structure:
119
148
 
120
- ### 3. Debt Map
149
+ ```markdown
150
+ ## Transferable Pattern
151
+
152
+ <one paragraph naming the reusable idea, such as "delegate caching to the operating system", "make the log the source of truth", or "push coordination into a control plane">
153
+
154
+ | System | How it uses the same idea | Shared constraint | Different price |
155
+ |---|---|---|---|
156
+ | <system> | <specific mechanism> | <why the same idea fits> | <what this system pays instead> |
157
+ ```
121
158
 
122
- Create two tables. Use the debt IDs introduced in the stages.
159
+ Then add a boundary or counterexample table:
160
+
161
+ ```markdown
162
+ ## Where This Pattern Stops
163
+
164
+ | Counterexample | Why the opposite choice is rational | Boundary rule |
165
+ |---|---|---|
166
+ | <system or system class> | <mechanism-level reason> | <when not to copy the original topic's design> |
167
+ ```
168
+
169
+ Generalization quality rules:
170
+
171
+ - Compare mechanisms, not product categories. "Both rely on OS page cache for immutable segment-like files" is useful; "both are data systems" is not.
172
+ - Include 3-5 sibling systems when there is a real shared principle. If fewer than 3 are defensible, use fewer and explain why.
173
+ - Include at least one counterexample or boundary class when the pattern has a meaningful opposite design. The counterexample should make the original idea clearer, not just criticize another system.
174
+ - Every sibling or counterexample must name the condition that makes the design work or fail: immutable files, append-only logs, random updates, strict transaction control, latency tail sensitivity, memory ownership, coordination scope, compatibility pressure, and so on.
175
+ - Do not imply the original topic's design is universally superior. The goal is "when to copy this idea" and "when not to copy it".
176
+ - For specific comparisons to real systems, verify with primary or high-authority sources when online verification is available.
177
+
178
+ ### 4. Debt Map
179
+
180
+ Create three tables. Use the debt IDs introduced in the stages. A debt is "resolved" only when the original failure mode is structurally removed or no longer a normal user concern. If a later design reduces blast radius, frequency, or operational cost but the pain can still appear, put it under "mitigated", not "resolved".
123
181
 
124
182
  Resolved debt:
125
183
 
@@ -128,6 +186,13 @@ Resolved debt:
128
186
  |---|---|---|---|---|
129
187
  ```
130
188
 
189
+ Mitigated debt:
190
+
191
+ ```markdown
192
+ | Debt ID | Debt | Introduced in | Mitigated in | What improved | What remains |
193
+ |---|---|---|---|---|---|
194
+ ```
195
+
131
196
  Unresolved debt:
132
197
 
133
198
  ```markdown
@@ -137,11 +202,11 @@ Unresolved debt:
137
202
 
138
203
  Debt map quality rules:
139
204
 
140
- - The map must explain "introduced in stage X, resolved in stage Y" where applicable.
205
+ - The map must explain "introduced in stage X, resolved or mitigated in stage Y" where applicable.
141
206
  - Do not list only abstract categories like "operational complexity". Name the concrete failure mode users feel.
142
207
  - Include important unresolved operational pain even if it came from an omitted or secondary stage, but label it clearly.
143
208
 
144
- ### 4. Pain Point Ranking
209
+ ### 5. Pain Point Ranking
145
210
 
146
211
  Rank the top unresolved problems that users still feel today.
147
212
 
@@ -157,8 +222,11 @@ Ranking quality rules:
157
222
  - Prefer production symptoms over abstract labels: "rebalance storms", "cold-read latency", "schema migration pain", "dependency hell", "slow compile times", "state restore time", "version skew".
158
223
  - The one-line explanation should describe what users observe during failure or scale, not just why the architecture is complex.
159
224
  - Competitive attack angles should be concrete. Name a class of alternative system or a known competitor only when the comparison is fair.
225
+ - Do not overclaim in competitive comparisons. If an alternative avoids one pain by accepting another trade-off, state that trade-off briefly instead of implying it is strictly better.
226
+ - Phrase attack angles as trade-off-aware comparisons: "X can attack this by doing Y, but pays Z." Avoid claims like "X does not have this problem" unless a primary source or well-established mechanism supports it.
227
+ - If the comparison would be shallow or unfair, write "N/A" rather than forcing a competitor into the table.
160
228
 
161
- ### 5. Causal Chain
229
+ ### 6. Causal Chain
162
230
 
163
231
  End with a causal chain that makes the evolution memorable. For complex systems, use an ASCII story map rather than a flat paragraph:
164
232
 
@@ -188,17 +256,31 @@ After the chain, add a bold one-sentence version:
188
256
 
189
257
  This sentence should be conversational, sharp, and technically accurate.
190
258
 
191
- ### 6. Sources
259
+ ### 7. Sources
192
260
 
193
- If online verification was used, end with a short source list. Prefer 6-10 high-signal sources over a long bibliography. When possible, group sources by what they support:
261
+ If online verification was used, end with a short source list. Prefer 6-10 high-signal sources over a long bibliography. Split sources into primary and secondary groups. Use secondary sources only when they add useful synthesis or operational perspective, and keep them to at most two items. Do not use a secondary source for a core mechanism when an official design doc, release note, RFC, KIP, PEP, paper, or maintainer explanation exists.
262
+
263
+ Use this format:
194
264
 
195
265
  ```markdown
266
+ Primary sources:
267
+
196
268
  - Foundational papers: <source>
197
269
  - Stage 2 replication: <source>
198
270
  - Stage 5 correctness semantics: <source>
199
271
  - Current pain points: <source>
272
+
273
+ Secondary sources (optional, max 2):
274
+
275
+ - Operational retrospective or synthesis: <source>
200
276
  ```
201
277
 
278
+ Source quality rules:
279
+
280
+ - Every major stage should be supported by at least one primary source when online verification is available.
281
+ - If an important claim is inferred from multiple sources rather than directly stated, mark it as inference in the analysis.
282
+ - Do not cite generic tutorials, SEO summaries, or casual comparison posts for mechanism, history, or version claims.
283
+
202
284
  Do not let sources replace reasoning. The main output should remain the decision tree and debt map.
203
285
 
204
286
  ## Style
@@ -212,6 +294,7 @@ Do not let sources replace reasoning. The main output should remain the decision
212
294
  - Use Chinese if the user is writing Chinese, English if the user is writing English, unless `--lang` overrides.
213
295
  - If the topic is too broad, choose the core system path and say what you intentionally left out.
214
296
  - If the historical record is uncertain, say so and give the most likely interpretation.
297
+ - Match the output language consistently. For non-English output, translate headings and table labels into the user's language instead of leaking English template labels.
215
298
 
216
299
  ## Quality Gate
217
300
 
@@ -219,11 +302,14 @@ Before finalizing, check the answer against these questions:
219
302
 
220
303
  - Could a reader infer the system's evolution from stage 1 to today by following only the trade-offs?
221
304
  - Did you include major debt repayment stages, not just feature releases?
305
+ - Did you include major partial-mitigation stages when a painful debt later received an important fix?
222
306
  - Does every stage have plausible rejected alternatives and a rational chosen path?
223
307
  - Are the pain points concrete production symptoms rather than broad categories?
224
308
  - Does every resolved or unresolved debt connect back to a stage or debt ID?
225
309
  - Is the throughline sharp enough to quote in one sentence?
310
+ - Does the transferable-pattern section show where the core idea works in other systems and where it stops?
226
311
  - Are sources high-signal and tied to the claims they support?
312
+ - Is the language of headings, labels, and section names consistent with the user's language?
227
313
 
228
314
  ## Tool-Specific Invocation Notes
229
315