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.
- forge/__init__.py +3 -0
- forge/_extensions/agents/.gitkeep +0 -0
- forge/_extensions/commands/.gitkeep +0 -0
- forge/_extensions/skills/analyze/SKILL.md +87 -0
- forge/_extensions/skills/challenge/SKILL.md +91 -0
- forge/_extensions/skills/consensus/SKILL.md +120 -0
- forge/_extensions/skills/consensus/resources/code_consensus_evaluation.md +94 -0
- forge/_extensions/skills/consensus/resources/consensus_evaluation.md +70 -0
- forge/_extensions/skills/consensus/resources/synthesis.md +101 -0
- forge/_extensions/skills/debate/SKILL.md +116 -0
- forge/_extensions/skills/debate/resources/code_debate_evaluation.md +101 -0
- forge/_extensions/skills/debate/resources/debate_evaluation.md +90 -0
- forge/_extensions/skills/panel/SKILL.md +141 -0
- forge/_extensions/skills/panel/resources/synthesis.md +103 -0
- forge/_extensions/skills/qa/SKILL.md +704 -0
- forge/_extensions/skills/qa/resources/checklist/0-enable.md +78 -0
- forge/_extensions/skills/qa/resources/checklist/1-preflight.md +24 -0
- forge/_extensions/skills/qa/resources/checklist/10-resume.md +143 -0
- forge/_extensions/skills/qa/resources/checklist/11-config.md +150 -0
- forge/_extensions/skills/qa/resources/checklist/12-search.md +58 -0
- forge/_extensions/skills/qa/resources/checklist/13-guard.md +237 -0
- forge/_extensions/skills/qa/resources/checklist/14-workflow.md +305 -0
- forge/_extensions/skills/qa/resources/checklist/15-skills.md +155 -0
- forge/_extensions/skills/qa/resources/checklist/16-handoff.md +224 -0
- forge/_extensions/skills/qa/resources/checklist/17-info.md +50 -0
- forge/_extensions/skills/qa/resources/checklist/18-disable.md +84 -0
- forge/_extensions/skills/qa/resources/checklist/19-uninstall.md +146 -0
- forge/_extensions/skills/qa/resources/checklist/2-extensions.md +188 -0
- forge/_extensions/skills/qa/resources/checklist/20-cleanup.md +36 -0
- forge/_extensions/skills/qa/resources/checklist/3-auth.md +234 -0
- forge/_extensions/skills/qa/resources/checklist/4-proxy.md +481 -0
- forge/_extensions/skills/qa/resources/checklist/5-session.md +541 -0
- forge/_extensions/skills/qa/resources/checklist/6-hooks.md +275 -0
- forge/_extensions/skills/qa/resources/checklist/7-costs.md +309 -0
- forge/_extensions/skills/qa/resources/checklist/8-status-line.md +174 -0
- forge/_extensions/skills/qa/resources/checklist/9-direct-commands.md +146 -0
- forge/_extensions/skills/qa/resources/checklist.md +103 -0
- forge/_extensions/skills/qa/resources/report-template.md +62 -0
- forge/_extensions/skills/qa/scripts/start-container.sh +529 -0
- forge/_extensions/skills/qa/scripts/walkthrough-state.py +1137 -0
- forge/_extensions/skills/review/SKILL.md +125 -0
- forge/_extensions/skills/review/references/claude-4.6.md +474 -0
- forge/_extensions/skills/review/references/claude-4.7.md +710 -0
- forge/_extensions/skills/review/references/gemini-3.1.md +546 -0
- forge/_extensions/skills/review/references/gpt-5.5.md +490 -0
- forge/_extensions/skills/review/references/skills-writing-guide.md +1588 -0
- forge/_extensions/skills/review/resources/code-anthropic.md +160 -0
- forge/_extensions/skills/review/resources/code-gemini.md +184 -0
- forge/_extensions/skills/review/resources/code-openai.md +203 -0
- forge/_extensions/skills/review/resources/code.md +160 -0
- forge/_extensions/skills/review-docs/SKILL.md +121 -0
- forge/_extensions/skills/review-docs/resources/docs-anthropic.md +170 -0
- forge/_extensions/skills/review-docs/resources/docs-gemini.md +204 -0
- forge/_extensions/skills/review-docs/resources/docs-openai.md +231 -0
- forge/_extensions/skills/review-docs/resources/docs.md +170 -0
- forge/_extensions/skills/smoke-test/SKILL.md +27 -0
- forge/_extensions/skills/smoke-test/scripts/smoke-test.sh +118 -0
- forge/_extensions/skills/understand/SKILL.md +148 -0
- forge/_extensions/skills/understand/resources/code-anthropic.md +163 -0
- forge/_extensions/skills/understand/resources/code-gemini.md +194 -0
- forge/_extensions/skills/understand/resources/code-openai.md +181 -0
- forge/_extensions/skills/understand/resources/code.md +163 -0
- forge/_extensions/skills/understand/resources/docs-anthropic.md +177 -0
- forge/_extensions/skills/understand/resources/docs-gemini.md +202 -0
- forge/_extensions/skills/understand/resources/docs-openai.md +191 -0
- forge/_extensions/skills/understand/resources/docs.md +177 -0
- forge/_extensions/skills/walkthrough/SKILL.md +599 -0
- forge/_extensions/skills/walkthrough/resources/checklist.md +765 -0
- forge/_extensions/skills/walkthrough/scripts/run-in-repo.sh +118 -0
- forge/_extensions/skills/walkthrough/scripts/setup-test-repo.sh +198 -0
- forge/_extensions/skills/walkthrough/scripts/walkthrough-state.py +1137 -0
- forge/backend/__init__.py +174 -0
- forge/backend/adapters/__init__.py +38 -0
- forge/backend/adapters/litellm.py +158 -0
- forge/backend/creation.py +89 -0
- forge/backend/registry.py +178 -0
- forge/cli/__init__.py +16 -0
- forge/cli/auth.py +483 -0
- forge/cli/backend.py +298 -0
- forge/cli/claude.py +411 -0
- forge/cli/config_cmd.py +303 -0
- forge/cli/extensions.py +1001 -0
- forge/cli/gc.py +165 -0
- forge/cli/guard.py +1018 -0
- forge/cli/guards.py +106 -0
- forge/cli/handoff.py +110 -0
- forge/cli/hooks/__init__.py +36 -0
- forge/cli/hooks/_group.py +20 -0
- forge/cli/hooks/_helpers.py +149 -0
- forge/cli/hooks/commands.py +1677 -0
- forge/cli/hooks/direct_commands.py +1304 -0
- forge/cli/hooks/install.py +232 -0
- forge/cli/hooks/policy.py +151 -0
- forge/cli/hooks/read_hygiene.py +74 -0
- forge/cli/hooks/verification.py +370 -0
- forge/cli/logs.py +406 -0
- forge/cli/main.py +292 -0
- forge/cli/proxy.py +1821 -0
- forge/cli/proxy_costs.py +313 -0
- forge/cli/search.py +416 -0
- forge/cli/session.py +892 -0
- forge/cli/session_addendum.py +81 -0
- forge/cli/session_fork.py +750 -0
- forge/cli/session_handoff.py +141 -0
- forge/cli/session_lifecycle.py +2053 -0
- forge/cli/session_manage.py +1336 -0
- forge/cli/session_memory.py +201 -0
- forge/cli/status_line.py +1398 -0
- forge/cli/workflow.py +1964 -0
- forge/config/__init__.py +110 -0
- forge/config/dataclass_utils.py +88 -0
- forge/config/defaults/__init__.py +0 -0
- forge/config/defaults/backends/__init__.py +0 -0
- forge/config/defaults/backends/litellm.yaml +196 -0
- forge/config/defaults/templates/__init__.py +0 -0
- forge/config/defaults/templates/litellm-anthropic-local.yaml +33 -0
- forge/config/defaults/templates/litellm-anthropic.yaml +24 -0
- forge/config/defaults/templates/litellm-gemini-flash-local.yaml +37 -0
- forge/config/defaults/templates/litellm-gemini-local.yaml +32 -0
- forge/config/defaults/templates/litellm-gemini-test.yaml +34 -0
- forge/config/defaults/templates/litellm-gemini.yaml +21 -0
- forge/config/defaults/templates/litellm-openai-codex-local.yaml +36 -0
- forge/config/defaults/templates/litellm-openai-local.yaml +38 -0
- forge/config/defaults/templates/litellm-openai.yaml +28 -0
- forge/config/defaults/templates/openrouter-anthropic.yaml +23 -0
- forge/config/defaults/templates/openrouter-deepseek.yaml +26 -0
- forge/config/defaults/templates/openrouter-gemini-flash.yaml +26 -0
- forge/config/defaults/templates/openrouter-gemini.yaml +23 -0
- forge/config/defaults/templates/openrouter-glm.yaml +23 -0
- forge/config/defaults/templates/openrouter-kimi.yaml +30 -0
- forge/config/defaults/templates/openrouter-minimax.yaml +26 -0
- forge/config/defaults/templates/openrouter-openai-codex.yaml +23 -0
- forge/config/defaults/templates/openrouter-openai.yaml +28 -0
- forge/config/defaults/templates/openrouter-qwen.yaml +25 -0
- forge/config/loader.py +675 -0
- forge/config/schema.py +448 -0
- forge/core/__init__.py +5 -0
- forge/core/auth/__init__.py +67 -0
- forge/core/auth/capabilities.py +219 -0
- forge/core/auth/credentials_file.py +244 -0
- forge/core/auth/protocols.py +18 -0
- forge/core/auth/secrets.py +243 -0
- forge/core/auth/template_secrets.py +112 -0
- forge/core/data/__init__.py +5 -0
- forge/core/data/model_catalog.yaml +1522 -0
- forge/core/data/pricing.yaml +140 -0
- forge/core/data/system_prompt_addendums/__init__.py +0 -0
- forge/core/data/system_prompt_addendums/gemini.md +330 -0
- forge/core/data/system_prompt_addendums/openai.md +328 -0
- forge/core/llm/__init__.py +231 -0
- forge/core/llm/clients/__init__.py +14 -0
- forge/core/llm/clients/base.py +115 -0
- forge/core/llm/clients/litellm.py +619 -0
- forge/core/llm/clients/openai_compat.py +244 -0
- forge/core/llm/clients/openrouter.py +234 -0
- forge/core/llm/credentials.py +439 -0
- forge/core/llm/detection.py +86 -0
- forge/core/llm/errors.py +44 -0
- forge/core/llm/protocols.py +80 -0
- forge/core/llm/types.py +176 -0
- forge/core/logging.py +146 -0
- forge/core/models/__init__.py +91 -0
- forge/core/models/catalog.py +467 -0
- forge/core/models/pricing.py +165 -0
- forge/core/models/types.py +167 -0
- forge/core/naming.py +212 -0
- forge/core/ops/__init__.py +73 -0
- forge/core/ops/context.py +141 -0
- forge/core/ops/gc.py +802 -0
- forge/core/ops/proxy.py +146 -0
- forge/core/ops/resolution.py +135 -0
- forge/core/ops/session.py +344 -0
- forge/core/ops/session_context.py +548 -0
- forge/core/paths.py +38 -0
- forge/core/process.py +54 -0
- forge/core/reactive/__init__.py +38 -0
- forge/core/reactive/cost_tracking.py +300 -0
- forge/core/reactive/env.py +180 -0
- forge/core/reactive/proxy.py +78 -0
- forge/core/reactive/routing.py +622 -0
- forge/core/reactive/session_runner.py +185 -0
- forge/core/reactive/structured_output.py +62 -0
- forge/core/reactive/tagger.py +94 -0
- forge/core/reactive/throttle.py +132 -0
- forge/core/state/__init__.py +59 -0
- forge/core/state/exceptions.py +59 -0
- forge/core/state/io.py +140 -0
- forge/core/state/lock.py +99 -0
- forge/core/state/timestamps.py +60 -0
- forge/core/transcript.py +78 -0
- forge/core/typing_helpers.py +24 -0
- forge/core/workqueue/__init__.py +67 -0
- forge/core/workqueue/queue.py +552 -0
- forge/core/workqueue/types.py +63 -0
- forge/guard/__init__.py +26 -0
- forge/guard/deterministic/__init__.py +26 -0
- forge/guard/deterministic/base.py +158 -0
- forge/guard/deterministic/coding_standards.py +256 -0
- forge/guard/deterministic/registry.py +148 -0
- forge/guard/deterministic/tdd.py +171 -0
- forge/guard/engine.py +216 -0
- forge/guard/protocols.py +91 -0
- forge/guard/queries.py +96 -0
- forge/guard/semantic/__init__.py +34 -0
- forge/guard/semantic/promotion.py +18 -0
- forge/guard/semantic/supervisor.py +813 -0
- forge/guard/semantic/verdict.py +183 -0
- forge/guard/store.py +124 -0
- forge/guard/team/__init__.py +6 -0
- forge/guard/team/config.py +24 -0
- forge/guard/team/handlers.py +209 -0
- forge/guard/team/prompts.py +41 -0
- forge/guard/types.py +125 -0
- forge/guard/workflow/__init__.py +17 -0
- forge/guard/workflow/branches.py +67 -0
- forge/guard/workflow/config.py +63 -0
- forge/guard/workflow/divergence.py +113 -0
- forge/guard/workflow/policy.py +87 -0
- forge/guard/workflow/stages.py +205 -0
- forge/install/__init__.py +55 -0
- forge/install/cli.py +281 -0
- forge/install/exceptions.py +163 -0
- forge/install/hooks.py +109 -0
- forge/install/installer.py +1037 -0
- forge/install/models.py +321 -0
- forge/install/preset.py +272 -0
- forge/install/settings_merge.py +831 -0
- forge/install/tracking.py +238 -0
- forge/install/version.py +141 -0
- forge/proxy/__init__.py +0 -0
- forge/proxy/base_client.py +181 -0
- forge/proxy/client_adapter.py +476 -0
- forge/proxy/client_factory.py +531 -0
- forge/proxy/converters.py +1206 -0
- forge/proxy/cost_logger.py +132 -0
- forge/proxy/cost_tracker.py +242 -0
- forge/proxy/data_models.py +338 -0
- forge/proxy/error_hints.py +92 -0
- forge/proxy/metrics.py +222 -0
- forge/proxy/model_spec.py +158 -0
- forge/proxy/proxies.py +333 -0
- forge/proxy/proxy_identity.py +134 -0
- forge/proxy/proxy_orchestrator.py +1018 -0
- forge/proxy/proxy_startup.py +54 -0
- forge/proxy/server.py +1561 -0
- forge/proxy/utils.py +537 -0
- forge/review/__init__.py +6 -0
- forge/review/adversarial.py +111 -0
- forge/review/consensus.py +236 -0
- forge/review/engine.py +356 -0
- forge/review/models.py +437 -0
- forge/review/resources/__init__.py +5 -0
- forge/review/resources/codereview-performance.md +85 -0
- forge/review/resources/codereview-quick.md +75 -0
- forge/review/resources/codereview-security.md +92 -0
- forge/review/resources/codereview.md +85 -0
- forge/review/resources/docreview-quick.md +75 -0
- forge/review/resources/docreview.md +86 -0
- forge/review/resources/thinkdeep.md +89 -0
- forge/review/routing.py +368 -0
- forge/review/synthesis.py +73 -0
- forge/runtime_config.py +438 -0
- forge/search/__init__.py +55 -0
- forge/search/bm25_store.py +264 -0
- forge/search/content_store.py +197 -0
- forge/search/engine.py +352 -0
- forge/search/exceptions.py +51 -0
- forge/search/extractor.py +234 -0
- forge/search/index_state.py +295 -0
- forge/search/store.py +215 -0
- forge/search/tokenizer.py +24 -0
- forge/session/__init__.py +130 -0
- forge/session/active.py +339 -0
- forge/session/artifacts.py +202 -0
- forge/session/claude/__init__.py +50 -0
- forge/session/claude/cleanup.py +105 -0
- forge/session/claude/invoke.py +236 -0
- forge/session/claude/paths.py +200 -0
- forge/session/cleanup.py +216 -0
- forge/session/config.py +34 -0
- forge/session/direct_model.py +107 -0
- forge/session/effective.py +169 -0
- forge/session/exceptions.py +255 -0
- forge/session/handoff.py +881 -0
- forge/session/handoff_agent.py +544 -0
- forge/session/hooks/__init__.py +35 -0
- forge/session/hooks/models.py +73 -0
- forge/session/hooks/session_start.py +507 -0
- forge/session/identity.py +84 -0
- forge/session/index.py +553 -0
- forge/session/manager.py +1506 -0
- forge/session/models.py +572 -0
- forge/session/overrides.py +344 -0
- forge/session/plan_resolution.py +286 -0
- forge/session/prev_sessions.py +128 -0
- forge/session/store.py +431 -0
- forge/session/validation.py +47 -0
- forge/session/worktree/__init__.py +65 -0
- forge/session/worktree/cleanup.py +262 -0
- forge/session/worktree/config_copy.py +203 -0
- forge/session/worktree/create.py +332 -0
- forge/sidecar/__init__.py +29 -0
- forge/sidecar/container.py +161 -0
- forge/sidecar/docker.py +86 -0
- forge/sidecar/secrets.py +19 -0
- multi_forge-0.2.0.dist-info/METADATA +242 -0
- multi_forge-0.2.0.dist-info/RECORD +311 -0
- multi_forge-0.2.0.dist-info/WHEEL +4 -0
- multi_forge-0.2.0.dist-info/entry_points.txt +2 -0
- multi_forge-0.2.0.dist-info/licenses/LICENSE +203 -0
- multi_forge-0.2.0.dist-info/licenses/NOTICE +14 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
<!-- prereq: 0.3 -->
|
|
2
|
+
|
|
3
|
+
## 17. System Info
|
|
4
|
+
|
|
5
|
+
### 17.1 `forge info`
|
|
6
|
+
|
|
7
|
+
<!-- auto -->
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
forge info
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
- [ ] Shows Forge version
|
|
14
|
+
- [ ] Shows installation status
|
|
15
|
+
- [ ] Shows proxy status
|
|
16
|
+
- [ ] Shows active session (if any)
|
|
17
|
+
|
|
18
|
+
### 17.2 Debug Logging and `forge logs`
|
|
19
|
+
|
|
20
|
+
<!-- human:confirm -->
|
|
21
|
+
|
|
22
|
+
Run a Forge command with debug logging enabled, then use `forge logs` to inspect and clean up log files.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Run a command with debug logging
|
|
26
|
+
FORGE_DEBUG=1 forge info
|
|
27
|
+
|
|
28
|
+
# Show log locations and file counts
|
|
29
|
+
forge logs
|
|
30
|
+
|
|
31
|
+
# Verify logs were written
|
|
32
|
+
forge logs
|
|
33
|
+
# Expected: shows log directory path and file count > 0
|
|
34
|
+
|
|
35
|
+
# Clean up logs
|
|
36
|
+
forge logs --clean
|
|
37
|
+
|
|
38
|
+
# Verify cleanup
|
|
39
|
+
forge logs
|
|
40
|
+
# Expected: reports 0 log files when no Forge processes are running.
|
|
41
|
+
# If QA proxies are still running, active proxy logs may be retained.
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- [ ] `FORGE_DEBUG=1` enables debug logging (no crash, no error)
|
|
45
|
+
- [ ] `forge logs` shows log directory location and file counts
|
|
46
|
+
- [ ] Log files were actually written (count > 0 after debug run)
|
|
47
|
+
- [ ] `forge logs --clean` removes stale log files
|
|
48
|
+
- [ ] After cleanup, `forge logs` reports 0 files, or only logs for currently running Forge proxy processes
|
|
49
|
+
|
|
50
|
+
---
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<!-- prereq: 0.3, 2.4 -->
|
|
2
|
+
|
|
3
|
+
## 18. Uninstallation (Incremental)
|
|
4
|
+
|
|
5
|
+
Test uninstalling individual scopes before the complete uninstall.
|
|
6
|
+
|
|
7
|
+
### 18.1 Uninstall Local Scope Only
|
|
8
|
+
|
|
9
|
+
<!-- auto -->
|
|
10
|
+
|
|
11
|
+
<!-- destructive -->
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
cd $FORGE_TEST_REPO
|
|
15
|
+
|
|
16
|
+
# Uninstall only the local scope
|
|
17
|
+
forge extension disable --scope local
|
|
18
|
+
|
|
19
|
+
# (Optional) Uninstall hooks-only path, if you used it
|
|
20
|
+
forge hook disable --local
|
|
21
|
+
|
|
22
|
+
# Verify local removal
|
|
23
|
+
ls .claude/commands/ # Should be empty or removed
|
|
24
|
+
cat .claude/settings.local.json | jq '.hooks' # Should have no Forge hooks
|
|
25
|
+
|
|
26
|
+
# Verify user scope STILL installed
|
|
27
|
+
ls ~/.claude/commands/ # Should still have Forge commands
|
|
28
|
+
cat ~/.claude/settings.json | jq '.hooks' # Should still have Forge hooks
|
|
29
|
+
|
|
30
|
+
# Check tracking
|
|
31
|
+
cat ~/.forge/installed.json | jq '.installations | keys'
|
|
32
|
+
# Should show only ["user"], not the local:... key
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- [ ] Local commands removed
|
|
36
|
+
- [ ] Local hooks removed from settings.local.json
|
|
37
|
+
- [ ] User scope commands still present
|
|
38
|
+
- [ ] User scope hooks still present
|
|
39
|
+
- [ ] Tracking shows only "user" key
|
|
40
|
+
|
|
41
|
+
### 18.2 Verify Pre-Existing Settings Restored (Local)
|
|
42
|
+
|
|
43
|
+
<!-- auto -->
|
|
44
|
+
|
|
45
|
+
<!-- destructive -->
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# CRITICAL: Check that user's original settings survived uninstall
|
|
49
|
+
cat .claude/settings.local.json | jq '.'
|
|
50
|
+
|
|
51
|
+
# Original permissions should still be there
|
|
52
|
+
cat .claude/settings.local.json | jq '.permissions.allow'
|
|
53
|
+
# Should show: ["Bash(npm test)", "Bash(uv run pytest*)"]
|
|
54
|
+
|
|
55
|
+
# Custom env var should still be there
|
|
56
|
+
cat .claude/settings.local.json | jq '.env.MY_CUSTOM_VAR'
|
|
57
|
+
# Should show: "should-survive-forge"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- [ ] Original `permissions.allow` entries preserved
|
|
61
|
+
- [ ] `env.MY_CUSTOM_VAR` still present
|
|
62
|
+
- [ ] Forge-added hooks removed; Forge-added permissions (Write, Edit) removed
|
|
63
|
+
- [ ] User-approved permissions (e.g., `Bash(forge workflow:*)`) may remain -- these are Claude Code auto-learned, not
|
|
64
|
+
Forge-managed
|
|
65
|
+
|
|
66
|
+
### 18.3 Re-install Local for Complete Test
|
|
67
|
+
|
|
68
|
+
<!-- auto -->
|
|
69
|
+
|
|
70
|
+
<!-- destructive -->
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Re-install local scope so we can test complete uninstall
|
|
74
|
+
forge extension enable --scope local
|
|
75
|
+
|
|
76
|
+
# Verify both scopes installed again
|
|
77
|
+
cat ~/.forge/installed.json | jq '.installations | keys'
|
|
78
|
+
# Should show: ["user", "local:/Users/..."]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- [ ] Local scope re-installed
|
|
82
|
+
- [ ] Both installations tracked
|
|
83
|
+
|
|
84
|
+
---
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<!-- prereq: 0.3, 2.4, 18 -->
|
|
2
|
+
|
|
3
|
+
## 19. Complete Uninstallation (setup.sh --uninstall)
|
|
4
|
+
|
|
5
|
+
This tests the curl-installable uninstall that removes EVERYTHING.
|
|
6
|
+
|
|
7
|
+
### 19.1 Pre-Uninstall State Verification
|
|
8
|
+
|
|
9
|
+
<!-- auto -->
|
|
10
|
+
|
|
11
|
+
<!-- destructive -->
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Verify we have both installations
|
|
15
|
+
cat ~/.forge/installed.json | jq '.installations | keys'
|
|
16
|
+
# Should show: ["user", "local:$FORGE_TEST_REPO"]
|
|
17
|
+
|
|
18
|
+
# Verify artifacts exist
|
|
19
|
+
ls ~/.forge/ # Should exist
|
|
20
|
+
ls ~/.forge/bin/forge # Should exist
|
|
21
|
+
ls ~/.claude/commands/ # Should have Forge commands
|
|
22
|
+
ls .claude/commands/ # Should have Forge commands (local)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- [ ] Both user and local installations tracked
|
|
26
|
+
- [ ] `~/.forge/` exists
|
|
27
|
+
- [ ] User scope has Forge files
|
|
28
|
+
- [ ] Local scope has Forge files
|
|
29
|
+
|
|
30
|
+
### 19.2 Run Complete Uninstall
|
|
31
|
+
|
|
32
|
+
<!-- auto -->
|
|
33
|
+
|
|
34
|
+
<!-- destructive -->
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# Run the uninstall script using the local copy
|
|
38
|
+
~/.forge/repo/scripts/setup.sh --uninstall
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The script attempts to remove extensions via Forge CLI:
|
|
42
|
+
|
|
43
|
+
- `forge extension disable --all --force` (remove tracked extensions)
|
|
44
|
+
|
|
45
|
+
Then it removes `~/.forge/` and other artifacts.
|
|
46
|
+
|
|
47
|
+
- [ ] Script runs without errors
|
|
48
|
+
- [ ] ALL scopes uninstalled (via `forge extension disable --all --force` or equivalent)
|
|
49
|
+
- [ ] Shows "Found N Forge installation(s)" summary (if forge available)
|
|
50
|
+
- [ ] `~/.forge/` removed
|
|
51
|
+
- [ ] `~/.forge/sessions/` removed (Forge session data)
|
|
52
|
+
- [ ] Docker images removed (multi-forge-\*)
|
|
53
|
+
- [ ] Shell profile cleaned (block markers removed)
|
|
54
|
+
|
|
55
|
+
### 19.3 Verify Complete Removal
|
|
56
|
+
|
|
57
|
+
<!-- auto -->
|
|
58
|
+
|
|
59
|
+
<!-- destructive -->
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Verify ~/.forge/ is gone
|
|
63
|
+
ls ~/.forge/ 2>/dev/null || echo "~/.forge/ removed"
|
|
64
|
+
|
|
65
|
+
# Verify forge not on PATH (need new terminal or source profile)
|
|
66
|
+
# source ~/.zshrc # or restart terminal
|
|
67
|
+
# which forge # Should fail or show nothing
|
|
68
|
+
|
|
69
|
+
# Verify no Forge hooks in global settings
|
|
70
|
+
cat ~/.claude/settings.json | jq '.hooks'
|
|
71
|
+
# Should be null or empty of Forge entries
|
|
72
|
+
|
|
73
|
+
# Verify user commands removed
|
|
74
|
+
ls ~/.claude/commands/ 2>/dev/null | grep -v "^$" || echo "User commands removed"
|
|
75
|
+
ls ~/.claude/agents/ 2>/dev/null | grep -v "^$" || echo "User agents removed"
|
|
76
|
+
ls ~/.claude/skills/ 2>/dev/null | grep -v "^$" || echo "User skills removed"
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
- [ ] `~/.forge/` directory removed
|
|
80
|
+
- [ ] Forge hooks removed from `~/.claude/settings.json`
|
|
81
|
+
- [ ] User commands/agents/skills removed
|
|
82
|
+
|
|
83
|
+
### 19.4 Verify Local Project Settings Preserved
|
|
84
|
+
|
|
85
|
+
<!-- auto -->
|
|
86
|
+
|
|
87
|
+
<!-- destructive -->
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
cd $FORGE_TEST_REPO
|
|
91
|
+
|
|
92
|
+
# CRITICAL: Local pre-existing settings should survive
|
|
93
|
+
cat .claude/settings.local.json | jq '.'
|
|
94
|
+
|
|
95
|
+
# Original permissions should still be there
|
|
96
|
+
cat .claude/settings.local.json | jq '.permissions.allow'
|
|
97
|
+
# Should show: ["Bash(npm test)", "Bash(uv run pytest*)"]
|
|
98
|
+
|
|
99
|
+
# Custom env var should still be there
|
|
100
|
+
cat .claude/settings.local.json | jq '.env.MY_CUSTOM_VAR'
|
|
101
|
+
# Should show: "should-survive-forge"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- [ ] `.claude/settings.local.json` still exists
|
|
105
|
+
- [ ] Original permissions preserved
|
|
106
|
+
- [ ] `env.MY_CUSTOM_VAR` preserved
|
|
107
|
+
- [ ] Forge-added entries (hooks, Write/Edit permissions, env) removed; user-approved permissions (e.g.,
|
|
108
|
+
`Bash(forge workflow:*)`) may remain
|
|
109
|
+
|
|
110
|
+
### 19.5 Verify Shell Profile Cleaned
|
|
111
|
+
|
|
112
|
+
<!-- auto -->
|
|
113
|
+
|
|
114
|
+
<!-- destructive -->
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# Check that block markers were removed from any shell profile Forge may touch.
|
|
118
|
+
PROFILES=("$HOME/.bashrc" "$HOME/.bash_profile" "$HOME/.zshrc" "$HOME/.config/fish/config.fish")
|
|
119
|
+
FOUND_PROFILE=0
|
|
120
|
+
FOUND_BACKUP=0
|
|
121
|
+
|
|
122
|
+
for profile in "${PROFILES[@]}"; do
|
|
123
|
+
if [ -f "$profile" ]; then
|
|
124
|
+
FOUND_PROFILE=1
|
|
125
|
+
echo "Checking $profile"
|
|
126
|
+
grep -n ">>> multi-forge >>>" "$profile" && exit 1 || true
|
|
127
|
+
grep -n "$HOME/.forge/bin" "$profile" && exit 1 || true
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
if [ -f "$profile.forge-uninstall-backup" ]; then
|
|
131
|
+
FOUND_BACKUP=1
|
|
132
|
+
echo "Backup exists: $profile.forge-uninstall-backup"
|
|
133
|
+
fi
|
|
134
|
+
done
|
|
135
|
+
|
|
136
|
+
echo "profiles_found=$FOUND_PROFILE backups_found=$FOUND_BACKUP"
|
|
137
|
+
if [ "$FOUND_PROFILE" -eq 0 ]; then
|
|
138
|
+
echo "No shell profile exists in this container; profile cleanup is N/A."
|
|
139
|
+
fi
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
- [ ] No `>>> multi-forge >>>` block remains in any existing shell profile
|
|
143
|
+
- [ ] No `.forge/bin` PATH entry remains in any existing shell profile
|
|
144
|
+
- [ ] Backup file exists for any profile that was modified; if no shell profile exists, profile cleanup is N/A
|
|
145
|
+
|
|
146
|
+
---
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
<!-- prereq: 0.3, 1.1 -->
|
|
2
|
+
|
|
3
|
+
## 2. Claude Code Extensions (`forge extension enable`)
|
|
4
|
+
|
|
5
|
+
### 2.1 Basic Installation (User Scope)
|
|
6
|
+
|
|
7
|
+
<!-- auto -->
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Install forge extensions (default: standard profile, user scope)
|
|
11
|
+
cd $FORGE_TEST_REPO
|
|
12
|
+
forge extension enable --scope user --symlink
|
|
13
|
+
|
|
14
|
+
# Optional: preview changes instead of applying
|
|
15
|
+
forge extension enable --scope user --dry-run
|
|
16
|
+
|
|
17
|
+
# Verify installation
|
|
18
|
+
ls -la $CLAUDE_HOME/skills/
|
|
19
|
+
cat $CLAUDE_HOME/settings.json | jq '.hooks'
|
|
20
|
+
cat $FORGE_HOME/installed.json | jq '.installations.user.modules_enabled'
|
|
21
|
+
|
|
22
|
+
# Optional: confirm status line + permissions were merged (user scope)
|
|
23
|
+
cat $CLAUDE_HOME/settings.json | jq '.statusLine'
|
|
24
|
+
cat $CLAUDE_HOME/settings.json | jq '.permissions'
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
- [ ] `modules_enabled` in `installed.json` lists `commands` and `agents` (directories created only if source has
|
|
28
|
+
installable files)
|
|
29
|
+
- [ ] Skills installed to `$CLAUDE_HOME/skills/` (standard profile)
|
|
30
|
+
- [ ] Hooks configured in `$CLAUDE_HOME/settings.json` (or in `$CLAUDE_HOME/settings.local.json` if you used hooks-only
|
|
31
|
+
install)
|
|
32
|
+
- [ ] `$FORGE_HOME/installed.json` tracking file created
|
|
33
|
+
|
|
34
|
+
### 2.2 Verify Installed Content
|
|
35
|
+
|
|
36
|
+
<!-- auto -->
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Check what was installed
|
|
40
|
+
cat $FORGE_HOME/installed.json | jq '.'
|
|
41
|
+
|
|
42
|
+
# Verify user-scope status line setting
|
|
43
|
+
cat $CLAUDE_HOME/settings.json | jq '.statusLine'
|
|
44
|
+
|
|
45
|
+
# Verify user-scope permissions
|
|
46
|
+
cat $CLAUDE_HOME/settings.json | jq '.permissions'
|
|
47
|
+
|
|
48
|
+
# Verify skills are installed
|
|
49
|
+
ls $CLAUDE_HOME/skills/
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- [ ] `installed.json` lists all installed files
|
|
53
|
+
- [ ] `statusLine` points to `forge status-line`
|
|
54
|
+
- [ ] Permissions include Forge-required entries
|
|
55
|
+
- [ ] Skills directory contains skill folders (analyze, debate, panel, review, review-docs, etc.)
|
|
56
|
+
|
|
57
|
+
### 2.3 Verify Pre-Existing Settings Preserved
|
|
58
|
+
|
|
59
|
+
<!-- auto -->
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Check that user's original settings survived installation
|
|
63
|
+
cat .claude/settings.local.json | jq '.'
|
|
64
|
+
|
|
65
|
+
# Verify original permissions still present (merged, not replaced)
|
|
66
|
+
cat .claude/settings.local.json | jq '.permissions.allow'
|
|
67
|
+
# Should include BOTH:
|
|
68
|
+
# - Original: "Bash(npm test)", "Bash(uv run pytest*)"
|
|
69
|
+
# - Forge-added permissions (if any added to local scope)
|
|
70
|
+
|
|
71
|
+
# Verify custom env var preserved
|
|
72
|
+
cat .claude/settings.local.json | jq '.env.MY_CUSTOM_VAR'
|
|
73
|
+
# Should show: "should-survive-forge"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
- [ ] Original `permissions.allow` entries preserved
|
|
77
|
+
- [ ] `env.MY_CUSTOM_VAR` still present
|
|
78
|
+
- [ ] Forge merged settings, didn't replace
|
|
79
|
+
|
|
80
|
+
### 2.4 Install Local Scope
|
|
81
|
+
|
|
82
|
+
<!-- auto -->
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# Install Forge extensions to LOCAL scope (this project only)
|
|
86
|
+
cd $FORGE_TEST_REPO
|
|
87
|
+
forge extension enable --scope local
|
|
88
|
+
|
|
89
|
+
# Verify local installation
|
|
90
|
+
cat .claude/settings.local.json | jq '.hooks'
|
|
91
|
+
LOCAL_KEY="local:$(cd "$FORGE_TEST_REPO" && pwd -P)"
|
|
92
|
+
cat $FORGE_HOME/installed.json | jq --arg key "$LOCAL_KEY" '.installations[$key].modules_enabled'
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- [ ] `modules_enabled` for local installation lists `commands` and `agents` (directories created only if source has
|
|
96
|
+
installable files)
|
|
97
|
+
- [ ] Hooks configured in `.claude/settings.local.json`
|
|
98
|
+
|
|
99
|
+
### 2.5 Verify Both Installations Tracked
|
|
100
|
+
|
|
101
|
+
<!-- auto -->
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Check tracking file shows BOTH installations
|
|
105
|
+
LOCAL_KEY="local:$(cd "$FORGE_TEST_REPO" && pwd -P)"
|
|
106
|
+
cat $FORGE_HOME/installed.json | jq '.installations | keys'
|
|
107
|
+
printf 'Expected local key: %s\n' "$LOCAL_KEY"
|
|
108
|
+
|
|
109
|
+
# Show user installation
|
|
110
|
+
cat $FORGE_HOME/installed.json | jq '.installations.user.scope'
|
|
111
|
+
# Should show: "user"
|
|
112
|
+
|
|
113
|
+
# Show local installation (note the key format with path)
|
|
114
|
+
cat $FORGE_HOME/installed.json | jq --arg key "$LOCAL_KEY" '.installations[$key].scope'
|
|
115
|
+
# Should show: "local"
|
|
116
|
+
|
|
117
|
+
# Verify project_path is tracked
|
|
118
|
+
cat $FORGE_HOME/installed.json | jq --arg key "$LOCAL_KEY" '.installations[$key].project_path'
|
|
119
|
+
# Should show the resolved path part of LOCAL_KEY
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
- [ ] Tracking shows "user" key
|
|
123
|
+
- [ ] Tracking shows "local:/path/to/project" key
|
|
124
|
+
- [ ] Both installations tracked separately
|
|
125
|
+
- [ ] project_path field populated for local installation
|
|
126
|
+
|
|
127
|
+
### 2.6 Test Double-Install Prevention
|
|
128
|
+
|
|
129
|
+
<!-- auto -->
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Try to install local again to same project
|
|
133
|
+
forge extension enable --scope local
|
|
134
|
+
|
|
135
|
+
# Should either:
|
|
136
|
+
# - Say "already installed" and skip
|
|
137
|
+
# - Or update existing installation (idempotent)
|
|
138
|
+
|
|
139
|
+
# Verify only ONE local entry in tracking
|
|
140
|
+
cat $FORGE_HOME/installed.json | jq '.installations | keys | length'
|
|
141
|
+
# Should show 2 (user + 1 local), not 3
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
- [ ] Re-running `forge extension enable --scope local` is idempotent
|
|
145
|
+
- [ ] No duplicate entries in tracking
|
|
146
|
+
|
|
147
|
+
### 2.7 Check Install Status (Nearest Scope)
|
|
148
|
+
|
|
149
|
+
<!-- auto -->
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
cd $FORGE_TEST_REPO
|
|
153
|
+
|
|
154
|
+
# Status for the nearest installation (auto-detects local/project/user)
|
|
155
|
+
forge extension status
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
- [ ] `forge extension status` succeeds
|
|
159
|
+
- [ ] Shows detected scope + profile/modules summary
|
|
160
|
+
|
|
161
|
+
### 2.8 Check Install Status (All Scopes)
|
|
162
|
+
|
|
163
|
+
<!-- auto -->
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
cd $FORGE_TEST_REPO
|
|
167
|
+
|
|
168
|
+
# Show user + project + local scopes
|
|
169
|
+
forge extension status --all
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
- [ ] Shows all three scopes (user/project/local)
|
|
173
|
+
- [ ] Missing scopes are shown as "Not installed" (does not error)
|
|
174
|
+
|
|
175
|
+
### 2.9 Update Installation (Idempotent)
|
|
176
|
+
|
|
177
|
+
<!-- auto -->
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
cd $FORGE_TEST_REPO
|
|
181
|
+
|
|
182
|
+
# Update the nearest installation (auto-detects)
|
|
183
|
+
forge extension sync
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
- [ ] Update completes (or reports already up to date)
|
|
187
|
+
|
|
188
|
+
---
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
## 20. Cleanup
|
|
2
|
+
|
|
3
|
+
### 20.1 Cleanup Test Artifacts
|
|
4
|
+
|
|
5
|
+
<!-- auto -->
|
|
6
|
+
|
|
7
|
+
<!-- destructive -->
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Clean up test sessions and artifacts, but preserve the QA state mount
|
|
11
|
+
rm -rf .forge/sessions/ .forge/artifacts/ .forge/prev_sessions/ .forge/search-index/
|
|
12
|
+
|
|
13
|
+
# Remove shell profile backups (optional)
|
|
14
|
+
rm -f \
|
|
15
|
+
~/.bashrc.forge-uninstall-backup \
|
|
16
|
+
~/.bash_profile.forge-uninstall-backup \
|
|
17
|
+
~/.zshrc.forge-uninstall-backup \
|
|
18
|
+
~/.config/fish/config.fish.forge-uninstall-backup
|
|
19
|
+
|
|
20
|
+
# Remove QA cost fixture logs (safe: only QA-owned fixture names)
|
|
21
|
+
rm -f ~/.forge/costs/requests/qa-fixture_*.jsonl
|
|
22
|
+
rm -f ~/.forge/costs/verbs/qa-fixture_*.jsonl
|
|
23
|
+
rm -f ~/.forge/costs/requests/*_qa-cap-seed.jsonl
|
|
24
|
+
|
|
25
|
+
# Remove test repo entirely (optional)
|
|
26
|
+
# cd .. && rm -rf manual-testing/walkthrough/test-repo
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
- [ ] `.forge/sessions/` removed (or did not exist)
|
|
30
|
+
- [ ] `.forge/qa/` preserved (QA state mount -- do NOT delete)
|
|
31
|
+
- [ ] Shell profile backup removed (if existed)
|
|
32
|
+
- [ ] QA cost fixture logs removed from `~/.forge/costs/requests/` (no `qa-fixture_*.jsonl`)
|
|
33
|
+
- [ ] QA cost fixture logs removed from `~/.forge/costs/verbs/` (no `qa-fixture_*.jsonl`)
|
|
34
|
+
- [ ] QA cap seed logs removed from `~/.forge/costs/requests/` (no `*_qa-cap-seed.jsonl`)
|
|
35
|
+
|
|
36
|
+
---
|