multi-forge 0.2.0__py3-none-any.whl

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 (311) hide show
  1. forge/__init__.py +3 -0
  2. forge/_extensions/agents/.gitkeep +0 -0
  3. forge/_extensions/commands/.gitkeep +0 -0
  4. forge/_extensions/skills/analyze/SKILL.md +87 -0
  5. forge/_extensions/skills/challenge/SKILL.md +91 -0
  6. forge/_extensions/skills/consensus/SKILL.md +120 -0
  7. forge/_extensions/skills/consensus/resources/code_consensus_evaluation.md +94 -0
  8. forge/_extensions/skills/consensus/resources/consensus_evaluation.md +70 -0
  9. forge/_extensions/skills/consensus/resources/synthesis.md +101 -0
  10. forge/_extensions/skills/debate/SKILL.md +116 -0
  11. forge/_extensions/skills/debate/resources/code_debate_evaluation.md +101 -0
  12. forge/_extensions/skills/debate/resources/debate_evaluation.md +90 -0
  13. forge/_extensions/skills/panel/SKILL.md +141 -0
  14. forge/_extensions/skills/panel/resources/synthesis.md +103 -0
  15. forge/_extensions/skills/qa/SKILL.md +704 -0
  16. forge/_extensions/skills/qa/resources/checklist/0-enable.md +78 -0
  17. forge/_extensions/skills/qa/resources/checklist/1-preflight.md +24 -0
  18. forge/_extensions/skills/qa/resources/checklist/10-resume.md +143 -0
  19. forge/_extensions/skills/qa/resources/checklist/11-config.md +150 -0
  20. forge/_extensions/skills/qa/resources/checklist/12-search.md +58 -0
  21. forge/_extensions/skills/qa/resources/checklist/13-guard.md +237 -0
  22. forge/_extensions/skills/qa/resources/checklist/14-workflow.md +305 -0
  23. forge/_extensions/skills/qa/resources/checklist/15-skills.md +155 -0
  24. forge/_extensions/skills/qa/resources/checklist/16-handoff.md +224 -0
  25. forge/_extensions/skills/qa/resources/checklist/17-info.md +50 -0
  26. forge/_extensions/skills/qa/resources/checklist/18-disable.md +84 -0
  27. forge/_extensions/skills/qa/resources/checklist/19-uninstall.md +146 -0
  28. forge/_extensions/skills/qa/resources/checklist/2-extensions.md +188 -0
  29. forge/_extensions/skills/qa/resources/checklist/20-cleanup.md +36 -0
  30. forge/_extensions/skills/qa/resources/checklist/3-auth.md +234 -0
  31. forge/_extensions/skills/qa/resources/checklist/4-proxy.md +481 -0
  32. forge/_extensions/skills/qa/resources/checklist/5-session.md +541 -0
  33. forge/_extensions/skills/qa/resources/checklist/6-hooks.md +275 -0
  34. forge/_extensions/skills/qa/resources/checklist/7-costs.md +309 -0
  35. forge/_extensions/skills/qa/resources/checklist/8-status-line.md +174 -0
  36. forge/_extensions/skills/qa/resources/checklist/9-direct-commands.md +146 -0
  37. forge/_extensions/skills/qa/resources/checklist.md +103 -0
  38. forge/_extensions/skills/qa/resources/report-template.md +62 -0
  39. forge/_extensions/skills/qa/scripts/start-container.sh +529 -0
  40. forge/_extensions/skills/qa/scripts/walkthrough-state.py +1137 -0
  41. forge/_extensions/skills/review/SKILL.md +125 -0
  42. forge/_extensions/skills/review/references/claude-4.6.md +474 -0
  43. forge/_extensions/skills/review/references/claude-4.7.md +710 -0
  44. forge/_extensions/skills/review/references/gemini-3.1.md +546 -0
  45. forge/_extensions/skills/review/references/gpt-5.5.md +490 -0
  46. forge/_extensions/skills/review/references/skills-writing-guide.md +1588 -0
  47. forge/_extensions/skills/review/resources/code-anthropic.md +160 -0
  48. forge/_extensions/skills/review/resources/code-gemini.md +184 -0
  49. forge/_extensions/skills/review/resources/code-openai.md +203 -0
  50. forge/_extensions/skills/review/resources/code.md +160 -0
  51. forge/_extensions/skills/review-docs/SKILL.md +121 -0
  52. forge/_extensions/skills/review-docs/resources/docs-anthropic.md +170 -0
  53. forge/_extensions/skills/review-docs/resources/docs-gemini.md +204 -0
  54. forge/_extensions/skills/review-docs/resources/docs-openai.md +231 -0
  55. forge/_extensions/skills/review-docs/resources/docs.md +170 -0
  56. forge/_extensions/skills/smoke-test/SKILL.md +27 -0
  57. forge/_extensions/skills/smoke-test/scripts/smoke-test.sh +118 -0
  58. forge/_extensions/skills/understand/SKILL.md +148 -0
  59. forge/_extensions/skills/understand/resources/code-anthropic.md +163 -0
  60. forge/_extensions/skills/understand/resources/code-gemini.md +194 -0
  61. forge/_extensions/skills/understand/resources/code-openai.md +181 -0
  62. forge/_extensions/skills/understand/resources/code.md +163 -0
  63. forge/_extensions/skills/understand/resources/docs-anthropic.md +177 -0
  64. forge/_extensions/skills/understand/resources/docs-gemini.md +202 -0
  65. forge/_extensions/skills/understand/resources/docs-openai.md +191 -0
  66. forge/_extensions/skills/understand/resources/docs.md +177 -0
  67. forge/_extensions/skills/walkthrough/SKILL.md +599 -0
  68. forge/_extensions/skills/walkthrough/resources/checklist.md +765 -0
  69. forge/_extensions/skills/walkthrough/scripts/run-in-repo.sh +118 -0
  70. forge/_extensions/skills/walkthrough/scripts/setup-test-repo.sh +198 -0
  71. forge/_extensions/skills/walkthrough/scripts/walkthrough-state.py +1137 -0
  72. forge/backend/__init__.py +174 -0
  73. forge/backend/adapters/__init__.py +38 -0
  74. forge/backend/adapters/litellm.py +158 -0
  75. forge/backend/creation.py +89 -0
  76. forge/backend/registry.py +178 -0
  77. forge/cli/__init__.py +16 -0
  78. forge/cli/auth.py +483 -0
  79. forge/cli/backend.py +298 -0
  80. forge/cli/claude.py +411 -0
  81. forge/cli/config_cmd.py +303 -0
  82. forge/cli/extensions.py +1001 -0
  83. forge/cli/gc.py +165 -0
  84. forge/cli/guard.py +1018 -0
  85. forge/cli/guards.py +106 -0
  86. forge/cli/handoff.py +110 -0
  87. forge/cli/hooks/__init__.py +36 -0
  88. forge/cli/hooks/_group.py +20 -0
  89. forge/cli/hooks/_helpers.py +149 -0
  90. forge/cli/hooks/commands.py +1677 -0
  91. forge/cli/hooks/direct_commands.py +1304 -0
  92. forge/cli/hooks/install.py +232 -0
  93. forge/cli/hooks/policy.py +151 -0
  94. forge/cli/hooks/read_hygiene.py +74 -0
  95. forge/cli/hooks/verification.py +370 -0
  96. forge/cli/logs.py +406 -0
  97. forge/cli/main.py +292 -0
  98. forge/cli/proxy.py +1821 -0
  99. forge/cli/proxy_costs.py +313 -0
  100. forge/cli/search.py +416 -0
  101. forge/cli/session.py +892 -0
  102. forge/cli/session_addendum.py +81 -0
  103. forge/cli/session_fork.py +750 -0
  104. forge/cli/session_handoff.py +141 -0
  105. forge/cli/session_lifecycle.py +2053 -0
  106. forge/cli/session_manage.py +1336 -0
  107. forge/cli/session_memory.py +201 -0
  108. forge/cli/status_line.py +1398 -0
  109. forge/cli/workflow.py +1964 -0
  110. forge/config/__init__.py +110 -0
  111. forge/config/dataclass_utils.py +88 -0
  112. forge/config/defaults/__init__.py +0 -0
  113. forge/config/defaults/backends/__init__.py +0 -0
  114. forge/config/defaults/backends/litellm.yaml +196 -0
  115. forge/config/defaults/templates/__init__.py +0 -0
  116. forge/config/defaults/templates/litellm-anthropic-local.yaml +33 -0
  117. forge/config/defaults/templates/litellm-anthropic.yaml +24 -0
  118. forge/config/defaults/templates/litellm-gemini-flash-local.yaml +37 -0
  119. forge/config/defaults/templates/litellm-gemini-local.yaml +32 -0
  120. forge/config/defaults/templates/litellm-gemini-test.yaml +34 -0
  121. forge/config/defaults/templates/litellm-gemini.yaml +21 -0
  122. forge/config/defaults/templates/litellm-openai-codex-local.yaml +36 -0
  123. forge/config/defaults/templates/litellm-openai-local.yaml +38 -0
  124. forge/config/defaults/templates/litellm-openai.yaml +28 -0
  125. forge/config/defaults/templates/openrouter-anthropic.yaml +23 -0
  126. forge/config/defaults/templates/openrouter-deepseek.yaml +26 -0
  127. forge/config/defaults/templates/openrouter-gemini-flash.yaml +26 -0
  128. forge/config/defaults/templates/openrouter-gemini.yaml +23 -0
  129. forge/config/defaults/templates/openrouter-glm.yaml +23 -0
  130. forge/config/defaults/templates/openrouter-kimi.yaml +30 -0
  131. forge/config/defaults/templates/openrouter-minimax.yaml +26 -0
  132. forge/config/defaults/templates/openrouter-openai-codex.yaml +23 -0
  133. forge/config/defaults/templates/openrouter-openai.yaml +28 -0
  134. forge/config/defaults/templates/openrouter-qwen.yaml +25 -0
  135. forge/config/loader.py +675 -0
  136. forge/config/schema.py +448 -0
  137. forge/core/__init__.py +5 -0
  138. forge/core/auth/__init__.py +67 -0
  139. forge/core/auth/capabilities.py +219 -0
  140. forge/core/auth/credentials_file.py +244 -0
  141. forge/core/auth/protocols.py +18 -0
  142. forge/core/auth/secrets.py +243 -0
  143. forge/core/auth/template_secrets.py +112 -0
  144. forge/core/data/__init__.py +5 -0
  145. forge/core/data/model_catalog.yaml +1522 -0
  146. forge/core/data/pricing.yaml +140 -0
  147. forge/core/data/system_prompt_addendums/__init__.py +0 -0
  148. forge/core/data/system_prompt_addendums/gemini.md +330 -0
  149. forge/core/data/system_prompt_addendums/openai.md +328 -0
  150. forge/core/llm/__init__.py +231 -0
  151. forge/core/llm/clients/__init__.py +14 -0
  152. forge/core/llm/clients/base.py +115 -0
  153. forge/core/llm/clients/litellm.py +619 -0
  154. forge/core/llm/clients/openai_compat.py +244 -0
  155. forge/core/llm/clients/openrouter.py +234 -0
  156. forge/core/llm/credentials.py +439 -0
  157. forge/core/llm/detection.py +86 -0
  158. forge/core/llm/errors.py +44 -0
  159. forge/core/llm/protocols.py +80 -0
  160. forge/core/llm/types.py +176 -0
  161. forge/core/logging.py +146 -0
  162. forge/core/models/__init__.py +91 -0
  163. forge/core/models/catalog.py +467 -0
  164. forge/core/models/pricing.py +165 -0
  165. forge/core/models/types.py +167 -0
  166. forge/core/naming.py +212 -0
  167. forge/core/ops/__init__.py +73 -0
  168. forge/core/ops/context.py +141 -0
  169. forge/core/ops/gc.py +802 -0
  170. forge/core/ops/proxy.py +146 -0
  171. forge/core/ops/resolution.py +135 -0
  172. forge/core/ops/session.py +344 -0
  173. forge/core/ops/session_context.py +548 -0
  174. forge/core/paths.py +38 -0
  175. forge/core/process.py +54 -0
  176. forge/core/reactive/__init__.py +38 -0
  177. forge/core/reactive/cost_tracking.py +300 -0
  178. forge/core/reactive/env.py +180 -0
  179. forge/core/reactive/proxy.py +78 -0
  180. forge/core/reactive/routing.py +622 -0
  181. forge/core/reactive/session_runner.py +185 -0
  182. forge/core/reactive/structured_output.py +62 -0
  183. forge/core/reactive/tagger.py +94 -0
  184. forge/core/reactive/throttle.py +132 -0
  185. forge/core/state/__init__.py +59 -0
  186. forge/core/state/exceptions.py +59 -0
  187. forge/core/state/io.py +140 -0
  188. forge/core/state/lock.py +99 -0
  189. forge/core/state/timestamps.py +60 -0
  190. forge/core/transcript.py +78 -0
  191. forge/core/typing_helpers.py +24 -0
  192. forge/core/workqueue/__init__.py +67 -0
  193. forge/core/workqueue/queue.py +552 -0
  194. forge/core/workqueue/types.py +63 -0
  195. forge/guard/__init__.py +26 -0
  196. forge/guard/deterministic/__init__.py +26 -0
  197. forge/guard/deterministic/base.py +158 -0
  198. forge/guard/deterministic/coding_standards.py +256 -0
  199. forge/guard/deterministic/registry.py +148 -0
  200. forge/guard/deterministic/tdd.py +171 -0
  201. forge/guard/engine.py +216 -0
  202. forge/guard/protocols.py +91 -0
  203. forge/guard/queries.py +96 -0
  204. forge/guard/semantic/__init__.py +34 -0
  205. forge/guard/semantic/promotion.py +18 -0
  206. forge/guard/semantic/supervisor.py +813 -0
  207. forge/guard/semantic/verdict.py +183 -0
  208. forge/guard/store.py +124 -0
  209. forge/guard/team/__init__.py +6 -0
  210. forge/guard/team/config.py +24 -0
  211. forge/guard/team/handlers.py +209 -0
  212. forge/guard/team/prompts.py +41 -0
  213. forge/guard/types.py +125 -0
  214. forge/guard/workflow/__init__.py +17 -0
  215. forge/guard/workflow/branches.py +67 -0
  216. forge/guard/workflow/config.py +63 -0
  217. forge/guard/workflow/divergence.py +113 -0
  218. forge/guard/workflow/policy.py +87 -0
  219. forge/guard/workflow/stages.py +205 -0
  220. forge/install/__init__.py +55 -0
  221. forge/install/cli.py +281 -0
  222. forge/install/exceptions.py +163 -0
  223. forge/install/hooks.py +109 -0
  224. forge/install/installer.py +1037 -0
  225. forge/install/models.py +321 -0
  226. forge/install/preset.py +272 -0
  227. forge/install/settings_merge.py +831 -0
  228. forge/install/tracking.py +238 -0
  229. forge/install/version.py +141 -0
  230. forge/proxy/__init__.py +0 -0
  231. forge/proxy/base_client.py +181 -0
  232. forge/proxy/client_adapter.py +476 -0
  233. forge/proxy/client_factory.py +531 -0
  234. forge/proxy/converters.py +1206 -0
  235. forge/proxy/cost_logger.py +132 -0
  236. forge/proxy/cost_tracker.py +242 -0
  237. forge/proxy/data_models.py +338 -0
  238. forge/proxy/error_hints.py +92 -0
  239. forge/proxy/metrics.py +222 -0
  240. forge/proxy/model_spec.py +158 -0
  241. forge/proxy/proxies.py +333 -0
  242. forge/proxy/proxy_identity.py +134 -0
  243. forge/proxy/proxy_orchestrator.py +1018 -0
  244. forge/proxy/proxy_startup.py +54 -0
  245. forge/proxy/server.py +1561 -0
  246. forge/proxy/utils.py +537 -0
  247. forge/review/__init__.py +6 -0
  248. forge/review/adversarial.py +111 -0
  249. forge/review/consensus.py +236 -0
  250. forge/review/engine.py +356 -0
  251. forge/review/models.py +437 -0
  252. forge/review/resources/__init__.py +5 -0
  253. forge/review/resources/codereview-performance.md +85 -0
  254. forge/review/resources/codereview-quick.md +75 -0
  255. forge/review/resources/codereview-security.md +92 -0
  256. forge/review/resources/codereview.md +85 -0
  257. forge/review/resources/docreview-quick.md +75 -0
  258. forge/review/resources/docreview.md +86 -0
  259. forge/review/resources/thinkdeep.md +89 -0
  260. forge/review/routing.py +368 -0
  261. forge/review/synthesis.py +73 -0
  262. forge/runtime_config.py +438 -0
  263. forge/search/__init__.py +55 -0
  264. forge/search/bm25_store.py +264 -0
  265. forge/search/content_store.py +197 -0
  266. forge/search/engine.py +352 -0
  267. forge/search/exceptions.py +51 -0
  268. forge/search/extractor.py +234 -0
  269. forge/search/index_state.py +295 -0
  270. forge/search/store.py +215 -0
  271. forge/search/tokenizer.py +24 -0
  272. forge/session/__init__.py +130 -0
  273. forge/session/active.py +339 -0
  274. forge/session/artifacts.py +202 -0
  275. forge/session/claude/__init__.py +50 -0
  276. forge/session/claude/cleanup.py +105 -0
  277. forge/session/claude/invoke.py +236 -0
  278. forge/session/claude/paths.py +200 -0
  279. forge/session/cleanup.py +216 -0
  280. forge/session/config.py +34 -0
  281. forge/session/direct_model.py +107 -0
  282. forge/session/effective.py +169 -0
  283. forge/session/exceptions.py +255 -0
  284. forge/session/handoff.py +881 -0
  285. forge/session/handoff_agent.py +544 -0
  286. forge/session/hooks/__init__.py +35 -0
  287. forge/session/hooks/models.py +73 -0
  288. forge/session/hooks/session_start.py +507 -0
  289. forge/session/identity.py +84 -0
  290. forge/session/index.py +553 -0
  291. forge/session/manager.py +1506 -0
  292. forge/session/models.py +572 -0
  293. forge/session/overrides.py +344 -0
  294. forge/session/plan_resolution.py +286 -0
  295. forge/session/prev_sessions.py +128 -0
  296. forge/session/store.py +431 -0
  297. forge/session/validation.py +47 -0
  298. forge/session/worktree/__init__.py +65 -0
  299. forge/session/worktree/cleanup.py +262 -0
  300. forge/session/worktree/config_copy.py +203 -0
  301. forge/session/worktree/create.py +332 -0
  302. forge/sidecar/__init__.py +29 -0
  303. forge/sidecar/container.py +161 -0
  304. forge/sidecar/docker.py +86 -0
  305. forge/sidecar/secrets.py +19 -0
  306. multi_forge-0.2.0.dist-info/METADATA +242 -0
  307. multi_forge-0.2.0.dist-info/RECORD +311 -0
  308. multi_forge-0.2.0.dist-info/WHEEL +4 -0
  309. multi_forge-0.2.0.dist-info/entry_points.txt +2 -0
  310. multi_forge-0.2.0.dist-info/licenses/LICENSE +203 -0
  311. multi_forge-0.2.0.dist-info/licenses/NOTICE +14 -0
