learnship 1.9.20 → 1.9.22
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/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/README.md +1 -1
- package/agents/learnship-debugger.md +1 -0
- package/agents/learnship-verifier.md +1 -0
- package/cursor-rules/learnship.mdc +48 -0
- package/gemini-extension.json +1 -1
- package/learnship/agents/debugger.md +81 -25
- package/learnship/agents/verifier.md +80 -24
- package/learnship/references/planning-config.md +2 -2
- package/learnship/workflows/add-phase.md +5 -2
- package/learnship/workflows/add-tests.md +2 -0
- package/learnship/workflows/add-todo.md +1 -1
- package/learnship/workflows/audit-milestone.md +1 -0
- package/learnship/workflows/cleanup.md +1 -1
- package/learnship/workflows/complete-milestone.md +2 -1
- package/learnship/workflows/debug.md +2 -2
- package/learnship/workflows/diagnose-issues.md +1 -0
- package/learnship/workflows/discovery-phase.md +6 -0
- package/learnship/workflows/discuss-milestone.md +2 -1
- package/learnship/workflows/discuss-phase.md +2 -1
- package/learnship/workflows/execute-plan.md +1 -0
- package/learnship/workflows/health.md +40 -34
- package/learnship/workflows/insert-phase.md +2 -2
- package/learnship/workflows/ls.md +2 -2
- package/learnship/workflows/map-codebase.md +1 -1
- package/learnship/workflows/milestone-retrospective.md +2 -0
- package/learnship/workflows/new-milestone.md +1 -0
- package/learnship/workflows/new-project.md +37 -15
- package/learnship/workflows/next.md +1 -1
- package/learnship/workflows/pause-work.md +1 -1
- package/learnship/workflows/plan-milestone-gaps.md +3 -1
- package/learnship/workflows/plan-phase.md +1 -1
- package/learnship/workflows/progress.md +2 -2
- package/learnship/workflows/quick.md +5 -3
- package/learnship/workflows/release.md +3 -2
- package/learnship/workflows/remove-phase.md +1 -1
- package/learnship/workflows/research-phase.md +1 -1
- package/learnship/workflows/resume-work.md +3 -3
- package/learnship/workflows/set-profile.md +6 -6
- package/learnship/workflows/settings.md +1 -1
- package/learnship/workflows/sync-upstream-skills.md +1 -1
- package/learnship/workflows/transition.md +1 -1
- package/learnship/workflows/update.md +2 -1
- package/learnship/workflows/validate-phase.md +2 -1
- package/package.json +1 -1
- package/references/planning-config.md +2 -2
|
@@ -13,6 +13,7 @@ Execute a single PLAN.md file in isolation. Useful when one plan in a phase fail
|
|
|
13
13
|
Find the phase directory:
|
|
14
14
|
```bash
|
|
15
15
|
ls .planning/phases/ | grep -E "^0*[phase]-" | head -1
|
|
16
|
+
# PowerShell: Get-ChildItem .planning/phases/ | Where-Object { $_.Name -match "^0*[phase]-" } | Select-Object -First 1 -ExpandProperty Name
|
|
16
17
|
PHASE_DIR=".planning/phases/[matched]"
|
|
17
18
|
```
|
|
18
19
|
|
|
@@ -15,7 +15,7 @@ Check if `--repair` flag is present.
|
|
|
15
15
|
## Step 2: Check Project Exists
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
|
|
18
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning') ? 'OK' : 'MISSING')"
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
If `.planning/` doesn't exist:
|
|
@@ -32,40 +32,49 @@ Run the following checks and classify each as error, warning, or info:
|
|
|
32
32
|
|
|
33
33
|
### Required Files
|
|
34
34
|
```bash
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
35
|
+
node -e "const fs=require('fs'); if(!fs.existsSync('.planning/PROJECT.md')) console.log('E002: PROJECT.md not found')"
|
|
36
|
+
node -e "const fs=require('fs'); if(!fs.existsSync('.planning/ROADMAP.md')) console.log('E003: ROADMAP.md not found')"
|
|
37
|
+
node -e "const fs=require('fs'); if(!fs.existsSync('.planning/STATE.md')) console.log('E004: STATE.md not found (repairable)')"
|
|
38
|
+
node -e "const fs=require('fs'); if(!fs.existsSync('.planning/config.json')) console.log('W003: config.json not found (repairable)')"
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
### Config Validity
|
|
42
42
|
```bash
|
|
43
|
-
|
|
43
|
+
node -e "try{JSON.parse(require('fs').readFileSync('.planning/config.json','utf8'))}catch(e){console.log('E005: config.json parse error (repairable)')}"
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
### State / Roadmap Consistency
|
|
47
47
|
```bash
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
node -e "
|
|
49
|
+
const fs=require('fs');
|
|
50
|
+
if(!fs.existsSync('.planning/STATE.md')||!fs.existsSync('.planning/ROADMAP.md'))process.exit(0);
|
|
51
|
+
const state=fs.readFileSync('.planning/STATE.md','utf8');
|
|
52
|
+
const m=state.match(/^Phase:\s*(\d+)/m);
|
|
53
|
+
if(m){
|
|
54
|
+
const roadmap=fs.readFileSync('.planning/ROADMAP.md','utf8');
|
|
55
|
+
if(!roadmap.includes('Phase '+m[1]+':'))console.log('W002: STATE.md references phase '+m[1]+' not found in roadmap (repairable)');
|
|
56
|
+
}
|
|
57
|
+
"
|
|
53
58
|
```
|
|
54
59
|
|
|
55
60
|
### Phase Directory Checks
|
|
56
61
|
```bash
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
node -e "
|
|
63
|
+
const fs=require('fs'),path=require('path');
|
|
64
|
+
if(!fs.existsSync('.planning/ROADMAP.md'))process.exit(0);
|
|
65
|
+
const roadmap=fs.readFileSync('.planning/ROADMAP.md','utf8');
|
|
66
|
+
const phases=[...roadmap.matchAll(/^## Phase (\d+):/mg)].map(m=>m[1]);
|
|
67
|
+
const phasesDir='.planning/phases';
|
|
68
|
+
const dirs=fs.existsSync(phasesDir)?fs.readdirSync(phasesDir):[];
|
|
69
|
+
for(const n of phases){
|
|
70
|
+
const pad=n.padStart(2,'0');
|
|
71
|
+
if(!dirs.some(d=>d.startsWith(pad+'-')))console.log('W006: Phase '+n+' in roadmap but no directory');
|
|
72
|
+
}
|
|
73
|
+
for(const d of dirs){
|
|
74
|
+
const slug=d.replace(/^\d+-/,'');
|
|
75
|
+
if(!roadmap.includes(slug))console.log('W007: Directory '+d+' not in roadmap');
|
|
76
|
+
}
|
|
77
|
+
"
|
|
69
78
|
```
|
|
70
79
|
|
|
71
80
|
### Plans Without Summaries
|
|
@@ -79,21 +88,18 @@ done
|
|
|
79
88
|
### Uncommitted Changes
|
|
80
89
|
```bash
|
|
81
90
|
git status --short .planning/ 2>/dev/null | head -10
|
|
91
|
+
# PowerShell: git status --short .planning/ 2>$null | Select-Object -First 10
|
|
82
92
|
```
|
|
83
93
|
|
|
84
94
|
### Config Fields
|
|
85
95
|
```bash
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
missing
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
missing.append(key)
|
|
94
|
-
if missing:
|
|
95
|
-
print('W004: config.json missing fields: ' + ', '.join(missing))
|
|
96
|
-
" 2>/dev/null
|
|
96
|
+
node -e "
|
|
97
|
+
try{
|
|
98
|
+
const cfg=JSON.parse(require('fs').readFileSync('.planning/config.json','utf8'));
|
|
99
|
+
const missing=['mode','granularity','model_profile','learning_mode'].filter(k=>!(k in cfg));
|
|
100
|
+
if(missing.length)console.log('W004: config.json missing fields: '+missing.join(', '));
|
|
101
|
+
}catch(e){}
|
|
102
|
+
"
|
|
97
103
|
```
|
|
98
104
|
|
|
99
105
|
## Step 4: Format Output
|
|
@@ -31,7 +31,7 @@ Validate that the after-phase number is an integer.
|
|
|
31
31
|
## Step 2: Validate
|
|
32
32
|
|
|
33
33
|
```bash
|
|
34
|
-
|
|
34
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/ROADMAP.md') ? 'OK' : 'MISSING')"
|
|
35
35
|
```
|
|
36
36
|
|
|
37
37
|
Check that phase `[N]` exists in ROADMAP.md:
|
|
@@ -56,7 +56,7 @@ Generate slug from description (lowercase, hyphens, max 40 chars).
|
|
|
56
56
|
## Step 4: Create Phase Directory
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
|
-
|
|
59
|
+
node -e "require('fs').mkdirSync('.planning/phases/[N].[M]-[SLUG]',{recursive:true})"
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
## Step 5: Update ROADMAP.md
|
|
@@ -13,7 +13,7 @@ The quickest way to answer "where am I and what do I do next?" Works for new use
|
|
|
13
13
|
## Step 1: Check for Project
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
|
|
16
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/PROJECT.md') ? 'EXISTS' : 'MISSING')"
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
**If MISSING** — no project initialized yet. Display:
|
|
@@ -50,7 +50,7 @@ cat .planning/ROADMAP.md
|
|
|
50
50
|
Find the 2–3 most recent SUMMARY.md files:
|
|
51
51
|
|
|
52
52
|
```bash
|
|
53
|
-
|
|
53
|
+
node -e "const fs=require('fs'),path=require('path');function find(d){let r=[];try{for(const e of fs.readdirSync(d,{withFileTypes:true})){const f=path.join(d,e.name);r=r.concat(e.isDirectory()?find(f):e.name.endsWith('-SUMMARY.md')?[f]:[]);}}catch(e){}return r;}const files=find('.planning').map(f=>({f,t:fs.statSync(f).mtimeMs})).sort((a,b)=>b.t-a.t).slice(0,3).map(x=>x.f);files.forEach(f=>console.log(f));"
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
Read each for a one-liner summary of what was accomplished.
|
|
@@ -15,7 +15,9 @@ A structured learning retrospective after a milestone ships. Five focused questi
|
|
|
15
15
|
Read the milestone that just shipped:
|
|
16
16
|
```bash
|
|
17
17
|
ls .planning/milestones/ | sort -V | tail -3
|
|
18
|
+
# PowerShell: Get-ChildItem .planning/milestones/ | Sort-Object Name | Select-Object -Last 3
|
|
18
19
|
cat .planning/milestones/[VERSION]-ROADMAP.md 2>/dev/null | head -60
|
|
20
|
+
# PowerShell: Get-Content .planning/milestones/[VERSION]-ROADMAP.md -ErrorAction SilentlyContinue | Select-Object -First 60
|
|
19
21
|
```
|
|
20
22
|
|
|
21
23
|
Read all phase SUMMARY.md files from this milestone:
|
|
@@ -48,6 +48,7 @@ Follow the thread. When you have enough to write clear goals, ask for confirmati
|
|
|
48
48
|
Read the last version from `.planning/milestones/`:
|
|
49
49
|
```bash
|
|
50
50
|
ls .planning/milestones/ | grep -E "^v[0-9]" | sort -V | tail -3
|
|
51
|
+
# PowerShell: Get-ChildItem .planning/milestones/ | Where-Object { $_.Name -match '^v[0-9]' } | Sort-Object Name | Select-Object -Last 3
|
|
51
52
|
```
|
|
52
53
|
|
|
53
54
|
Propose the next version (e.g., `v1.0 → v1.1`, or `v2.0` for a major scope change). Confirm with user or let them specify.
|
|
@@ -6,16 +6,29 @@ description: Initialize a new project — questioning → research → requireme
|
|
|
6
6
|
|
|
7
7
|
Initialize a new project with full context gathering, optional research, requirements scoping, and roadmap creation. This is the most leveraged moment in any project — deep questioning now means better plans, better execution, better outcomes.
|
|
8
8
|
|
|
9
|
+
> **This workflow has 9 mandatory steps. You must complete every step in order. Do not skip, defer, or abbreviate any step. Check each one off as you complete it:**
|
|
10
|
+
>
|
|
11
|
+
> - [ ] Step 1 — Setup & codebase check
|
|
12
|
+
> - [ ] Step 1b — Existing codebase scan (if applicable)
|
|
13
|
+
> - [ ] Step 2 — Configuration questions
|
|
14
|
+
> - [ ] Step 3 — Deep questioning (4 exchanges)
|
|
15
|
+
> - [ ] Step 4 — Write and confirm PROJECT.md
|
|
16
|
+
> - [ ] Step 5 — Research decision (ask user, wait for answer)
|
|
17
|
+
> - [ ] Step 6 — Define requirements (interactive)
|
|
18
|
+
> - [ ] Step 7 — Create and approve roadmap
|
|
19
|
+
> - [ ] Step 8 — Generate AGENTS.md ← **mandatory, never skip**
|
|
20
|
+
> - [ ] Step 9 — Done banner + next step
|
|
21
|
+
|
|
9
22
|
## Step 1: Setup
|
|
10
23
|
|
|
11
|
-
|
|
24
|
+
You are running on **Windsurf**. Platform config directory: `.windsurf/`
|
|
12
25
|
|
|
13
26
|
> **Routing protocol suspended.** While this workflow is running, every user message is an answer to a workflow question — not a task to route. Do NOT apply the request routing protocol until `/new-project` is fully complete and `.planning/PROJECT.md` exists.
|
|
14
27
|
|
|
15
28
|
Check if `.planning/PROJECT.md` already exists:
|
|
16
29
|
|
|
17
30
|
```bash
|
|
18
|
-
|
|
31
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/PROJECT.md') ? 'EXISTS' : 'NEW')"
|
|
19
32
|
```
|
|
20
33
|
|
|
21
34
|
**If EXISTS:** Stop. Project already initialized. Use the `progress` workflow to see where you are.
|
|
@@ -23,11 +36,11 @@ python3 -c "import os; print('EXISTS' if os.path.exists('.planning/PROJECT.md')
|
|
|
23
36
|
**Check for an existing codebase:**
|
|
24
37
|
|
|
25
38
|
```bash
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
39
|
+
node -e "
|
|
40
|
+
const fs=require('fs'),path=require('path');
|
|
41
|
+
function walk(dir,skip){let n=0;try{for(const e of fs.readdirSync(dir,{withFileTypes:true})){const f=path.join(dir,e.name);if(skip.some(s=>f.includes(s)))continue;n+=e.isDirectory()?walk(f,skip):1;}}catch(e){}return n;}
|
|
42
|
+
const n=walk('.',['/.git/','node_modules','.planning','__pycache__','.venv']);
|
|
43
|
+
console.log(n>2?'HAS_CODE':'BLANK');console.log(n+' files');
|
|
31
44
|
"
|
|
32
45
|
```
|
|
33
46
|
|
|
@@ -36,7 +49,7 @@ print(f'{len(files)} files')
|
|
|
36
49
|
Check if git is initialized:
|
|
37
50
|
|
|
38
51
|
```bash
|
|
39
|
-
|
|
52
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.git') ? 'HAS_GIT' : 'NO_GIT')"
|
|
40
53
|
```
|
|
41
54
|
|
|
42
55
|
**If NO_GIT:**
|
|
@@ -46,12 +59,12 @@ git init
|
|
|
46
59
|
|
|
47
60
|
Add the platform config directory to `.gitignore` so AI platform files are not tracked in the project repo:
|
|
48
61
|
```bash
|
|
49
|
-
|
|
62
|
+
grep -q '.windsurf/' .gitignore 2>/dev/null || echo '.windsurf/' >> .gitignore
|
|
50
63
|
```
|
|
51
64
|
|
|
52
65
|
Create the planning directory:
|
|
53
66
|
```bash
|
|
54
|
-
|
|
67
|
+
node -e "require('fs').mkdirSync('.planning/research',{recursive:true})"
|
|
55
68
|
```
|
|
56
69
|
|
|
57
70
|
## Step 1b: Existing Codebase Scan (only if EXISTING_CODEBASE = true)
|
|
@@ -60,6 +73,7 @@ If `EXISTING_CODEBASE = true`, do a quick structural scan before questioning so
|
|
|
60
73
|
|
|
61
74
|
```bash
|
|
62
75
|
find . -maxdepth 3 -not -path './.git/*' -not -path './node_modules/*' -not -path './.planning/*' -not -path './__pycache__/*' -not -path './.venv/*' | sort | head -40
|
|
76
|
+
# PowerShell: Get-ChildItem -Recurse -Depth 3 | Where-Object { $_.FullName -notmatch '\.git|node_modules|\.planning|__pycache__|\.venv' } | Select-Object -First 40
|
|
63
77
|
```
|
|
64
78
|
|
|
65
79
|
Note the tech stack, key directories, and any README content internally. Use this ONLY to ask sharper follow-up questions — never to infer the user's intent or skip ceremony steps.
|
|
@@ -92,7 +106,9 @@ Ask: "Which workflow agents should be enabled?"
|
|
|
92
106
|
- **Plan Check** (recommended) — Verify plans achieve their goals before execution
|
|
93
107
|
- **Verifier** (recommended) — Confirm deliverables match phase goals after execution
|
|
94
108
|
|
|
95
|
-
|
|
109
|
+
**Group D — Parallel execution:**
|
|
110
|
+
|
|
111
|
+
Windsurf does not support real subagents. Parallelization is automatically set to `false`.
|
|
96
112
|
|
|
97
113
|
Ask: "Commit planning docs to git?"
|
|
98
114
|
- **Yes** (recommended) — Planning docs tracked in version control
|
|
@@ -208,15 +224,15 @@ If user requests changes: update PROJECT.md, show the full file again, re-ask th
|
|
|
208
224
|
git add .planning/PROJECT.md && git commit -m "docs: initialize project"
|
|
209
225
|
```
|
|
210
226
|
|
|
211
|
-
> 🛑 STOP.
|
|
227
|
+
> 🛑 STOP — **Step 4 complete. You MUST now ask the research question (Step 5) before writing any other file.** Do not write REQUIREMENTS.md. Do not write ROADMAP.md. Do not proceed to any other step. The next action is to ask the user exactly one question: whether to research the domain first.
|
|
212
228
|
|
|
213
229
|
## Step 5: Research Decision
|
|
214
230
|
|
|
215
|
-
Ask: "
|
|
231
|
+
Ask: **"Before I write the requirements — do you want me to research the domain ecosystem first?"**
|
|
216
232
|
- **Research first** (recommended) — Discover standard stacks, expected features, architecture patterns
|
|
217
233
|
- **Skip research** — I know this domain well, go straight to requirements
|
|
218
234
|
|
|
219
|
-
> 🛑 STOP. Wait for the user's explicit choice
|
|
235
|
+
> 🛑 STOP. Wait for the user's explicit choice. Do not default to either option. Do not write REQUIREMENTS.md yet. Do not proceed until the user replies.
|
|
220
236
|
|
|
221
237
|
**If Research first:**
|
|
222
238
|
|
|
@@ -325,6 +341,8 @@ Ask for approval:
|
|
|
325
341
|
git add .planning/ROADMAP.md .planning/STATE.md .planning/REQUIREMENTS.md && git commit -m "docs: create roadmap ([N] phases)"
|
|
326
342
|
```
|
|
327
343
|
|
|
344
|
+
> 🛑 STOP — **Step 7 complete. You MUST now generate AGENTS.md (Step 8) before anything else.** Do not display the done banner. Do not suggest next steps. Do not end the workflow. The roadmap is approved — AGENTS.md is next.
|
|
345
|
+
|
|
328
346
|
## Step 8: Generate AGENTS.md
|
|
329
347
|
|
|
330
348
|
> **🔴 MANDATORY — This step must always be completed. Do not skip it, do not defer it, do not move to Step 9 without writing AGENTS.md to the project root. AGENTS.md is the persistent memory file that every future session depends on.**
|
|
@@ -336,6 +354,7 @@ Fill in the placeholder sections using information gathered in this session:
|
|
|
336
354
|
**Project Structure** — derive from the project description and any existing directories:
|
|
337
355
|
```bash
|
|
338
356
|
find . -maxdepth 2 -not -path './.git/*' -not -path './node_modules/*' -not -path './.planning/*' -type d | sort | head -20
|
|
357
|
+
# PowerShell: Get-ChildItem -Directory -Recurse -Depth 2 | Where-Object { $_.FullName -notmatch '\.git|node_modules|\.planning' } | Select-Object -First 20
|
|
339
358
|
```
|
|
340
359
|
|
|
341
360
|
Populate the `## Project Structure` tree with real directories and one-line descriptions.
|
|
@@ -378,7 +397,10 @@ Files created:
|
|
|
378
397
|
- .planning/config.json
|
|
379
398
|
[- .planning/research/ (if research was run)]
|
|
380
399
|
|
|
381
|
-
▶ Next: discuss-phase 1
|
|
400
|
+
▶ Next: `/discuss-phase 1` — **start here, not `/plan-phase`**
|
|
401
|
+
|
|
402
|
+
The phase loop is: `discuss-phase` → `plan-phase` → `execute-phase` → `verify-work`
|
|
403
|
+
`discuss-phase` is mandatory before planning — it captures your intent and writes the CONTEXT.md that plan-phase depends on. Skipping it means planning without context.
|
|
382
404
|
|
|
383
405
|
> **Platform detected:** `[PLATFORM]` — parallelization is `[true/false]`
|
|
384
406
|
```
|
|
@@ -13,7 +13,7 @@ Reads project state and runs the right next workflow automatically. No need to r
|
|
|
13
13
|
## Step 1: Check for Project
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
|
|
16
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/PROJECT.md') ? 'EXISTS' : 'MISSING')"
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
**If MISSING:**
|
|
@@ -12,7 +12,7 @@ Create a `.continue-here.md` handoff file that captures complete work state. Ena
|
|
|
12
12
|
|
|
13
13
|
Find the most recently active phase:
|
|
14
14
|
```bash
|
|
15
|
-
|
|
15
|
+
node -e "const fs=require('fs'),path=require('path');function find(d){let r=[];try{for(const e of fs.readdirSync(d,{withFileTypes:true})){const f=path.join(d,e.name);r=r.concat(e.isDirectory()?find(f):e.name.endsWith('-PLAN.md')?[f]:[]);}}catch(e){}return r;}const files=find('.planning/phases').map(f=>({f,t:fs.statSync(f).mtimeMs})).sort((a,b)=>b.t-a.t);if(files[0])console.log(files[0].f);"
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
Extract the phase directory name from the result.
|
|
@@ -13,6 +13,7 @@ Create all phases needed to close gaps identified by `audit-milestone`. One work
|
|
|
13
13
|
Find the most recent audit file:
|
|
14
14
|
```bash
|
|
15
15
|
ls -t .planning/*-MILESTONE-AUDIT.md 2>/dev/null | head -1
|
|
16
|
+
# PowerShell: Get-ChildItem .planning/*-MILESTONE-AUDIT.md -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
|
16
17
|
```
|
|
17
18
|
|
|
18
19
|
If no audit file exists or status is `passed`:
|
|
@@ -74,6 +75,7 @@ Gap: Flow "User stays logged in" broken
|
|
|
74
75
|
Find the highest existing phase number:
|
|
75
76
|
```bash
|
|
76
77
|
ls .planning/phases/ | grep -E "^[0-9]" | sort -V | tail -1
|
|
78
|
+
# PowerShell: Get-ChildItem .planning/phases/ | Where-Object { $_.Name -match '^[0-9]' } | Sort-Object Name | Select-Object -Last 1
|
|
77
79
|
```
|
|
78
80
|
|
|
79
81
|
Gap closure phases continue from the highest existing phase + 1.
|
|
@@ -131,7 +133,7 @@ For each unsatisfied requirement being addressed:
|
|
|
131
133
|
|
|
132
134
|
```bash
|
|
133
135
|
for each gap closure phase:
|
|
134
|
-
|
|
136
|
+
node -e "require('fs').mkdirSync('.planning/phases/[NN]-[slug]',{recursive:true})"
|
|
135
137
|
done
|
|
136
138
|
```
|
|
137
139
|
|
|
@@ -25,7 +25,7 @@ cat .planning/config.json
|
|
|
25
25
|
|
|
26
26
|
Create the phase directory if it doesn't exist:
|
|
27
27
|
```bash
|
|
28
|
-
|
|
28
|
+
node -e "require('fs').mkdirSync('.planning/phases/[padded_phase]-[phase_slug]',{recursive:true})"
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
Check what already exists:
|
|
@@ -9,7 +9,7 @@ Check where you are in the project, what's been done, and what comes next.
|
|
|
9
9
|
## Step 1: Check for Planning Structure
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
|
|
12
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/PROJECT.md') ? 'EXISTS' : 'MISSING')"
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
If `.planning/` doesn't exist: stop — run `new-project` to initialize.
|
|
@@ -24,7 +24,7 @@ cat .planning/ROADMAP.md
|
|
|
24
24
|
|
|
25
25
|
Find the 2-3 most recent SUMMARY.md files:
|
|
26
26
|
```bash
|
|
27
|
-
|
|
27
|
+
node -e "const fs=require('fs'),path=require('path');function find(d){let r=[];try{for(const e of fs.readdirSync(d,{withFileTypes:true})){const f=path.join(d,e.name);r=r.concat(e.isDirectory()?find(f):e.name.endsWith('-SUMMARY.md')?[f]:[]);}}catch(e){}return r;}const files=find('.planning').map(f=>({f,t:fs.statSync(f).mtimeMs})).sort((a,b)=>b.t-a.t).slice(0,3).map(x=>x.f);files.forEach(f=>console.log(f));"
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
Read each to extract what was recently accomplished (one-liner per plan).
|
|
@@ -34,7 +34,7 @@ Display banner based on active flags:
|
|
|
34
34
|
|
|
35
35
|
Check that a project exists:
|
|
36
36
|
```bash
|
|
37
|
-
|
|
37
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/PROJECT.md') ? 'OK' : 'MISSING')"
|
|
38
38
|
```
|
|
39
39
|
|
|
40
40
|
If PROJECT.md missing: stop — run `new-project` first. Quick tasks require an active project.
|
|
@@ -46,13 +46,15 @@ Generate a slug from the description (lowercase, hyphens, max 40 chars).
|
|
|
46
46
|
Find the next task number:
|
|
47
47
|
```bash
|
|
48
48
|
ls .planning/quick/ 2>/dev/null | grep -E "^[0-9]+" | sort -n | tail -1
|
|
49
|
+
# PowerShell: Get-ChildItem .planning/quick/ -ErrorAction SilentlyContinue | Where-Object { $_.Name -match '^[0-9]+' } | Sort-Object Name | Select-Object -Last 1
|
|
49
50
|
```
|
|
50
51
|
|
|
51
52
|
Set `NEXT_NUM` to the next available number (001, 002, etc.).
|
|
52
53
|
|
|
53
54
|
Create task directory:
|
|
54
55
|
```bash
|
|
55
|
-
|
|
56
|
+
node -e "require('fs').mkdirSync('.planning/quick/${NEXT_NUM}-${SLUG}',{recursive:true})"
|
|
57
|
+
# PowerShell: New-Item -ItemType Directory -Force -Path ".planning/quick/${NEXT_NUM}-${SLUG}"
|
|
56
58
|
```
|
|
57
59
|
|
|
58
60
|
Report: "Creating quick task ${NEXT_NUM}: ${DESCRIPTION}"
|
|
@@ -130,7 +132,7 @@ If `--full`: also include `must_haves` in plan frontmatter (truths, artifacts, k
|
|
|
130
132
|
|
|
131
133
|
Verify plan was created (substitute actual NEXT_NUM and SLUG values):
|
|
132
134
|
```bash
|
|
133
|
-
|
|
135
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/quick/NEXT_NUM-SLUG/NEXT_NUM-PLAN.md') ? 'OK' : 'MISSING')"
|
|
134
136
|
```
|
|
135
137
|
|
|
136
138
|
## Step 5: Plan Check (only with `--full`)
|
|
@@ -168,10 +168,10 @@ curl -s -X POST \
|
|
|
168
168
|
\"tag_name\": \"vX.Y.Z\",
|
|
169
169
|
\"target_commitish\": \"main\",
|
|
170
170
|
\"name\": \"vX.Y.Z — [Short title]\",
|
|
171
|
-
\"body\": $(
|
|
171
|
+
\"body\": $(node -e "process.stdout.write(JSON.stringify(require('fs').readFileSync('/dev/stdin','utf8')))" <<< "$RELEASE_NOTES"),
|
|
172
172
|
\"draft\": false,
|
|
173
173
|
\"prerelease\": false
|
|
174
|
-
}" |
|
|
174
|
+
}" | node -e "let d='';process.stdin.on('data',c=>d+=c).on('end',()=>{const r=JSON.parse(d);console.log(r.html_url||r.message||'ERROR');})"
|
|
175
175
|
```
|
|
176
176
|
|
|
177
177
|
If successful, the release URL is printed.
|
|
@@ -198,6 +198,7 @@ git remote -v
|
|
|
198
198
|
```bash
|
|
199
199
|
git log --oneline public-main -3 # new release commit at top
|
|
200
200
|
git tag --sort=-version:refname | head -5 # new tag at top
|
|
201
|
+
# PowerShell: git tag --sort=-version:refname | Select-Object -First 5
|
|
201
202
|
```
|
|
202
203
|
|
|
203
204
|
Open the release URL printed in Step 11 to confirm it looks correct on GitHub.
|
|
@@ -22,7 +22,7 @@ Example: remove-phase 7
|
|
|
22
22
|
|
|
23
23
|
Check roadmap exists:
|
|
24
24
|
```bash
|
|
25
|
-
|
|
25
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/ROADMAP.md') ? 'OK' : 'MISSING')"
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
## Step 2: Verify the Phase is Future
|
|
@@ -13,7 +13,7 @@ Run standalone domain research for a phase. Useful when the domain is unfamiliar
|
|
|
13
13
|
## Step 1: Validate Phase
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
|
|
16
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/ROADMAP.md') ? 'OK' : 'MISSING')"
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Find phase `[N]` in ROADMAP.md:
|
|
@@ -9,9 +9,9 @@ Instantly restore full project context. Use when starting a new session, returni
|
|
|
9
9
|
## Step 1: Check Planning Structure
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/STATE.md') ? 'HAS_STATE' : 'NO_STATE')"
|
|
13
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/PROJECT.md') ? 'HAS_PROJECT' : 'NO_PROJECT')"
|
|
14
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/ROADMAP.md') ? 'HAS_ROADMAP' : 'NO_ROADMAP')"
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
If nothing exists: stop — run `new-project` to start a project.
|
|
@@ -51,12 +51,12 @@ Stop.
|
|
|
51
51
|
Update the `model_profile` field in `.planning/config.json`:
|
|
52
52
|
|
|
53
53
|
```bash
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
cfg
|
|
57
|
-
cfg
|
|
58
|
-
|
|
59
|
-
|
|
54
|
+
node -e "
|
|
55
|
+
const fs=require('fs');
|
|
56
|
+
const cfg=JSON.parse(fs.readFileSync('.planning/config.json','utf8'));
|
|
57
|
+
cfg.model_profile='[profile]';
|
|
58
|
+
fs.writeFileSync('.planning/config.json',JSON.stringify(cfg,null,2));
|
|
59
|
+
console.log('Updated.');
|
|
60
60
|
"
|
|
61
61
|
```
|
|
62
62
|
|
|
@@ -11,7 +11,7 @@ Interactive configuration editor for the current project. Updates `.planning/con
|
|
|
11
11
|
## Step 1: Ensure Config Exists
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
|
|
14
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/config.json') ? 'exists' : 'missing')"
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
If missing, create from template:
|
|
@@ -97,7 +97,7 @@ Confirm both clones succeeded — `SKILL.md` must exist in `$AGENTIC_LEARN_TMP`
|
|
|
97
97
|
|
|
98
98
|
```bash
|
|
99
99
|
BACKUP_DIR="$(pwd)/.windsurf/skills/.upstream-backup-$(date +%Y%m%d-%H%M%S)"
|
|
100
|
-
|
|
100
|
+
node -e "require('fs').mkdirSync('$BACKUP_DIR',{recursive:true})"
|
|
101
101
|
|
|
102
102
|
cp -r "$(pwd)/.windsurf/skills/agentic-learning" "$BACKUP_DIR/agentic-learning"
|
|
103
103
|
cp -r "$(pwd)/.windsurf/skills/impeccable" "$BACKUP_DIR/impeccable"
|
|
@@ -27,7 +27,7 @@ find .planning/ -name "*.md" | sort
|
|
|
27
27
|
|
|
28
28
|
Read the most recent SUMMARY.md files (last 3 phases):
|
|
29
29
|
```bash
|
|
30
|
-
|
|
30
|
+
node -e "const fs=require('fs'),path=require('path');function find(d){let r=[];try{for(const e of fs.readdirSync(d,{withFileTypes:true})){const f=path.join(d,e.name);r=r.concat(e.isDirectory()?find(f):e.name.endsWith('-SUMMARY.md')?[f]:[]);}}catch(e){}return r;}const files=find('.planning/phases').map(f=>({f,t:fs.statSync(f).mtimeMs})).sort((a,b)=>b.t-a.t).slice(0,6).map(x=>x.f);files.forEach(f=>console.log(f));"
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
Check git status:
|
|
@@ -35,6 +35,7 @@ for loc in \
|
|
|
35
35
|
"$HOME/favio/learnship" \
|
|
36
36
|
"$HOME/learnship" \
|
|
37
37
|
"$(find $HOME -name "install.sh" -path "*/learnship/*" 2>/dev/null | head -1 | xargs dirname 2>/dev/null)"; do
|
|
38
|
+
# PowerShell: (Get-ChildItem $HOME -Recurse -Filter install.sh -ErrorAction SilentlyContinue | Where-Object { $_.FullName -match 'learnship' } | Select-Object -First 1).DirectoryName
|
|
38
39
|
test -d "$loc/.windsurf/workflows" && SOURCE_DIR="$loc" && break
|
|
39
40
|
done
|
|
40
41
|
```
|
|
@@ -93,7 +94,7 @@ Stop.
|
|
|
93
94
|
For any workflow file that exists in install dir AND differs from source AND differs from the current source (meaning you modified it):
|
|
94
95
|
|
|
95
96
|
```bash
|
|
96
|
-
|
|
97
|
+
node -e "require('fs').mkdirSync('$INSTALL_DIR/local-patches',{recursive:true})"
|
|
97
98
|
```
|
|
98
99
|
|
|
99
100
|
For each locally modified file:
|
|
@@ -22,7 +22,7 @@ If `nyquist_validation: false`: stop — "Validation is disabled. Enable it in `
|
|
|
22
22
|
## Step 2: Validate Phase
|
|
23
23
|
|
|
24
24
|
```bash
|
|
25
|
-
|
|
25
|
+
node -e "const fs=require('fs'); console.log(fs.existsSync('.planning/ROADMAP.md') ? 'OK' : 'MISSING')"
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
Determine the phase directory:
|
|
@@ -61,6 +61,7 @@ Extract:
|
|
|
61
61
|
find . \( -name "jest.config.*" -o -name "vitest.config.*" -o -name "pytest.ini" -o -name "pyproject.toml" \) -not -path "*/node_modules/*" 2>/dev/null
|
|
62
62
|
|
|
63
63
|
find . \( -name "*.test.*" -o -name "*.spec.*" -o -name "test_*.py" \) -not -path "*/node_modules/*" 2>/dev/null | head -20
|
|
64
|
+
# PowerShell: Get-ChildItem -Recurse | Where-Object { $_.Name -match '\.test\.|spec\.|^test_.*\.py' -and $_.FullName -notmatch 'node_modules' } | Select-Object -First 20
|
|
64
65
|
```
|
|
65
66
|
|
|
66
67
|
Identify: test framework, how to run tests, existing test file patterns.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "learnship",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.22",
|
|
4
4
|
"description": "Learn as you build. Build with intent. — A multi-platform agentic engineering system for Windsurf, Claude Code, Cursor, OpenCode, Gemini CLI, and Codex: spec-driven workflows, integrated learning, and production-grade design.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentic",
|
|
@@ -40,7 +40,7 @@ Configuration options for `.planning/` directory behavior.
|
|
|
40
40
|
|
|
41
41
|
```bash
|
|
42
42
|
# Read commit_docs from config.json
|
|
43
|
-
COMMIT_DOCS=$(
|
|
43
|
+
COMMIT_DOCS=$(node -e "try{const c=JSON.parse(require('fs').readFileSync('.planning/config.json','utf8'));process.stdout.write(String((c.planning||{}).commit_docs??'true'));}catch(e){process.stdout.write('true');}" 2>/dev/null || echo 'true')
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
**Auto-detection:** If `.planning/` is gitignored, treat `commit_docs` as `false` regardless of config.json. This prevents git errors.
|
|
@@ -139,7 +139,7 @@ To use uncommitted mode:
|
|
|
139
139
|
|
|
140
140
|
Read config directly:
|
|
141
141
|
```bash
|
|
142
|
-
|
|
142
|
+
node -e "const c=JSON.parse(require('fs').readFileSync('.planning/config.json','utf8')),g=c.git||{};console.log(g.branching_strategy||'none',g.phase_branch_template||'phase-{phase}-{slug}',g.milestone_branch_template||'{milestone}-{slug}')"
|
|
143
143
|
```
|
|
144
144
|
|
|
145
145
|
**Branch creation:**
|