@try-works/dsh-recursive-mode 0.1.0

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.
Files changed (88) hide show
  1. package/cordis.patch.yml +12 -0
  2. package/lib/bootstrap.d.ts +35 -0
  3. package/lib/client/board.d.ts +10 -0
  4. package/lib/client/contract.d.ts +51 -0
  5. package/lib/client/derive.d.ts +92 -0
  6. package/lib/client/index.d.ts +21 -0
  7. package/lib/client/inspector.d.ts +10 -0
  8. package/lib/client/node.d.ts +71 -0
  9. package/lib/client/settings.d.ts +6 -0
  10. package/lib/client/slots.d.ts +7 -0
  11. package/lib/client/strip.d.ts +7 -0
  12. package/lib/client.d.ts +10 -0
  13. package/lib/client.js +490 -0
  14. package/lib/closeout.d.ts +23 -0
  15. package/lib/commands.d.ts +51 -0
  16. package/lib/delegation.d.ts +92 -0
  17. package/lib/enforcement.d.ts +53 -0
  18. package/lib/events.d.ts +173 -0
  19. package/lib/handoff.d.ts +51 -0
  20. package/lib/index.d.ts +40 -0
  21. package/lib/lifecycle.d.ts +107 -0
  22. package/lib/lock.d.ts +92 -0
  23. package/lib/policy.d.ts +12 -0
  24. package/lib/projection.d.ts +29 -0
  25. package/lib/recursive_closeout.tool.d.ts +8 -0
  26. package/lib/recursive_init.tool.d.ts +2 -0
  27. package/lib/recursive_lint.tool.d.ts +2 -0
  28. package/lib/recursive_lock.tool.d.ts +2 -0
  29. package/lib/recursive_scratch.tool.d.ts +7 -0
  30. package/lib/recursive_status.tool.d.ts +2 -0
  31. package/lib/review.d.ts +39 -0
  32. package/lib/router.d.ts +77 -0
  33. package/lib/run.d.ts +29 -0
  34. package/lib/runtime.d.ts +241 -0
  35. package/lib/scratch.d.ts +18 -0
  36. package/lib/status.d.ts +19 -0
  37. package/lib/types.d.ts +104 -0
  38. package/lib/workspace.d.ts +50 -0
  39. package/package.json +119 -0
  40. package/preset/recursive/agent.cordis.yml +282 -0
  41. package/preset/recursive/preset.yml +3 -0
  42. package/scripts/install-recursive-mode.ps1 +956 -0
  43. package/scripts/install-recursive-mode.py +750 -0
  44. package/scripts/lint-recursive-run.py +2868 -0
  45. package/scripts/recursive-closeout.py +541 -0
  46. package/scripts/recursive-init.py +356 -0
  47. package/scripts/recursive-lock.py +302 -0
  48. package/scripts/recursive-status.py +2124 -0
  49. package/scripts/recursive_phase_rules.py +367 -0
  50. package/scripts/recursive_router_lib.py +2282 -0
  51. package/scripts/test-recursive-mode-smoke.ts +204 -0
  52. package/scripts/verify-locks.py +353 -0
  53. package/src/bootstrap.ts +118 -0
  54. package/src/client/board.tsx +61 -0
  55. package/src/client/contract.ts +58 -0
  56. package/src/client/derive.ts +241 -0
  57. package/src/client/index.ts +28 -0
  58. package/src/client/inspector.tsx +49 -0
  59. package/src/client/node.ts +156 -0
  60. package/src/client/settings.tsx +18 -0
  61. package/src/client/slots.ts +67 -0
  62. package/src/client/strip.tsx +28 -0
  63. package/src/client.ts +11 -0
  64. package/src/closeout.ts +183 -0
  65. package/src/commands.ts +142 -0
  66. package/src/delegation.ts +306 -0
  67. package/src/enforcement.ts +180 -0
  68. package/src/events.ts +173 -0
  69. package/src/handoff.ts +165 -0
  70. package/src/index.ts +283 -0
  71. package/src/lifecycle.ts +235 -0
  72. package/src/lock.ts +369 -0
  73. package/src/policy.ts +56 -0
  74. package/src/projection.ts +237 -0
  75. package/src/recursive_closeout.tool.ts +35 -0
  76. package/src/recursive_init.tool.ts +28 -0
  77. package/src/recursive_lint.tool.ts +29 -0
  78. package/src/recursive_lock.tool.ts +33 -0
  79. package/src/recursive_scratch.tool.ts +42 -0
  80. package/src/recursive_status.tool.ts +24 -0
  81. package/src/review.ts +178 -0
  82. package/src/router.ts +197 -0
  83. package/src/run.ts +85 -0
  84. package/src/runtime.ts +564 -0
  85. package/src/scratch.ts +85 -0
  86. package/src/status.ts +194 -0
  87. package/src/types.ts +112 -0
  88. package/src/workspace.ts +67 -0