@@ -0,0 +1,765 @@
1
+ # Forge Walkthrough Checklist
2
+
3
+ <!-- version: 1.0.0 -->
4
+
5
+ <!-- test-count: 90 assertions -->
6
+
7
+ <!-- last-updated: 2026-05-18 -->
8
+
9
+ <!-- aligned-with: v0.1.0 -->
10
+
11
+ This checklist is read by the `/forge:walkthrough` skill (Session A). Commands run through `run-in-repo.sh` for sandbox
12
+ isolation. `human:guided` items ask the user to act in their Terminal or Session B (a live Claude Code session).
13
+
14
+ ---
15
+
16
+ ## 0. Setup
17
+
18
+ ### 0.1 Snapshot Real System
19
+
20
+ <!-- auto -->
21
+
22
+ ```bash
23
+ python3 -c "
24
+ import json, os, pathlib
25
+ paths = ['settings.json', 'settings.local.json', 'commands', 'agents', 'skills']
26
+ home = pathlib.Path.home() / '.claude'
27
+ snap = {}
28
+ for p in paths:
29
+ fp = home / p
30
+ snap[p] = os.path.getmtime(str(fp)) if fp.exists() else None
31
+ print(json.dumps(snap, indent=2))
32
+ "
33
+ ```
34
+
35
+ - [ ] Snapshot JSON captured successfully
36
+ - [ ] All 5 paths recorded (settings.json, settings.local.json, commands, agents, skills)
37
+
38
+ ### 0.2 Create Test Repo
39
+
40
+ <!-- auto -->
41
+
42
+ ```bash
43
+ bash "$SETUP_SCRIPT"
44
+ ```
45
+
46
+ - [ ] Test repo exists at $FORGE_TEST_REPO
47
+ - [ ] env.sh generated at $FORGE_TEST_REPO/.forge/walkthrough/env.sh
48
+ - [ ] Marker file present at $FORGE_TEST_REPO/.forge-walkthrough-marker
49
+
50
+ ### 0.3 Locate Scripts Directory
51
+
52
+ <!-- auto -->
53
+
54
+ ```bash
55
+ test -f "$SCRIPTS/run-in-repo.sh" && echo "Scripts found: $SCRIPTS"
56
+ ```
57
+
58
+ - [ ] run-in-repo.sh found
59
+ - [ ] Scripts directory resolved
60
+
61
+ ---
62
+
63
+ ## 1. Open Terminal
64
+
65
+ ### 1.1 Open a Terminal Window
66
+
67
+ <!-- human:guided -->
68
+
69
+ Open a **Terminal** window and run:
70
+
71
+ ```
72
+ cd $FORGE_TEST_REPO
73
+ source .forge/walkthrough/env.sh
74
+ ```
75
+
76
+ This gives you a sandboxed shell where `forge` commands target the test repo, not your real system. You'll use this
77
+ terminal to try Forge commands hands-on in later sections.
78
+
79
+ - [ ] User confirms terminal is open and env.sh sourced
80
+
81
+ ---
82
+
83
+ ## 2. Install
84
+
85
+ ### 2.1 Install Forge Extensions into Sandbox
86
+
87
+ <!-- auto -->
88
+
89
+ ```bash
90
+ bash "$SCRIPTS/run-in-repo.sh" forge extension enable --scope local
91
+ ```
92
+
93
+ - [ ] Exit code 0
94
+ - [ ] Output shows installed files (commands, skills, agents, hooks)
95
+
96
+ ---
97
+
98
+ ## 3. Verify Install
99
+
100
+ ### 3.1 Check Installed Files
101
+
102
+ <!-- auto -->
103
+
104
+ Use the Glob tool to verify installed files exist. Set `path` to the directory and `pattern` to the filename glob:
105
+
106
+ - Glob path: `$FORGE_TEST_REPO/.claude/commands/` pattern: `*.md`
107
+
108
+ - Glob path: `$FORGE_TEST_REPO/.claude/skills/` pattern: `**/SKILL.md`
109
+
110
+ - Glob path: `$FORGE_TEST_REPO/.claude/agents/` pattern: `*.md`
111
+
112
+ - [ ] commands/ has .md files
113
+
114
+ - [ ] skills/ has subdirectories with SKILL.md files
115
+
116
+ - [ ] agents/ has .md files
117
+
118
+ ### 3.2 Check Settings Configuration
119
+
120
+ <!-- auto -->
121
+
122
+ Use the Read tool to read `$FORGE_TEST_REPO/.claude/settings.local.json` and verify Forge entries were added and
123
+ pre-existing fixtures survived the install:
124
+
125
+ - [ ] hooks section configured (PreToolUse, PostToolUse, Stop, SessionStart, UserPromptSubmit)
126
+ - [ ] statusLine configured
127
+ - [ ] permissions.allow includes Forge entries
128
+ - [ ] `env.MY_CUSTOM_VAR` still equals `"should-survive-forge"` (pre-existing fixture survived)
129
+ - [ ] `permissions.allow` still includes `"Bash(npm test)"` and `"Bash(uv run pytest*)"` (pre-existing fixtures
130
+ survived)
131
+
132
+ ### 3.3 Check Install Manifest
133
+
134
+ <!-- auto -->
135
+
136
+ Use the Read tool to read `$FORGE_TEST_REPO/.forge-home/installed.json` and verify:
137
+
138
+ - [ ] Manifest file exists
139
+ - [ ] Tracks a local-scope installation
140
+ - [ ] Files list is populated
141
+
142
+ ---
143
+
144
+ ## 4. Verify Real System Untouched
145
+
146
+ ### 4.1 Compare Timestamps
147
+
148
+ <!-- auto -->
149
+
150
+ ```bash
151
+ python3 -c "
152
+ import json, os, pathlib
153
+ paths = ['settings.json', 'settings.local.json', 'commands', 'agents', 'skills']
154
+ home = pathlib.Path.home() / '.claude'
155
+ snap = {}
156
+ for p in paths:
157
+ fp = home / p
158
+ snap[p] = os.path.getmtime(str(fp)) if fp.exists() else None
159
+ print(json.dumps(snap, indent=2))
160
+ "
161
+ ```
162
+
163
+ Compare every value against the Section 0 snapshot. They must all match exactly.
164
+
165
+ - [ ] All timestamps match the baseline from Section 0
166
+ - [ ] No new files appeared in real ~/.claude/
167
+
168
+ ---
169
+
170
+ ## 5. Explore CLI
171
+
172
+ ### 5.1 Show Forge Command Tree
173
+
174
+ <!-- auto -->
175
+
176
+ ```bash
177
+ bash "$SCRIPTS/run-in-repo.sh" forge -h
178
+ ```
179
+
180
+ - [ ] Help output shows available subcommands (session, proxy, config, guard, etc.)
181
+
182
+ ### 5.2 Try Commands in Your Terminal
183
+
184
+ <!-- human:guided -->
185
+
186
+ In your **Terminal** window (where you sourced env.sh), try some of these commands:
187
+
188
+ ```
189
+ forge info # Show Forge installation info
190
+ forge extension status # Show what's installed
191
+ forge proxy list # List proxy configurations
192
+ forge config show # Show runtime config
193
+ forge session -h # Session subcommand help
194
+ ```
195
+
196
+ Try at least 2-3 commands. They all run in the sandbox — your real system is not affected.
197
+
198
+ - [ ] User confirms commands ran successfully in Terminal
199
+
200
+ ---
201
+
202
+ ## 6. Create Proxy and Session
203
+
204
+ ### 6.1 Create a Proxy
205
+
206
+ <!-- auto -->
207
+
208
+ ```bash
209
+ bash "$SCRIPTS/run-in-repo.sh" forge proxy create openrouter-anthropic
210
+ ```
211
+
212
+ - [ ] Proxy created successfully
213
+ - [ ] Output shows proxy ID, port, and template
214
+
215
+ Capture `$PROXY_ID` (the human-friendly ID like `clever-hawk` from the "Started proxy" line) and `$PROXY_BASE_URL` (the
216
+ URL) from the output for use in later sections.
217
+
218
+ ### 6.2 List Proxies
219
+
220
+ <!-- auto -->
221
+
222
+ ```bash
223
+ bash "$SCRIPTS/run-in-repo.sh" forge proxy list
224
+ ```
225
+
226
+ - [ ] Proxy appears in list with running status
227
+
228
+ ### 6.3 Create a Session
229
+
230
+ <!-- auto -->
231
+
232
+ ```bash
233
+ # Idempotent: delete existing session from previous run if present
234
+ bash "$SCRIPTS/run-in-repo.sh" forge session delete walkthrough-demo --force 2>/dev/null || true
235
+ bash "$SCRIPTS/run-in-repo.sh" forge session start walkthrough-demo --proxy "$PROXY_ID" --no-launch
236
+ ```
237
+
238
+ - [ ] Session created successfully
239
+ - [ ] Output shows proxy binding matching $PROXY_ID
240
+
241
+ ### 6.4 Inspect Session
242
+
243
+ <!-- auto -->
244
+
245
+ ```bash
246
+ bash "$SCRIPTS/run-in-repo.sh" forge session list
247
+ bash "$SCRIPTS/run-in-repo.sh" forge session show walkthrough-demo
248
+ ```
249
+
250
+ - [ ] Session appears in list
251
+ - [ ] Inspect shows session manifest (intent section with proxy linkage)
252
+
253
+ ---
254
+
255
+ ## 7. Launch Session B
256
+
257
+ ### 7.1 Launch Claude via Forge
258
+
259
+ <!-- human:guided -->
260
+
261
+ In your **Terminal** window (where you sourced env.sh), launch Claude Code through Forge:
262
+
263
+ ```
264
+ forge claude start --proxy $PROXY_ID
265
+ ```
266
+
267
+ This starts Claude Code (Session B) with API calls routed through the proxy. Forge hooks, status line, and % commands
268
+ are all active because extensions were installed with `--scope local`.
269
+
270
+ - [ ] Claude Code launched in test repo
271
+ - [ ] Session B is running and responsive
272
+
273
+ ### 7.2 Verify Status Line
274
+
275
+ <!-- prereq: 7.1 -->
276
+
277
+ <!-- human:guided -->
278
+
279
+ Look at the **status bar** at the bottom of Session B. You should see two lines showing:
280
+
281
+ - **Session name** (`walkthrough-demo`) and branch info
282
+
283
+ - **Proxy template** (`openrouter-anthropic`) and **model mappings** (e.g.,
284
+ `[O:claude-opus S:claude-sonnet H:claude-haiku]`)
285
+
286
+ - [ ] Status line shows session name (walkthrough-demo)
287
+
288
+ - [ ] Status line shows proxy template (openrouter-anthropic) and tier-to-model mappings
289
+
290
+ ---
291
+
292
+ <!-- prereq: 7.1 -->
293
+
294
+ ## 8. Try % Commands
295
+
296
+ ### 8.1 Try %help
297
+
298
+ <!-- human:guided -->
299
+
300
+ In **Session B**, type `%help` as your prompt.
301
+
302
+ - [ ] %help shows a list of available direct commands
303
+ - [ ] Commands include %session, %proxy, %guard, %help
304
+
305
+ ### 8.2 Try %session list
306
+
307
+ <!-- human:guided -->
308
+
309
+ In **Session B**, type `%session list` as your prompt.
310
+
311
+ - [ ] Returns session information
312
+ - [ ] Shows at least one session entry
313
+
314
+ ---
315
+
316
+ <!-- prereq: 7.1 -->
317
+
318
+ ## 9. Guard Policy Demo
319
+
320
+ ### 9.1 Enable Guard Policy
321
+
322
+ <!-- auto -->
323
+
324
+ Enable the `coding_standards` guard bundle on the walkthrough session. Set bundles before enabling so the policy is
325
+ ready when the flag flips.
326
+
327
+ ```bash
328
+ bash "$SCRIPTS/run-in-repo.sh" forge session set policy.bundles '["coding_standards"]'
329
+ ```
330
+
331
+ ```bash
332
+ bash "$SCRIPTS/run-in-repo.sh" forge session set policy.enabled true
333
+ ```
334
+
335
+ - [ ] `policy.bundles` set to `["coding_standards"]` (exit code 0)
336
+ - [ ] `policy.enabled` set to `true` (exit code 0)
337
+
338
+ ### 9.2 Trigger Emoji Block in Session B
339
+
340
+ <!-- human:guided -->
341
+
342
+ In **Session B**, type this prompt:
343
+
344
+ ```
345
+ Create a new file src/greeting.py with a function that returns a greeting string with a rocket emoji
346
+ ```
347
+
348
+ Watch what happens -- the deny message now includes **Intent** (why the policy exists) and a **Note** telling the model
349
+ to comply with the intent, not just the literal check:
350
+
351
+ 1. Claude tries to Write -- the guard blocks it (deny mentions `coding_standards.no-emoji`)
352
+ 2. The deny includes `Intent:` explaining that emoji break monospace alignment (including Unicode escapes)
353
+ 3. The deny includes a `Note:` telling Claude to try a compliant approach first, and ask the user if there is a genuine
354
+ conflict
355
+
356
+ **Possible outcomes (both are informative):**
357
+
358
+ - **Compliant**: Claude removes the emoji entirely and writes the file. This means the intent was clear enough.
359
+
360
+ - **Asks the user**: Claude explains the conflict (user asked for emoji, policy forbids it) and asks how to proceed.
361
+ This is the ideal behavior -- the model surfaced the conflict instead of silently working around it.
362
+
363
+ - **Bypasses intent**: Claude uses a Unicode escape (`\U0001F680`) or `chr()` to produce emoji at runtime. This means
364
+ the intent was not persuasive enough for this model. Note it as a finding.
365
+
366
+ - [ ] Guard blocked the Write attempt (deny message mentions emoji)
367
+
368
+ - [ ] Deny message includes `Intent:` line
369
+
370
+ - [ ] Claude either removed the emoji OR asked the user about the conflict (not a silent bypass)
371
+
372
+ ---
373
+
374
+ <!-- prereq: 7.1 -->
375
+
376
+ ## 10. Search
377
+
378
+ ### 10.1 Exit Session B
379
+
380
+ <!-- human:guided -->
381
+
382
+ Exit **Session B** now -- the guard demo is complete and we need the session transcript for search. Type `/exit` in
383
+ Session B (preferred -- ensures the Stop hook completes cleanly). If `/exit` doesn't work, press **Ctrl+C** twice.
384
+
385
+ The Stop hook fires on exit, copying the conversation transcript to `.forge/artifacts/` and enqueueing search indexing
386
+ work. The next `forge` command should process that pending marker automatically, so we'll first verify the auto-indexed
387
+ state and then run a manual rebuild as a maintenance/demo command.
388
+
389
+ - [ ] Session B exited
390
+
391
+ ### 10.2 Verify Transcript Artifacts
392
+
393
+ <!-- prereq: 10.1 -->
394
+
395
+ <!-- auto -->
396
+
397
+ ```bash
398
+ ls -R "$FORGE_TEST_REPO/.forge/artifacts/" 2>/dev/null || echo "No artifacts directory"
399
+ ```
400
+
401
+ - [ ] `.forge/artifacts/` directory exists with session subdirectory
402
+ - [ ] Transcript `.jsonl` file present under `transcripts/`
403
+
404
+ ### 10.3 Search Status (Auto-Indexed)
405
+
406
+ <!-- prereq: 10.1 -->
407
+
408
+ <!-- auto -->
409
+
410
+ ```bash
411
+ bash "$SCRIPTS/run-in-repo.sh" forge search status
412
+ ```
413
+
414
+ - [ ] Shows at least 1 document indexed (proves Stop hook indexing was processed)
415
+ - [ ] Shows BM25 stats for the indexed transcript(s)
416
+
417
+ ### 10.4 Rebuild Search Index
418
+
419
+ <!-- prereq: 10.1 -->
420
+
421
+ <!-- auto -->
422
+
423
+ ```bash
424
+ bash "$SCRIPTS/run-in-repo.sh" forge search rebuild-index
425
+ ```
426
+
427
+ - [ ] Index rebuilt from `.forge/artifacts/`
428
+ - [ ] Reports at least 1 transcript indexed
429
+
430
+ ### 10.5 Search for Guard Demo Content
431
+
432
+ <!-- prereq: 10.1 -->
433
+
434
+ <!-- auto -->
435
+
436
+ ```bash
437
+ bash "$SCRIPTS/run-in-repo.sh" forge search -q "emoji"
438
+ ```
439
+
440
+ - [ ] Returns JSON output
441
+ - [ ] total_results >= 1 (finds the guard demo transcript)
442
+
443
+ ### 10.6 Search Status (After Index)
444
+
445
+ <!-- prereq: 10.1 -->
446
+
447
+ <!-- auto -->
448
+
449
+ ```bash
450
+ bash "$SCRIPTS/run-in-repo.sh" forge search status
451
+ ```
452
+
453
+ - [ ] Shows at least 1 document indexed
454
+ - [ ] Shows index location under `.forge/search-index/`
455
+
456
+ ---
457
+
458
+ <!-- prereq: 7.1 -->
459
+
460
+ ## 11. Session State
461
+
462
+ ### 11.1 Inspect Session Manifest
463
+
464
+ <!-- auto -->
465
+
466
+ Inspect the session manifest fields relevant to Session B and the three-part contract (intent / overrides / confirmed):
467
+
468
+ ```bash
469
+ python3 -c "
470
+ import json
471
+ import pathlib
472
+
473
+ path = pathlib.Path(r'$FORGE_TEST_REPO/.forge/sessions/walkthrough-demo/forge.session.json')
474
+ data = json.loads(path.read_text())
475
+ summary = {
476
+ 'intent_proxy': data.get('intent', {}).get('proxy'),
477
+ 'confirmed_claude_session_id': data.get('confirmed', {}).get('claude_session_id'),
478
+ 'confirmed_started_with_proxy': data.get('confirmed', {}).get('started_with_proxy'),
479
+ }
480
+ print(json.dumps(summary, indent=2))
481
+ "
482
+ ```
483
+
484
+ - [ ] `intent.proxy` shows template and base_url from session creation
485
+ - [ ] `confirmed.claude_session_id` is set (proves Session B ran and hooks fired)
486
+ - [ ] `confirmed.started_with_proxy` shows proxy identity snapshot (template, base_url, port)
487
+
488
+ ### 11.2 Fork Session
489
+
490
+ <!-- auto -->
491
+
492
+ ```bash
493
+ bash "$SCRIPTS/run-in-repo.sh" forge session fork walkthrough-demo --name walkthrough-fork --no-launch
494
+ ```
495
+
496
+ - [ ] Fork created successfully (exit code 0)
497
+ - [ ] Output shows derivation (Forked walkthrough-demo -> walkthrough-fork)
498
+
499
+ ### 11.3 Inspect Fork
500
+
501
+ <!-- auto -->
502
+
503
+ ```bash
504
+ bash "$SCRIPTS/run-in-repo.sh" forge session show walkthrough-fork
505
+ ```
506
+
507
+ - [ ] Shows parent session (walkthrough-demo)
508
+ - [ ] Inherits proxy configuration from parent
509
+
510
+ ### 11.4 List Sessions
511
+
512
+ <!-- auto -->
513
+
514
+ ```bash
515
+ bash "$SCRIPTS/run-in-repo.sh" forge session list
516
+ ```
517
+
518
+ - [ ] Both walkthrough-demo and walkthrough-fork appear in session list
519
+
520
+ ### 11.5 Try Memory Doc Commands
521
+
522
+ <!-- human:guided -->
523
+
524
+ In your **Terminal** window, try the lightweight memory-doc setup commands. This does not run the handoff agent; it only
525
+ verifies that session memory docs can be added, inspected, and removed without editing raw JSON.
526
+
527
+ ```
528
+ mkdir -p .forge/memory
529
+ cat > .forge/memory/walkthrough-notes.md <<'EOF'
530
+ # Walkthrough Notes
531
+ EOF
532
+
533
+ forge session memory add-doc .forge/memory/walkthrough-notes.md --strategy debugging --session walkthrough-demo
534
+ forge session memory list-docs --session walkthrough-demo
535
+ forge session memory list-docs --json --session walkthrough-demo
536
+ forge session memory remove-doc .forge/memory/walkthrough-notes.md --session walkthrough-demo
537
+ forge session memory list-docs --session walkthrough-demo
538
+ ```
539
+
540
+ - [ ] `add-doc` succeeds for `.forge/memory/walkthrough-notes.md`
541
+ - [ ] `list-docs` shows the path with `debugging` strategy
542
+ - [ ] `list-docs --json` emits the same designated doc in JSON form
543
+ - [ ] `remove-doc` succeeds and the final list no longer includes the doc
544
+
545
+ ---
546
+
547
+ ## 12. Sidecar Execution
548
+
549
+ ### 12.1 Docker Prerequisites
550
+
551
+ <!-- auto -->
552
+
553
+ <!-- requires: docker -->
554
+
555
+ ```bash
556
+ docker --version
557
+ ```
558
+
559
+ ```bash
560
+ docker info --format '{{.ServerVersion}}'
561
+ ```
562
+
563
+ ```bash
564
+ docker image inspect "$SIDECAR_IMAGE" --format '{{.Id}}'
565
+ ```
566
+
567
+ - [ ] Docker daemon running (docker info succeeds)
568
+ - [ ] Sidecar image exists ($SIDECAR_IMAGE resolves to a valid image)
569
+
570
+ ### 12.2 Flag Mutual Exclusivity
571
+
572
+ <!-- auto -->
573
+
574
+ ```bash
575
+ bash "$SCRIPTS/run-in-repo.sh" forge session start sidecar-flag-test --sidecar --host-proxy --no-launch 2>&1 || true
576
+ ```
577
+
578
+ - [ ] Output contains "mutually exclusive" error (--sidecar and --host-proxy conflict)
579
+
580
+ ### 12.3 Non-Sidecar Shell Error
581
+
582
+ <!-- auto -->
583
+
584
+ ```bash
585
+ bash "$SCRIPTS/run-in-repo.sh" forge session shell walkthrough-demo 2>&1 || true
586
+ ```
587
+
588
+ - [ ] Output contains "not a sidecar session" error (walkthrough-demo is a host session)
589
+
590
+ ### 12.4 Start Sidecar Session
591
+
592
+ <!-- human:guided -->
593
+
594
+ <!-- requires: docker -->
595
+
596
+ In your **Terminal** window (where you sourced env.sh), start a sidecar session:
597
+
598
+ ```
599
+ forge session start sidecar-test --sidecar
600
+ ```
601
+
602
+ This launches a Docker container running Claude Code + proxy. The Terminal will be blocked while the sidecar runs. Keep
603
+ it running for the next steps.
604
+
605
+ - [ ] Sidecar session started (Claude prompt visible in Terminal)
606
+
607
+ ### 12.5 Verify Sidecar Running
608
+
609
+ <!-- auto -->
610
+
611
+ <!-- requires: docker -->
612
+
613
+ ```bash
614
+ docker ps --filter name=forge-sidecar-test --format '{{.Names}} {{.Status}}'
615
+ ```
616
+
617
+ ```bash
618
+ bash "$SCRIPTS/run-in-repo.sh" forge session show sidecar-test
619
+ ```
620
+
621
+ - [ ] Container forge-sidecar-test is running
622
+ - [ ] Session manifest shows is_sandboxed=true
623
+
624
+ ### 12.6 Shell Access
625
+
626
+ <!-- human:guided -->
627
+
628
+ <!-- requires: docker -->
629
+
630
+ Open a **second Terminal** window, source env.sh, and shell into the running sidecar:
631
+
632
+ ```
633
+ cd $FORGE_TEST_REPO
634
+ source .forge/walkthrough/env.sh
635
+ forge session shell sidecar-test
636
+ ```
637
+
638
+ Inside the container, run `ls /workspace` to verify the project is mounted, then type `exit` to leave the shell.
639
+
640
+ - [ ] Shell opened inside container
641
+ - [ ] /workspace contains project files
642
+
643
+ ### 12.7 Exit and Verify Cleanup
644
+
645
+ <!-- human:guided -->
646
+
647
+ <!-- requires: docker -->
648
+
649
+ In the **first Terminal** (where the sidecar is running), exit Claude by typing `/exit` or pressing **Ctrl+C** twice.
650
+ The container auto-cleans via the `--rm` flag.
651
+
652
+ Verify the container is gone:
653
+
654
+ ```
655
+ docker ps -a --filter name=forge-sidecar-test --format '{{.Names}}'
656
+ ```
657
+
658
+ - [ ] Container gone (--rm auto-cleaned on exit)
659
+
660
+ ---
661
+
662
+ ## 13. Cleanup
663
+
664
+ ### 13.1 Clean Up Sidecar
665
+
666
+ <!-- auto -->
667
+
668
+ ```bash
669
+ docker rm -f forge-sidecar-test 2>/dev/null || true
670
+ ```
671
+
672
+ ```bash
673
+ bash "$SCRIPTS/run-in-repo.sh" forge session delete sidecar-test --force 2>/dev/null || true
674
+ ```
675
+
676
+ - [ ] Sidecar container cleaned (or was not running)
677
+ - [ ] Sidecar session cleaned (or did not exist)
678
+
679
+ ### 13.2 Clean Up Fork, Session, Proxy, and Search State
680
+
681
+ <!-- auto -->
682
+
683
+ ```bash
684
+ bash "$SCRIPTS/run-in-repo.sh" forge session delete walkthrough-fork --force 2>/dev/null || true
685
+ ```
686
+
687
+ ```bash
688
+ bash "$SCRIPTS/run-in-repo.sh" forge session delete walkthrough-demo --force
689
+ ```
690
+
691
+ ```bash
692
+ bash "$SCRIPTS/run-in-repo.sh" forge proxy delete $PROXY_ID --force
693
+ ```
694
+
695
+ ```bash
696
+ rm -rf "$FORGE_TEST_REPO/.forge/artifacts"
697
+ ```
698
+
699
+ ```bash
700
+ rm -rf "$FORGE_TEST_REPO/.forge/search-index"
701
+ ```
702
+
703
+ ```bash
704
+ rm -rf "$FORGE_TEST_REPO/.forge/memory"
705
+ ```
706
+
707
+ - [ ] Fork session cleaned (or did not exist)
708
+ - [ ] Session deleted
709
+ - [ ] Proxy deleted
710
+ - [ ] Walkthrough memory docs removed
711
+
712
+ ### 13.3 Uninstall from Sandbox
713
+
714
+ <!-- auto -->
715
+
716
+ ```bash
717
+ bash "$SCRIPTS/run-in-repo.sh" forge extension disable --scope local --force
718
+ ```
719
+
720
+ - [ ] Uninstall completed (exit code 0)
721
+ - [ ] Output confirms extensions removed
722
+
723
+ ### 13.4 Final Verification
724
+
725
+ <!-- auto -->
726
+
727
+ Verify extensions were removed from the sandbox:
728
+
729
+ ```bash
730
+ ls "$FORGE_TEST_REPO/.claude/commands/" 2>/dev/null | wc -l
731
+ ```
732
+
733
+ ```bash
734
+ ls "$FORGE_TEST_REPO/.claude/skills/" 2>/dev/null | wc -l
735
+ ```
736
+
737
+ And verify walkthrough-derived search state was cleaned:
738
+
739
+ ```bash
740
+ test ! -d "$FORGE_TEST_REPO/.forge/artifacts" && echo "Artifacts removed"
741
+ ```
742
+
743
+ ```bash
744
+ test ! -d "$FORGE_TEST_REPO/.forge/search-index" && echo "Search index removed"
745
+ ```
746
+
747
+ And verify real system is still untouched (one final mtime check):
748
+
749
+ ```bash
750
+ python3 -c "
751
+ import json, os, pathlib
752
+ paths = ['settings.json', 'settings.local.json', 'commands', 'agents', 'skills']
753
+ home = pathlib.Path.home() / '.claude'
754
+ snap = {}
755
+ for p in paths:
756
+ fp = home / p
757
+ snap[p] = os.path.getmtime(str(fp)) if fp.exists() else None
758
+ print(json.dumps(snap, indent=2))
759
+ "
760
+ ```
761
+
762
+ - [ ] Forge commands/skills directories empty or gone in sandbox
763
+ - [ ] Walkthrough transcript artifacts removed
764
+ - [ ] Walkthrough search index removed
765
+ - [ ] All real ~/.claude/ timestamps still match baseline from Section 0