@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.
- package/cordis.patch.yml +12 -0
- package/lib/bootstrap.d.ts +35 -0
- package/lib/client/board.d.ts +10 -0
- package/lib/client/contract.d.ts +51 -0
- package/lib/client/derive.d.ts +92 -0
- package/lib/client/index.d.ts +21 -0
- package/lib/client/inspector.d.ts +10 -0
- package/lib/client/node.d.ts +71 -0
- package/lib/client/settings.d.ts +6 -0
- package/lib/client/slots.d.ts +7 -0
- package/lib/client/strip.d.ts +7 -0
- package/lib/client.d.ts +10 -0
- package/lib/client.js +490 -0
- package/lib/closeout.d.ts +23 -0
- package/lib/commands.d.ts +51 -0
- package/lib/delegation.d.ts +92 -0
- package/lib/enforcement.d.ts +53 -0
- package/lib/events.d.ts +173 -0
- package/lib/handoff.d.ts +51 -0
- package/lib/index.d.ts +40 -0
- package/lib/lifecycle.d.ts +107 -0
- package/lib/lock.d.ts +92 -0
- package/lib/policy.d.ts +12 -0
- package/lib/projection.d.ts +29 -0
- package/lib/recursive_closeout.tool.d.ts +8 -0
- package/lib/recursive_init.tool.d.ts +2 -0
- package/lib/recursive_lint.tool.d.ts +2 -0
- package/lib/recursive_lock.tool.d.ts +2 -0
- package/lib/recursive_scratch.tool.d.ts +7 -0
- package/lib/recursive_status.tool.d.ts +2 -0
- package/lib/review.d.ts +39 -0
- package/lib/router.d.ts +77 -0
- package/lib/run.d.ts +29 -0
- package/lib/runtime.d.ts +241 -0
- package/lib/scratch.d.ts +18 -0
- package/lib/status.d.ts +19 -0
- package/lib/types.d.ts +104 -0
- package/lib/workspace.d.ts +50 -0
- package/package.json +119 -0
- package/preset/recursive/agent.cordis.yml +282 -0
- package/preset/recursive/preset.yml +3 -0
- package/scripts/install-recursive-mode.ps1 +956 -0
- package/scripts/install-recursive-mode.py +750 -0
- package/scripts/lint-recursive-run.py +2868 -0
- package/scripts/recursive-closeout.py +541 -0
- package/scripts/recursive-init.py +356 -0
- package/scripts/recursive-lock.py +302 -0
- package/scripts/recursive-status.py +2124 -0
- package/scripts/recursive_phase_rules.py +367 -0
- package/scripts/recursive_router_lib.py +2282 -0
- package/scripts/test-recursive-mode-smoke.ts +204 -0
- package/scripts/verify-locks.py +353 -0
- package/src/bootstrap.ts +118 -0
- package/src/client/board.tsx +61 -0
- package/src/client/contract.ts +58 -0
- package/src/client/derive.ts +241 -0
- package/src/client/index.ts +28 -0
- package/src/client/inspector.tsx +49 -0
- package/src/client/node.ts +156 -0
- package/src/client/settings.tsx +18 -0
- package/src/client/slots.ts +67 -0
- package/src/client/strip.tsx +28 -0
- package/src/client.ts +11 -0
- package/src/closeout.ts +183 -0
- package/src/commands.ts +142 -0
- package/src/delegation.ts +306 -0
- package/src/enforcement.ts +180 -0
- package/src/events.ts +173 -0
- package/src/handoff.ts +165 -0
- package/src/index.ts +283 -0
- package/src/lifecycle.ts +235 -0
- package/src/lock.ts +369 -0
- package/src/policy.ts +56 -0
- package/src/projection.ts +237 -0
- package/src/recursive_closeout.tool.ts +35 -0
- package/src/recursive_init.tool.ts +28 -0
- package/src/recursive_lint.tool.ts +29 -0
- package/src/recursive_lock.tool.ts +33 -0
- package/src/recursive_scratch.tool.ts +42 -0
- package/src/recursive_status.tool.ts +24 -0
- package/src/review.ts +178 -0
- package/src/router.ts +197 -0
- package/src/run.ts +85 -0
- package/src/runtime.ts +564 -0
- package/src/scratch.ts +85 -0
- package/src/status.ts +194 -0
- package/src/types.ts +112 -0
- 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()
|