@@ -0,0 +1,750 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Cross-platform installer/bootstrapper for recursive-mode.
4
+
5
+ Behavior is shared with install-recursive-mode.ps1:
6
+ - creates the canonical .recursive/ control-plane layout
7
+ - upserts the canonical workflow into .recursive/RECURSIVE.md
8
+ - creates a lightweight .recursive/AGENTS.md router for internal doc discovery
9
+ - upserts the primary Codex AGENTS bridge into .codex/AGENTS.md
10
+ - upserts the primary Codex plans bridge into .agent/PLANS.md
11
+ - upserts stable assistant-memory pointers into .cursorrules, CLAUDE.md, and .github/copilot-instructions.md
12
+ - bootstraps training memory under .recursive/memory/training/
13
+ - copies the packaged runtime scripts into .recursive/scripts/
14
+ - ensures the routed delegation policy scaffold exists under .recursive/config/
15
+ - adds the device-local router discovery inventory to .gitignore
16
+ - mirrors the AGENTS bridge into repo-root AGENTS.md when that file already exists
17
+ - preserves unrelated existing file content
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import argparse
23
+ import re
24
+ import sys
25
+ from pathlib import Path
26
+
27
+ SCRIPT_DIR = Path(__file__).resolve().parent
28
+ if str(SCRIPT_DIR) not in sys.path:
29
+ sys.path.insert(0, str(SCRIPT_DIR))
30
+
31
+ from recursive_router_lib import RouterConfigError, ensure_router_scaffold
32
+
33
+
34
+ def write_utf8_no_bom(path: Path, content: str) -> None:
35
+ path.write_text(content, encoding="utf-8", newline="\n")
36
+
37
+
38
+ def ensure_directory(path: Path) -> None:
39
+ if not path.exists():
40
+ path.mkdir(parents=True, exist_ok=True)
41
+ print(f"[OK] Created directory: {path}")
42
+ else:
43
+ print(f"[OK] Directory exists: {path}")
44
+
45
+
46
+ def ensure_file(path: Path, content: str) -> None:
47
+ if not path.exists():
48
+ if path.parent:
49
+ ensure_directory(path.parent)
50
+ write_utf8_no_bom(path, content)
51
+ print(f"[OK] Created file: {path}")
52
+ else:
53
+ print(f"[OK] File exists: {path}")
54
+
55
+
56
+ def ensure_gitignore_line(repo_root: Path, line: str) -> None:
57
+ gitignore_path = repo_root / ".gitignore"
58
+ normalized_line = line.strip()
59
+ existing = gitignore_path.read_text(encoding="utf-8") if gitignore_path.exists() else ""
60
+ existing_lines = existing.splitlines()
61
+ if any(candidate.strip() == normalized_line for candidate in existing_lines):
62
+ print(f"[OK] File already up to date: {gitignore_path}")
63
+ return
64
+ updated = existing
65
+ if updated and not updated.endswith("\n"):
66
+ updated += "\n"
67
+ updated += normalized_line + "\n"
68
+ write_utf8_no_bom(gitignore_path, updated)
69
+ action = "Updated" if existing else "Created"
70
+ print(f"[OK] {action} file: {gitignore_path}")
71
+
72
+
73
+ def resolve_canonical_workflow_path(skill_root: Path) -> Path:
74
+ candidates = [
75
+ skill_root / ".recursive" / "RECURSIVE.md",
76
+ skill_root / "references" / "bootstrap" / "RECURSIVE.md",
77
+ ]
78
+ for candidate in candidates:
79
+ if candidate.exists():
80
+ print(f"[INFO] Using canonical workflow template: {candidate}")
81
+ return candidate
82
+ raise FileNotFoundError(
83
+ "Missing canonical workflow template. Expected one of: "
84
+ + ", ".join(str(candidate) for candidate in candidates)
85
+ )
86
+
87
+
88
+ def upsert_marked_block(file_path: Path, start_marker: str, end_marker: str, block_body: str) -> None:
89
+ existing = file_path.read_text(encoding="utf-8") if file_path.exists() else ""
90
+ block = f"{start_marker}\n{block_body}\n{end_marker}"
91
+ pattern = re.compile(rf"{re.escape(start_marker)}.*?{re.escape(end_marker)}", re.DOTALL)
92
+
93
+ if pattern.search(existing):
94
+ updated = pattern.sub(lambda _match: block, existing)
95
+ elif existing.strip():
96
+ updated = f"{existing.rstrip()}\n\n{block}\n"
97
+ else:
98
+ updated = f"{block}\n"
99
+
100
+ if updated != existing:
101
+ write_utf8_no_bom(file_path, updated)
102
+ print(f"[OK] Updated file: {file_path}")
103
+ else:
104
+ print(f"[OK] File already up to date: {file_path}")
105
+
106
+
107
+ def normalize_plain_or_wrapped_content(content: str, start_marker: str, end_marker: str) -> str:
108
+ start_index = content.find(start_marker)
109
+ end_index = content.rfind(end_marker)
110
+ if start_index == -1 or end_index == -1 or end_index < start_index:
111
+ return content.rstrip("\r\n")
112
+ prefix = content[:start_index].rstrip("\r\n")
113
+ if prefix.strip():
114
+ return prefix
115
+ body_start = start_index + len(start_marker)
116
+ return content[body_start:end_index].strip("\r\n")
117
+
118
+
119
+ def sync_plain_file(file_path: Path, content: str) -> None:
120
+ normalized = content.rstrip("\r\n") + "\n"
121
+ existing = file_path.read_text(encoding="utf-8") if file_path.exists() else ""
122
+ if existing != normalized:
123
+ write_utf8_no_bom(file_path, normalized)
124
+ print(f"[OK] Updated file: {file_path}")
125
+ else:
126
+ print(f"[OK] File already up to date: {file_path}")
127
+
128
+
129
+ def upsert_or_migrate_canonical(
130
+ file_path: Path,
131
+ start_marker: str,
132
+ end_marker: str,
133
+ canonical_body: str,
134
+ ) -> None:
135
+ """Upsert the canonical block in file_path, preserving any surrounding content.
136
+
137
+ Migration: if the file exists without markers and its normalized content
138
+ equals the canonical body (written by a prior plain-file install), replace
139
+ it with the marked version to avoid duplicate content on the first upgrade.
140
+ """
141
+ existing = file_path.read_text(encoding="utf-8") if file_path.exists() else ""
142
+ block = f"{start_marker}\n{canonical_body.rstrip()}\n{end_marker}"
143
+ pattern = re.compile(rf"{re.escape(start_marker)}.*?{re.escape(end_marker)}", re.DOTALL)
144
+
145
+ if pattern.search(existing):
146
+ updated = pattern.sub(lambda _match: block, existing)
147
+ elif not existing.strip():
148
+ updated = f"{block}\n"
149
+ elif existing.rstrip("\r\n") == canonical_body.rstrip("\r\n"):
150
+ # Plain-installed canonical content — wrap in markers without duplication.
151
+ updated = f"{block}\n"
152
+ else:
153
+ updated = f"{existing.rstrip()}\n\n{block}\n"
154
+
155
+ if updated != existing:
156
+ write_utf8_no_bom(file_path, updated)
157
+ print(f"[OK] Updated file: {file_path}")
158
+ else:
159
+ print(f"[OK] File already up to date: {file_path}")
160
+
161
+
162
+ def memory_router_body() -> str:
163
+ return """## Memory Router
164
+
165
+ This file is the durable memory router for the repository.
166
+ It is not a knowledge dump. Store durable memory in sharded docs under `domains/`, `patterns/`, `incidents/`, `episodes/`, `training/`, `skills/`, or `archive/`.
167
+
168
+ Control-plane docs are not memory docs:
169
+ - `/.recursive/RECURSIVE.md`
170
+ - `/.recursive/STATE.md`
171
+ - `/.recursive/DECISIONS.md`
172
+ - `/.codex/AGENTS.md`
173
+ - `/AGENTS.md`
174
+ - `/.agent/PLANS.md`
175
+
176
+ ## Retrieval Rules
177
+
178
+ - Read this file before loading any other memory docs.
179
+ - Load only the memory docs relevant to the current task.
180
+ - If the task may benefit from prior recursive-mode experiential learnings, use this index to identify the relevant docs under `/.recursive/memory/training/` and `/.recursive/memory/domains/`.
181
+ - The optional `recursive-training-sync.py` helper is read-only; it prints startup guidance about what to read, but does not modify `MEMORY.md` or the memory plane.
182
+ - If the task plans delegated review, subagent help, review bundles, smoke-harness portability work, or capability-sensitive execution, read `/.recursive/memory/skills/SKILLS.md` and then load the relevant skill-memory shards.
183
+ - If Phase 8 will need to promote durable lessons, first capture run-local skill usage in the run artifact and only then promote generalized conclusions into skill-memory shards.
184
+ - Prefer `Status: CURRENT` docs for planning and execution.
185
+ - `Status: SUSPECT` docs may be used as leads, but revalidate them before trust.
186
+ - Exclude `STALE` and `DEPRECATED` docs from default retrieval unless doing historical analysis.
187
+
188
+ ## Registry
189
+
190
+ - `domains/` - stable functional-area knowledge with `Owns-Paths`
191
+ - `patterns/` - reusable playbooks and solution patterns
192
+ - `incidents/` - recurring failure signatures and fixes
193
+ - `episodes/` - distilled lessons from specific runs
194
+ - `training/` - extracted experiential learnings promoted from completed recursive-mode runs
195
+ - `skills/` - durable skill and capability memory, routed via `skills/SKILLS.md`
196
+ - `archive/` - historical or deprecated memory docs
197
+
198
+ ## Freshness Rules
199
+
200
+ - Durable memory docs must declare the metadata defined by the installed `recursive-mode` artifact template.
201
+ - Any doc whose `Owns-Paths` or `Watch-Paths` overlaps final changed code paths must be reviewed in Phase 8.
202
+ - Affected `CURRENT` docs should be downgraded to `SUSPECT` until revalidated against final code, `STATE.md`, and `DECISIONS.md`.
203
+ - If changed paths have no owning domain doc, create one or record the uncovered-path follow-up in `08-memory-impact.md`.
204
+ - Training memory docs should keep their canonical content under `/.recursive/memory/training/`, use the memory index as the discovery surface, and record source runs plus watch-path or applicability guidance.
205
+ - Skill-memory docs should record source runs, last validated date, environment notes, and current trust/fit guidance.
206
+ - If a run materially teaches the repo something about skill availability, delegated-review quality, review-bundle usage, or toolchain fallback behavior, Phase 8 must either create/refresh a skill-memory shard or record why no durable lesson was promoted.
207
+ - If the repo itself is a reusable skill/workflow distribution, durable memory must remain generalized. Do not store current-session run residue or temp-environment observations as if they were universal truth.
208
+ """
209
+
210
+
211
+ def skill_memory_router_body() -> str:
212
+ return """## Skill Memory Router
213
+
214
+ This file routes durable skill and capability knowledge for the repository.
215
+ It summarizes what skills were available, what was attempted, what worked, what failed, and how future runs should use those skills.
216
+
217
+ Use the subfolders for durable Markdown-only skill memory:
218
+
219
+ - `availability/` - environment-specific skill availability and capability probe notes
220
+ - `usage/` - stable usage guidance and fit for specific skills
221
+ - `issues/` - recurring skill failures, limitations, or confusing behavior
222
+ - `patterns/` - reusable multi-skill operating patterns and delegation playbooks
223
+
224
+ Keep this file concise. Link to child docs instead of duplicating them.
225
+
226
+ ## Retrieval Hints
227
+
228
+ - If the run may use delegated review, subagents, or review bundles:
229
+ - read this router
230
+ - read only the most relevant skill-memory docs that are actually present for the current environment and workflow
231
+ - If the run may need specialized external capability:
232
+ - prefer the `find-skills` skill when available
233
+ - otherwise use the Skills CLI directly and treat discovered packages as candidates until quality is checked
234
+ - If the run changes the smoke harness or cross-toolchain behavior:
235
+ - read the most relevant availability/usage notes if any have been intentionally promoted into skill memory
236
+ - In Phase 8, promote durable skill lessons into one of these shards:
237
+ - `availability/` for capability probes and environment constraints
238
+ - `usage/` for stable fit/use guidance
239
+ - `issues/` for recurring failure modes
240
+ - `patterns/` for reusable operating playbooks
241
+ - Before promoting anything durable, capture run-local skill usage in the Phase 8 artifact:
242
+ - what skills were available
243
+ - what skills were sought
244
+ - what skills were attempted or used
245
+ - what worked well or poorly
246
+ - what future guidance should change
247
+
248
+ ## Current Docs
249
+
250
+ - `/.recursive/memory/skills/usage/skill-discovery-and-evaluation.md`
251
+ - `/.recursive/memory/skills/patterns/delegated-verification-and-refresh.md`
252
+ - `/.recursive/memory/skills/patterns/phase8-skill-memory-promotion.md`
253
+ - Add child docs here only when they are intentionally promoted as reusable repository guidance.
254
+ """
255
+
256
+
257
+ def cursorrules_memory_pointers_body() -> str:
258
+ return """# recursive-mode memory pointers
259
+ # Canonical repository memory lives under `/.recursive/memory/`.
260
+ # Read `/.recursive/memory/MEMORY.md` before loading any other memory docs.
261
+ # Load only the memory docs relevant to the current task.
262
+ # When repository experiential memory may help, run:
263
+ # python .recursive/scripts/recursive-training-loader.py --repo-root . --query "<task>" --files "<path1,path2>"
264
+ # This file is only a pointer surface; the canonical memory store remains `/.recursive/memory/`.
265
+ """
266
+
267
+
268
+ def claude_memory_pointers_body() -> str:
269
+ return """## recursive-mode memory pointers
270
+
271
+ - Canonical repository memory lives under `/.recursive/memory/`.
272
+ - Read `/.recursive/memory/MEMORY.md` before loading any other memory docs.
273
+ - Load only the memory docs relevant to the current task.
274
+ - When repository experiential memory may help, run `python .recursive/scripts/recursive-training-loader.py --repo-root . --query "<task>" --files "<path1,path2>"`.
275
+ - Treat this file as a pointer only; the canonical memory store remains `/.recursive/memory/`.
276
+ """
277
+
278
+
279
+ def copilot_memory_pointers_body() -> str:
280
+ return """## recursive-mode memory pointers
281
+
282
+ - Canonical repository memory lives under `/.recursive/memory/`.
283
+ - Read `/.recursive/memory/MEMORY.md` before loading any other memory docs.
284
+ - Load only the memory docs relevant to the current task.
285
+ - When repository experiential memory may help, run `python .recursive/scripts/recursive-training-loader.py --repo-root . --query "<task>" --files "<path1,path2>"`.
286
+ - Treat this file as a pointer only; the canonical memory store remains `/.recursive/memory/`.
287
+ """
288
+
289
+
290
+ def skill_discovery_memory_doc() -> str:
291
+ return """Type: `pattern`
292
+ Status: `CURRENT`
293
+ Scope: `How recursive-mode runs should discover, evaluate, and record external skills or missing capabilities.`
294
+ Owns-Paths:
295
+ Watch-Paths:
296
+ - `/.recursive/RECURSIVE.md`
297
+ - `/.recursive/memory/skills/SKILLS.md`
298
+ - `/.recursive/run/`
299
+ Source-Runs:
300
+ - `none (generic repository guidance)`
301
+ Validated-At-Commit: `generic-repository-guidance`
302
+ Last-Validated: `2026-04-09T00:00:00Z`
303
+ Tags:
304
+ - `skills`
305
+ - `discovery`
306
+ - `find-skills`
307
+ - `capability`
308
+
309
+ # Skill Discovery And Evaluation
310
+
311
+ Use this guidance when a run needs a specialized capability that is not already available.
312
+
313
+ ## Preferred Order
314
+
315
+ 1. Use the `find-skills` skill if it is already installed.
316
+ 2. Otherwise use the Skills CLI directly.
317
+ 3. If nothing suitable exists, proceed with built-in capability and record that no suitable external skill was available.
318
+
319
+ ## Useful Commands
320
+
321
+ - `npx skills find <query>`
322
+ - `npx skills add <package-or-repo>`
323
+ - `npx skills add <package-or-repo> --skill <skill-name>`
324
+ - `npx skills check`
325
+ - `npx skills update`
326
+
327
+ ## Evaluation Rules
328
+
329
+ - Prefer skills from reputable publishers or organizations.
330
+ - Prefer higher install counts when the skills are otherwise comparable.
331
+ - Check upstream repository quality before recommending or installing a skill.
332
+ - Do not treat search results as proof of quality; verify source and documentation first.
333
+
334
+ ## Phase 8 Recording
335
+
336
+ If a run materially used skill discovery, capture it in `08-memory-impact.md` under:
337
+
338
+ - `## Run-Local Skill Usage Capture`
339
+ - `## Skill Memory Promotion Review`
340
+
341
+ Promote only durable, reusable conclusions into skill memory. Leave one-off session notes in the run artifact instead of turning them into durable guidance.
342
+ """
343
+
344
+
345
+ def delegated_verification_memory_doc() -> str:
346
+ return """Type: `pattern`
347
+ Status: `CURRENT`
348
+ Scope: `How the main agent verifies delegated review or audit work before accepting it as lockable evidence.`
349
+ Owns-Paths:
350
+ Watch-Paths:
351
+ - `/.recursive/RECURSIVE.md`
352
+ - `/.recursive/memory/skills/SKILLS.md`
353
+ - `/.recursive/run/`
354
+ Source-Runs:
355
+ - `none (generic repository guidance)`
356
+ Validated-At-Commit: `generic-repository-guidance`
357
+ Last-Validated: `2026-04-09T00:00:00Z`
358
+ Tags:
359
+ - `skills`
360
+ - `subagent`
361
+ - `verification`
362
+ - `review-bundle`
363
+
364
+ # Delegated Verification And Refresh
365
+
366
+ Delegated work is optional helper output, not autonomous authority.
367
+
368
+ ## Main-Agent Acceptance Rules
369
+
370
+ Before accepting meaningful delegated work, the main agent should verify:
371
+
372
+ - claimed file impact against the actual diff-owned file set
373
+ - claimed artifact reads or updates against files that actually exist
374
+ - review-bundle contents against the current reviewed artifact and artifact hash
375
+ - requirement, plan, addenda, and prior recursive docs that materially informed acceptance
376
+ - whether any post-review repair made the delegated context stale
377
+
378
+ ## Record In The Phase Artifact
379
+
380
+ When delegated work materially contributes, `## Subagent Contribution Verification` should record:
381
+
382
+ - `Reviewed Action Records`
383
+ - `Main-Agent Verification Performed`
384
+ - `Acceptance Decision`
385
+ - `Refresh Handling`
386
+ - `Repair Performed After Verification`
387
+
388
+ ## Refresh Rule
389
+
390
+ If repairs materially change the reviewed artifact, changed-file scope, or evidence basis, refresh the review bundle or action record before relying on delegated work for lockable evidence.
391
+
392
+ ## Rejection Rule
393
+
394
+ If the main agent cannot verify delegated claims against actual files, actual artifacts, and the actual diff scope, reject the delegated result and fall back to self-audit for lockable completion evidence.
395
+ """
396
+
397
+
398
+ def phase8_skill_memory_doc() -> str:
399
+ return """Type: `pattern`
400
+ Status: `CURRENT`
401
+ Scope: `How Phase 8 captures run-local skill usage and promotes only durable lessons into skill memory.`
402
+ Owns-Paths:
403
+ Watch-Paths:
404
+ - `/.recursive/RECURSIVE.md`
405
+ - `/.recursive/memory/MEMORY.md`
406
+ - `/.recursive/memory/skills/SKILLS.md`
407
+ - `/.recursive/run/`
408
+ Source-Runs:
409
+ - `none (generic repository guidance)`
410
+ Validated-At-Commit: `generic-repository-guidance`
411
+ Last-Validated: `2026-04-09T00:00:00Z`
412
+ Tags:
413
+ - `skills`
414
+ - `memory`
415
+ - `phase8`
416
+ - `promotion`
417
+
418
+ # Phase 8 Skill Memory Promotion
419
+
420
+ Skill memory should be operational, not accidental.
421
+
422
+ ## First Capture It Run-Locally
423
+
424
+ Before promoting durable guidance, record run-local skill usage in `08-memory-impact.md`:
425
+
426
+ - what skills were available
427
+ - what skills were sought
428
+ - what skills were attempted or used
429
+ - what worked well
430
+ - what issues were encountered
431
+ - what future guidance changed
432
+ - what promotion candidates exist
433
+
434
+ ## Then Decide What Becomes Durable
435
+
436
+ Promote only lessons that are:
437
+
438
+ - reusable across runs
439
+ - specific enough to change future planning or verification behavior
440
+ - not merely one-off environmental noise
441
+
442
+ ## Keep The Boundary Honest
443
+
444
+ - Run-local observations belong in the run artifact first.
445
+ - Durable memory should contain generalized guidance, not session history.
446
+ - In reusable skill/workflow repos, do not turn current-session implementation residue into durable memory unless it has been rewritten as generic repository guidance.
447
+ """
448
+
449
+
450
+ def recursive_agents_router_body() -> str:
451
+ return """## .recursive AGENTS Router
452
+
453
+ This file is a lightweight routing/index doc for agents already working inside the repository.
454
+ It exists to reduce blind doc-by-doc scanning. It is not a second workflow spec.
455
+
456
+ ## Canonical Rule
457
+
458
+ - Treat `/.recursive/RECURSIVE.md` as the single workflow source of truth.
459
+ - If this file conflicts with `/.recursive/RECURSIVE.md`, follow `/.recursive/RECURSIVE.md`.
460
+
461
+ ## Suggested Read Order
462
+
463
+ 1. Read `/.recursive/RECURSIVE.md` first for workflow rules and required behavior.
464
+ 2. Read `/.recursive/STATE.md` when the current repo state matters.
465
+ 3. Read `/.recursive/DECISIONS.md` when prior rationale or relevant earlier work matters.
466
+ 4. Read `/.recursive/memory/MEMORY.md` when task context may depend on durable memory.
467
+ 5. Read `/.recursive/memory/skills/SKILLS.md` when the task may use delegated review, subagents, review bundles, smoke-harness portability work, or other capability-sensitive execution.
468
+ 6. Read the recursive-mode package README or maintainer notes from the installed skill directory or source package checkout when changing the package itself.
469
+
470
+ ## Task Routing
471
+
472
+ - Starting or resuming a recursive-mode run:
473
+ - `/.recursive/RECURSIVE.md`
474
+ - `/.recursive/STATE.md`
475
+ - `/.recursive/DECISIONS.md`
476
+ - `/.recursive/memory/MEMORY.md`
477
+ - Authoring a new recursive-mode spec or `00-requirements.md`:
478
+ - `/.recursive/STATE.md`
479
+ - `/.recursive/DECISIONS.md`
480
+ - `/.recursive/memory/MEMORY.md`
481
+ - the installed `recursive-spec` skill
482
+ - relevant code and tests for the requested area
483
+ - Benchmarking recursive-mode against a non-recursive baseline:
484
+ - Install the separate optional `recursive-benchmark` add-on only when the user explicitly asks for benchmarking.
485
+ - Prefer `find-skills` when available; otherwise use `npx skills add <recursive-benchmark-package-or-repo> --full-depth`.
486
+ - The default exported `recursive-mode` package intentionally excludes benchmark fixtures and benchmark skill files.
487
+ - After the benchmark add-on is installed, follow its packaged fixture and harness docs.
488
+ - Working on reusable package/bootstrap/docs for this repo:
489
+ - the recursive-mode package README or maintainer notes from the installed skill directory or source package checkout
490
+ - the recursive-mode installer scripts from the installed skill directory or source package checkout
491
+ - Working on phase artifact structure or lint expectations:
492
+ - the recursive-mode artifact template from the installed skill directory or source package checkout
493
+ - the recursive-mode lint/status helpers from the installed skill directory or source package checkout
494
+ - Working on delegated review, subagent behavior, or routed CLI delegation:
495
+ - `/.recursive/memory/skills/SKILLS.md`
496
+ - `/.recursive/config/recursive-router.json`
497
+ - `/.recursive/config/recursive-router-discovered.json`
498
+ - the installed `recursive-router`, `recursive-subagent`, and `recursive-review-bundle` skills
499
+ - Working on memory behavior:
500
+ - `/.recursive/memory/MEMORY.md`
501
+ - the installed `recursive-training` skill
502
+ - `/.recursive/scripts/recursive-training-loader.py`
503
+ - `/.recursive/memory/training/`
504
+ - `/.recursive/memory/skills/SKILLS.md`
505
+
506
+ ## Non-Canonical Bridges
507
+
508
+ These are adapters, not second specs:
509
+
510
+ - `/.codex/AGENTS.md`
511
+ - `/AGENTS.md`
512
+ - `/.agent/PLANS.md`
513
+
514
+ Read them only when the tool or host expects those entrypoints.
515
+ """
516
+
517
+
518
+ def plans_bridge_body() -> str:
519
+ return """## recursive-mode plans bridge
520
+
521
+ This file exists only for tools that expect the Codex plans bridge at `/.agent/PLANS.md`.
522
+
523
+ The canonical workflow specification lives in `/.recursive/RECURSIVE.md`.
524
+ Do not maintain a second authoritative workflow here.
525
+
526
+ If this bridge conflicts with `/.recursive/RECURSIVE.md`, follow `/.recursive/RECURSIVE.md`.
527
+
528
+ Short user commands that should trigger recursive-mode orchestration include:
529
+
530
+ - `Implement the run`
531
+ - `Implement run <run-id>`
532
+ - `Implement requirement '<run-id>'`
533
+ - `Implement the plan`
534
+ - `Create a new run based on the plan`
535
+ - `Start a recursive run`
536
+
537
+ Resolution rule:
538
+
539
+ - If a run id is explicit, use that run.
540
+ - If exactly one active/incomplete run exists and no run id is given, resume it.
541
+ - If the user refers to a plan, create a new run only when a unique source plan/requirements artifact can be identified from repo docs or immediate task context.
542
+ - If the command is ambiguous, ask for the run id or the repo path of the source plan/requirements artifact.
543
+
544
+ Spec-authoring rule:
545
+
546
+ - If the user asks to create a plan, help plan, create a spec, or write requirements for a new recursive run, prefer `recursive-spec` before orchestration.
547
+ - `recursive-spec` should confirm the user wants spec help, ask what they want to do, read `STATE.md`, `DECISIONS.md`, `MEMORY.md`, and relevant code/tests, keep the draft in temporary non-repo storage, then create the new run only after the requirements are approved.
548
+
549
+ Benchmark rule:
550
+
551
+ - If the user asks to benchmark recursive-mode, compare recursive vs non-recursive execution, or generate a recursive-mode benchmark report, install and use the separate optional `recursive-benchmark` add-on on demand instead of assuming benchmark fixtures ship with the default recursive-mode package.
552
+ - Prefer `find-skills` when available. Otherwise use `npx skills add <recursive-benchmark-package-or-repo> --full-depth`.
553
+
554
+ Audit delegation rule:
555
+
556
+ - If subagents are available and the audit/review context bundle is complete, delegated audit/review is the default path.
557
+ - If the controller still chooses `self-audit`, record a concrete `Delegation Override Reason` in the audited phase artifact.
558
+
559
+ Router rule:
560
+
561
+ - If the user asks to route delegated work through another transport/model, configure or inspect `/.recursive/config/recursive-router.json`, refresh `/.recursive/config/recursive-router-discovered.json`, re-read both immediately before choosing the delegated CLI/model, and use `recursive-router` before dispatching the delegated role.
562
+ """
563
+
564
+
565
+ def main() -> None:
566
+ parser = argparse.ArgumentParser(description="Install/bootstrap recursive-mode scaffolding.")
567
+ parser.add_argument("--repo-root", default=".", help="Repository root path (default: current directory).")
568
+ parser.add_argument(
569
+ "--skip-recursive-update",
570
+ action="store_true",
571
+ help="Skip canonical RECURSIVE.md upsert.",
572
+ )
573
+ args = parser.parse_args()
574
+
575
+ repo_root = Path(args.repo_root).resolve()
576
+ print(f"[INFO] Repo root: {repo_root}")
577
+
578
+ skill_root = Path(__file__).resolve().parent.parent
579
+ canonical_workflow_path = resolve_canonical_workflow_path(skill_root)
580
+ agents_block_path = skill_root / "references" / "agents-block.md"
581
+
582
+ recursive_root = repo_root / ".recursive"
583
+ codex_root = repo_root / ".codex"
584
+ memory_root = recursive_root / "memory"
585
+ run_root = recursive_root / "run"
586
+ config_root = recursive_root / "config"
587
+ agent_root = repo_root / ".agent"
588
+
589
+ recursive_path = recursive_root / "RECURSIVE.md"
590
+ recursive_agents_path = recursive_root / "AGENTS.md"
591
+ state_path = recursive_root / "STATE.md"
592
+ decisions_path = recursive_root / "DECISIONS.md"
593
+ memory_router_path = memory_root / "MEMORY.md"
594
+ training_memory_root = memory_root / "training"
595
+ skill_memory_root = memory_root / "skills"
596
+ skill_memory_router_path = skill_memory_root / "SKILLS.md"
597
+ skill_discovery_path = skill_memory_root / "usage" / "skill-discovery-and-evaluation.md"
598
+ delegated_verification_path = skill_memory_root / "patterns" / "delegated-verification-and-refresh.md"
599
+ phase8_skill_memory_path = skill_memory_root / "patterns" / "phase8-skill-memory-promotion.md"
600
+ cursorrules_path = repo_root / ".cursorrules"
601
+ claude_path = repo_root / "CLAUDE.md"
602
+ github_root = repo_root / ".github"
603
+ copilot_instructions_path = github_root / "copilot-instructions.md"
604
+ codex_agents_path = codex_root / "AGENTS.md"
605
+ root_agents_path = repo_root / "AGENTS.md"
606
+ plans_path = agent_root / "PLANS.md"
607
+
608
+ recursive_start_marker = "<!-- RECURSIVE-MODE-CANONICAL:START -->"
609
+ recursive_end_marker = "<!-- RECURSIVE-MODE-CANONICAL:END -->"
610
+ memory_start_marker = "<!-- RECURSIVE-MODE-MEMORY:START -->"
611
+ memory_end_marker = "<!-- RECURSIVE-MODE-MEMORY:END -->"
612
+ agents_start_marker = "<!-- RECURSIVE-MODE-AGENTS:START -->"
613
+ agents_end_marker = "<!-- RECURSIVE-MODE-AGENTS:END -->"
614
+ plans_start_marker = "<!-- RECURSIVE-MODE-PLANS-BRIDGE:START -->"
615
+ plans_end_marker = "<!-- RECURSIVE-MODE-PLANS-BRIDGE:END -->"
616
+ cursorrules_start_marker = "# RECURSIVE-MODE-MEMORY-POINTERS:START"
617
+ cursorrules_end_marker = "# RECURSIVE-MODE-MEMORY-POINTERS:END"
618
+ repo_md_start_marker = "<!-- RECURSIVE-MODE-MEMORY-POINTERS:START -->"
619
+ repo_md_end_marker = "<!-- RECURSIVE-MODE-MEMORY-POINTERS:END -->"
620
+
621
+ ensure_directory(recursive_root)
622
+ ensure_directory(codex_root)
623
+ ensure_directory(agent_root)
624
+ ensure_directory(github_root)
625
+ ensure_directory(memory_root)
626
+ ensure_directory(training_memory_root)
627
+ ensure_directory(skill_memory_root)
628
+ ensure_directory(run_root)
629
+ ensure_directory(config_root)
630
+ for subdir in ("domains", "patterns", "incidents", "episodes", "archive"):
631
+ ensure_directory(memory_root / subdir)
632
+ ensure_file(memory_root / subdir / ".gitkeep", "")
633
+ ensure_file(training_memory_root / ".gitkeep", "")
634
+ for subdir in ("availability", "usage", "issues", "patterns"):
635
+ ensure_directory(skill_memory_root / subdir)
636
+ ensure_file(skill_memory_root / subdir / ".gitkeep", "")
637
+
638
+ # Copy packaged runtime scripts into .recursive/scripts/ so every installed
639
+ # subskill can use the same repo-local tools after bootstrap.
640
+ scripts_dest = recursive_root / "scripts"
641
+ ensure_directory(scripts_dest)
642
+ skill_scripts_dir = skill_root / "scripts"
643
+ runtime_scripts = sorted(
644
+ path.name
645
+ for path in skill_scripts_dir.iterdir()
646
+ if path.is_file()
647
+ and path.suffix in {".py", ".ps1"}
648
+ and (
649
+ path.name.startswith("recursive-")
650
+ or path.name.startswith("lint-")
651
+ or path.name.startswith("verify-")
652
+ or path.name in {"recursive_phase_rules.py", "recursive_router_cli_lib.py", "recursive_router_lib.py"}
653
+ )
654
+ )
655
+ for script_name in runtime_scripts:
656
+ src = skill_scripts_dir / script_name
657
+ dst = scripts_dest / script_name
658
+ content = src.read_text(encoding="utf-8")
659
+ if not dst.exists() or dst.read_text(encoding="utf-8") != content:
660
+ dst.write_text(content, encoding="utf-8")
661
+ print(f"[OK] Copied runtime script: {dst}")
662
+ else:
663
+ print(f"[OK] Up to date: {dst}")
664
+
665
+ ensure_file(run_root / ".gitkeep", "")
666
+ ensure_file(recursive_path, "# RECURSIVE.md\n")
667
+ ensure_file(recursive_agents_path, "# AGENTS.md\n")
668
+ ensure_file(state_path, "# STATE.md\n\n## Current State\n\n- Initial state not documented yet.\n")
669
+ ensure_file(decisions_path, "# DECISIONS.md\n\n## Recursive Run Index\n\n- No runs recorded yet.\n")
670
+ ensure_file(memory_router_path, "# MEMORY.md\n")
671
+ ensure_file(skill_memory_router_path, "# SKILLS.md\n")
672
+ ensure_file(skill_discovery_path, skill_discovery_memory_doc())
673
+ ensure_file(delegated_verification_path, delegated_verification_memory_doc())
674
+ ensure_file(phase8_skill_memory_path, phase8_skill_memory_doc())
675
+ ensure_file(codex_agents_path, "# AGENTS.md\n")
676
+ ensure_file(plans_path, "# PLANS.md\n")
677
+ ensure_file(cursorrules_path, "")
678
+ ensure_file(claude_path, "")
679
+ ensure_file(copilot_instructions_path, "")
680
+ ensure_gitignore_line(repo_root, "/.recursive/config/recursive-router-discovered.json")
681
+ try:
682
+ ensure_router_scaffold(repo_root)
683
+ except RouterConfigError as exc:
684
+ raise SystemExit(f"[FAIL] {exc}") from exc
685
+
686
+ upsert_marked_block(
687
+ recursive_agents_path,
688
+ agents_start_marker,
689
+ agents_end_marker,
690
+ recursive_agents_router_body().rstrip("\r\n"),
691
+ )
692
+ upsert_marked_block(
693
+ memory_router_path,
694
+ memory_start_marker,
695
+ memory_end_marker,
696
+ memory_router_body().rstrip("\r\n"),
697
+ )
698
+ upsert_marked_block(
699
+ skill_memory_router_path,
700
+ memory_start_marker,
701
+ memory_end_marker,
702
+ skill_memory_router_body().rstrip("\r\n"),
703
+ )
704
+ upsert_marked_block(
705
+ cursorrules_path,
706
+ cursorrules_start_marker,
707
+ cursorrules_end_marker,
708
+ cursorrules_memory_pointers_body().rstrip("\r\n"),
709
+ )
710
+ upsert_marked_block(
711
+ claude_path,
712
+ repo_md_start_marker,
713
+ repo_md_end_marker,
714
+ claude_memory_pointers_body().rstrip("\r\n"),
715
+ )
716
+ upsert_marked_block(
717
+ copilot_instructions_path,
718
+ repo_md_start_marker,
719
+ repo_md_end_marker,
720
+ copilot_memory_pointers_body().rstrip("\r\n"),
721
+ )
722
+
723
+ if not agents_block_path.exists():
724
+ raise FileNotFoundError(f"Missing AGENTS bridge template: {agents_block_path}")
725
+ agents_block = agents_block_path.read_text(encoding="utf-8").rstrip("\r\n")
726
+ upsert_marked_block(codex_agents_path, agents_start_marker, agents_end_marker, agents_block)
727
+ if root_agents_path.exists():
728
+ upsert_marked_block(root_agents_path, agents_start_marker, agents_end_marker, agents_block)
729
+ upsert_marked_block(plans_path, plans_start_marker, plans_end_marker, plans_bridge_body().rstrip("\r\n"))
730
+
731
+ if not args.skip_recursive_update:
732
+ canonical_body = normalize_plain_or_wrapped_content(
733
+ canonical_workflow_path.read_text(encoding="utf-8"),
734
+ recursive_start_marker,
735
+ recursive_end_marker,
736
+ )
737
+ upsert_or_migrate_canonical(
738
+ recursive_path,
739
+ recursive_start_marker,
740
+ recursive_end_marker,
741
+ canonical_body,
742
+ )
743
+ else:
744
+ print("[INFO] Skipped RECURSIVE.md update by configuration.")
745
+
746
+ print("[OK] recursive-mode installation bootstrap complete.")
747
+
748
+
749
+ if __name__ == "__main__":
750
+ main()