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,174 @@
|
|
|
1
|
+
<!-- prereq: 0.3, 2.1, 5.1 -->
|
|
2
|
+
|
|
3
|
+
## 8. Status Line
|
|
4
|
+
|
|
5
|
+
### 8.1 Direct Invocation
|
|
6
|
+
|
|
7
|
+
<!-- human:confirm -->
|
|
8
|
+
|
|
9
|
+
This is a rendered status-line smoke test. It does not call Claude or an LLM; it feeds a synthetic Claude Code
|
|
10
|
+
`statusLine` JSON payload into `forge status-line` and asks you to review the terminal-facing output.
|
|
11
|
+
|
|
12
|
+
Expected visible shape, with colors/spaces rendered by the terminal:
|
|
13
|
+
|
|
14
|
+
```text
|
|
15
|
+
${FORGE_TEST_REPO} (main) | test-session-1
|
|
16
|
+
[Opus 4.6] -------- 6%/200K | 3m | +12/-3 | in:28.0K out:17.5K
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
The output may wrap to two physical terminal lines. A proxy template/tier prefix is expected only when
|
|
20
|
+
`ANTHROPIC_BASE_URL` points at a live or registered Forge proxy; if `test-session-1` was started without a proxy, no
|
|
21
|
+
proxy segment is expected here.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
cd $FORGE_TEST_REPO
|
|
25
|
+
|
|
26
|
+
# Mirror Claude Code's statusLine JSON contract and the Forge launch env.
|
|
27
|
+
BASE_URL=$(jq -r '.intent.proxy.base_url // empty' .forge/sessions/test-session-1/forge.session.json)
|
|
28
|
+
mkdir -p .forge/walkthrough
|
|
29
|
+
cat > .forge/walkthrough/status-line-transcript.jsonl <<EOF
|
|
30
|
+
{"requestId":"req-001","message":{"role":"user","content":[{"type":"text","text":"Read the config file."}]}}
|
|
31
|
+
{"requestId":"req-001","message":{"role":"assistant","content":[{"type":"text","text":"I'll inspect it."},{"type":"tool_use","id":"tool-001","name":"Read","input":{"file_path":"${FORGE_TEST_REPO}/config.yaml"}}]}}
|
|
32
|
+
{"requestId":"req-001","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"tool-001","content":"timeout: 10"}]}}
|
|
33
|
+
{"requestId":"req-002","message":{"role":"user","content":[{"type":"text","text":"Update the timeout and run tests."}]}}
|
|
34
|
+
{"requestId":"req-002","message":{"role":"assistant","content":[{"type":"tool_use","id":"tool-002","name":"Edit","input":{"file_path":"${FORGE_TEST_REPO}/config.yaml"}},{"type":"tool_use","id":"tool-003","name":"Bash","input":{"command":"uv run pytest"}}]}}
|
|
35
|
+
EOF
|
|
36
|
+
STATUS_INPUT=$(jq -nc \
|
|
37
|
+
--arg cwd "$FORGE_TEST_REPO" \
|
|
38
|
+
--arg transcript "$FORGE_TEST_REPO/.forge/walkthrough/status-line-transcript.jsonl" \
|
|
39
|
+
'{
|
|
40
|
+
workspace: {current_dir: $cwd},
|
|
41
|
+
model: {display_name: "Opus 4.6"},
|
|
42
|
+
transcript_path: $transcript,
|
|
43
|
+
context_window: {
|
|
44
|
+
context_window_size: 200000,
|
|
45
|
+
used_percentage: 6,
|
|
46
|
+
total_input_tokens: 28000,
|
|
47
|
+
total_output_tokens: 17500,
|
|
48
|
+
current_usage: {
|
|
49
|
+
input_tokens: 8500,
|
|
50
|
+
cache_creation_input_tokens: 2000,
|
|
51
|
+
cache_read_input_tokens: 1500
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
cost: {
|
|
55
|
+
total_duration_ms: 185000,
|
|
56
|
+
total_lines_added: 12,
|
|
57
|
+
total_lines_removed: 3
|
|
58
|
+
}
|
|
59
|
+
}')
|
|
60
|
+
|
|
61
|
+
echo "$STATUS_INPUT" \
|
|
62
|
+
| FORGE_SESSION=test-session-1 ANTHROPIC_BASE_URL="$BASE_URL" forge status-line
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
- [ ] Shows compact workspace path, git branch, and `test-session-1`
|
|
66
|
+
- [ ] Shows `[Opus 4.6]` plus context usage `6%/200K` with a visible progress bar
|
|
67
|
+
- [ ] Shows seeded metrics: `3m`, `+12/-3`, `in:28.0K`, and `out:17.5K`
|
|
68
|
+
- [ ] If `ANTHROPIC_BASE_URL` belongs to a created/running proxy, also shows proxy template/tier info
|
|
69
|
+
- [ ] Does not print raw JSON, a Python traceback, or `[Error: ...]`
|
|
70
|
+
- [ ] ANSI/color and non-breaking-space internals are checked in 8.2, not by this rendered review
|
|
71
|
+
|
|
72
|
+
### 8.2 Verify Display Elements
|
|
73
|
+
|
|
74
|
+
<!-- human:confirm -->
|
|
75
|
+
|
|
76
|
+
The status line uses a category-based layout with 5 categories: Where, Who, What, Metrics, State. This step
|
|
77
|
+
intentionally pipes the output through `cat -v`, so the output will look ugly on purpose:
|
|
78
|
+
|
|
79
|
+
- non-breaking spaces show up as `M-BM-`
|
|
80
|
+
- ANSI escapes show up as `^[[...`
|
|
81
|
+
- colorized line-change segments and dimmed `in:` / `out:` / `cache:` labels still show their raw escapes
|
|
82
|
+
|
|
83
|
+
Rendered output is covered in 8.1. This step is only checking that the raw escapes and hardened spacing are present.
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
cd $FORGE_TEST_REPO
|
|
87
|
+
|
|
88
|
+
BASE_URL=$(jq -r '.intent.proxy.base_url // empty' .forge/sessions/test-session-1/forge.session.json)
|
|
89
|
+
mkdir -p .forge/walkthrough
|
|
90
|
+
cat > .forge/walkthrough/status-line-transcript.jsonl <<EOF
|
|
91
|
+
{"requestId":"req-001","message":{"role":"user","content":[{"type":"text","text":"Read the config file."}]}}
|
|
92
|
+
{"requestId":"req-001","message":{"role":"assistant","content":[{"type":"text","text":"I'll inspect it."},{"type":"tool_use","id":"tool-001","name":"Read","input":{"file_path":"${FORGE_TEST_REPO}/config.yaml"}}]}}
|
|
93
|
+
{"requestId":"req-001","message":{"role":"user","content":[{"type":"tool_result","tool_use_id":"tool-001","content":"timeout: 10"}]}}
|
|
94
|
+
{"requestId":"req-002","message":{"role":"user","content":[{"type":"text","text":"Update the timeout and run tests."}]}}
|
|
95
|
+
{"requestId":"req-002","message":{"role":"assistant","content":[{"type":"tool_use","id":"tool-002","name":"Edit","input":{"file_path":"${FORGE_TEST_REPO}/config.yaml"}},{"type":"tool_use","id":"tool-003","name":"Bash","input":{"command":"uv run pytest"}}]}}
|
|
96
|
+
EOF
|
|
97
|
+
STATUS_INPUT=$(jq -nc \
|
|
98
|
+
--arg cwd "$FORGE_TEST_REPO" \
|
|
99
|
+
--arg transcript "$FORGE_TEST_REPO/.forge/walkthrough/status-line-transcript.jsonl" \
|
|
100
|
+
'{
|
|
101
|
+
workspace: {current_dir: $cwd},
|
|
102
|
+
model: {display_name: "Opus 4.6 (200k context)"},
|
|
103
|
+
transcript_path: $transcript,
|
|
104
|
+
context_window: {
|
|
105
|
+
context_window_size: 200000,
|
|
106
|
+
used_percentage: 6,
|
|
107
|
+
total_input_tokens: 28000,
|
|
108
|
+
total_output_tokens: 17500,
|
|
109
|
+
current_usage: {
|
|
110
|
+
input_tokens: 8500,
|
|
111
|
+
cache_creation_input_tokens: 2000,
|
|
112
|
+
cache_read_input_tokens: 1500
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
cost: {
|
|
116
|
+
total_duration_ms: 185000,
|
|
117
|
+
total_lines_added: 12,
|
|
118
|
+
total_lines_removed: 3
|
|
119
|
+
}
|
|
120
|
+
}')
|
|
121
|
+
|
|
122
|
+
# Pipe through cat -v to inspect raw ANSI escapes and NBSP rendering.
|
|
123
|
+
# Expected: ugly raw output, not a pretty status line.
|
|
124
|
+
echo "$STATUS_INPUT" \
|
|
125
|
+
| FORGE_SESSION=test-session-1 ANTHROPIC_BASE_URL="$BASE_URL" forge status-line 2>&1 | cat -v
|
|
126
|
+
# Check for non-breaking spaces (M-BM-), ANSI codes (^[[...),
|
|
127
|
+
# and ASCII indicators/progress-bar text rather than rendered terminal styling.
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
- [ ] Shows ANSI-colored ASCII segments in raw `cat -v` form
|
|
131
|
+
- [ ] Shows model name (cleaned, without redundant context info)
|
|
132
|
+
- [ ] Uses non-breaking spaces (prevents VSCode trimming)
|
|
133
|
+
- [ ] ANSI reset prefix present
|
|
134
|
+
|
|
135
|
+
### 8.3 Breadcrumb Display (for resumed sessions)
|
|
136
|
+
|
|
137
|
+
<!-- human:confirm -->
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
cd $FORGE_TEST_REPO
|
|
141
|
+
|
|
142
|
+
# Create a disposable derived-looking session so this step does not depend on section 10.
|
|
143
|
+
forge session delete test-session-breadcrumb --force 2>/dev/null || true
|
|
144
|
+
forge session start test-session-breadcrumb --no-launch >/dev/null
|
|
145
|
+
|
|
146
|
+
cat .forge/sessions/test-session-breadcrumb/forge.session.json \
|
|
147
|
+
| jq '.confirmed.derivation = {
|
|
148
|
+
"parent_session": "test-session-1",
|
|
149
|
+
"parent_transcript": ".forge/artifacts/test-session-1/transcript.jsonl",
|
|
150
|
+
"inherited_proxy": null,
|
|
151
|
+
"strategy": "minimal",
|
|
152
|
+
"depth": 1,
|
|
153
|
+
"resumed_at": "2026-03-16T00:00:00Z",
|
|
154
|
+
"lineage": ["test-session-1"]
|
|
155
|
+
}' > /tmp/test-session-breadcrumb.json && \
|
|
156
|
+
mv /tmp/test-session-breadcrumb.json .forge/sessions/test-session-breadcrumb/forge.session.json
|
|
157
|
+
|
|
158
|
+
BASE_URL=$(jq -r '.intent.proxy.base_url // empty' .forge/sessions/test-session-breadcrumb/forge.session.json)
|
|
159
|
+
STATUS_INPUT=$(jq -nc \
|
|
160
|
+
--arg cwd "$FORGE_TEST_REPO" \
|
|
161
|
+
'{
|
|
162
|
+
workspace: {current_dir: $cwd},
|
|
163
|
+
model: {display_name: "Opus 4.6"}
|
|
164
|
+
}')
|
|
165
|
+
|
|
166
|
+
echo "$STATUS_INPUT" \
|
|
167
|
+
| FORGE_SESSION=test-session-breadcrumb ANTHROPIC_BASE_URL="$BASE_URL" forge status-line 2>/dev/null
|
|
168
|
+
|
|
169
|
+
forge session delete test-session-breadcrumb --force >/dev/null
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
- [ ] Shows session lineage breadcrumb (for example `test-session-1 > test-session-breadcrumb`)
|
|
173
|
+
|
|
174
|
+
---
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<!-- prereq: 0.3, 2.1, 5.1 -->
|
|
2
|
+
|
|
3
|
+
## 9. Direct Commands (% commands)
|
|
4
|
+
|
|
5
|
+
### 9.1 Test %help
|
|
6
|
+
|
|
7
|
+
<!-- auto -->
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# Simulate UserPromptSubmit with %help
|
|
11
|
+
echo '{"prompt": "%help"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- [ ] Returns help text listing available commands
|
|
15
|
+
|
|
16
|
+
### 9.2 Test %session list
|
|
17
|
+
|
|
18
|
+
<!-- auto -->
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
echo '{"prompt": "%session list"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- [ ] Returns session list (similar to CLI)
|
|
25
|
+
|
|
26
|
+
### 9.3 Test %proxy list
|
|
27
|
+
|
|
28
|
+
<!-- auto -->
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
echo '{"prompt": "%proxy list"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- [ ] Returns proxy list (read-only)
|
|
35
|
+
|
|
36
|
+
### 9.4 Test %guard commands
|
|
37
|
+
|
|
38
|
+
<!-- auto -->
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# Guard status
|
|
42
|
+
echo '{"prompt": "%guard status"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
43
|
+
|
|
44
|
+
# Guard enable
|
|
45
|
+
echo '{"prompt": "%guard enable --bundle tdd"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
46
|
+
|
|
47
|
+
# Guard disable
|
|
48
|
+
echo '{"prompt": "%guard disable"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
- [ ] `%guard status` returns policy state
|
|
52
|
+
- [ ] `%guard enable` enables TDD enforcement
|
|
53
|
+
- [ ] `%guard disable` disables all policy
|
|
54
|
+
|
|
55
|
+
### 9.5 Test %guard check (Phase 18)
|
|
56
|
+
|
|
57
|
+
<!-- auto -->
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cd $FORGE_TEST_REPO
|
|
61
|
+
|
|
62
|
+
# Create a test file to generate a diff
|
|
63
|
+
echo 'def hello(): pass' > src/test_guard_check.py
|
|
64
|
+
git add src/test_guard_check.py && git commit -m "placeholder"
|
|
65
|
+
echo 'def hello(): return "world"' > src/test_guard_check.py
|
|
66
|
+
|
|
67
|
+
# Check unstaged changes against TDD bundle (should deny: impl without tests)
|
|
68
|
+
echo '{"prompt": "%guard check --bundle tdd"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
69
|
+
|
|
70
|
+
# Check staged changes
|
|
71
|
+
git add src/test_guard_check.py
|
|
72
|
+
echo '{"prompt": "%guard check --bundle tdd --staged"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
73
|
+
|
|
74
|
+
# With explicit bundle override
|
|
75
|
+
echo '{"prompt": "%guard check --bundle coding_standards"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
76
|
+
|
|
77
|
+
# Clean up the test file (revert the commit + remove the file)
|
|
78
|
+
git reset --hard HEAD~1
|
|
79
|
+
rm -f src/test_guard_check.py
|
|
80
|
+
|
|
81
|
+
# Ensure no unstaged changes remain (Forge may have modified settings.local.json etc.)
|
|
82
|
+
git checkout -- . 2>/dev/null || true
|
|
83
|
+
|
|
84
|
+
# Now verify "no changes" path
|
|
85
|
+
echo '{"prompt": "%guard check --bundle tdd"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
- [ ] `%guard check` returns JSON with `passed`, `files_checked`, `bundles` fields
|
|
89
|
+
- [ ] Impl-only file denied by TDD bundle (`passed: false`)
|
|
90
|
+
- [ ] `--staged` flag evaluates staged changes instead of unstaged
|
|
91
|
+
- [ ] `--bundle` override selects specific bundle
|
|
92
|
+
- [ ] No changes returns `"No unstaged changes to check."`
|
|
93
|
+
|
|
94
|
+
### 9.6 Test %config
|
|
95
|
+
|
|
96
|
+
<!-- auto -->
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
echo '{"prompt": "%config"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
- [ ] Returns effective runtime config (read-only)
|
|
103
|
+
|
|
104
|
+
### 9.7 Test %session list --no-incognito
|
|
105
|
+
|
|
106
|
+
<!-- auto -->
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
echo '{"prompt": "%session list --no-incognito"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
- [ ] Returns a session list that excludes incognito sessions
|
|
113
|
+
|
|
114
|
+
### 9.8 Test %proxy show
|
|
115
|
+
|
|
116
|
+
<!-- auto -->
|
|
117
|
+
|
|
118
|
+
<!-- prereq: 4.2 -->
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
echo '{"prompt": "%proxy show test-proxy-nostart"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
- [ ] Returns proxy details (template, base_url, status) for the requested proxy id
|
|
125
|
+
|
|
126
|
+
### 9.9 Test %cancel-verification
|
|
127
|
+
|
|
128
|
+
<!-- auto -->
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
cd $FORGE_TEST_REPO
|
|
132
|
+
|
|
133
|
+
# Configure verification (completion promise) on the session
|
|
134
|
+
forge session set verification '{"type":"completion_promise","promise":"FORGE_COMPLETED"}' --session test-session-1
|
|
135
|
+
|
|
136
|
+
# Enable bypass via direct command escape hatch
|
|
137
|
+
echo '{"prompt": "%cancel-verification"}' | FORGE_SESSION=test-session-1 forge hook user-prompt-submit
|
|
138
|
+
|
|
139
|
+
# Verify override set
|
|
140
|
+
cat .forge/sessions/test-session-1/forge.session.json | jq '.overrides.verification.bypass'
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
- [ ] `%cancel-verification` returns "bypass enabled" message
|
|
144
|
+
- [ ] Session overrides include `verification.bypass: true`
|
|
145
|
+
|
|
146
|
+
---
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Forge QA Checklist
|
|
2
|
+
|
|
3
|
+
<!-- checklist: index -->
|
|
4
|
+
|
|
5
|
+
<!-- version: 1.0.19 -->
|
|
6
|
+
|
|
7
|
+
<!-- test-count: 482 -->
|
|
8
|
+
|
|
9
|
+
<!-- last-updated: 2026-05-18 -->
|
|
10
|
+
|
|
11
|
+
<!-- aligned-with: v0.1.0 -->
|
|
12
|
+
|
|
13
|
+
**Test Repo**: `$FORGE_TEST_REPO`
|
|
14
|
+
|
|
15
|
+
**Last updated**: 2026-05-18 (add memory CLI and handoff report checks)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Sections
|
|
20
|
+
|
|
21
|
+
- [0. Enable Forge (New User Flow)](checklist/0-enable.md)
|
|
22
|
+
|
|
23
|
+
<!-- section: 0 checklist/0-enable.md -->
|
|
24
|
+
|
|
25
|
+
- [1. Pre-Flight for Extension Tests](checklist/1-preflight.md)
|
|
26
|
+
|
|
27
|
+
<!-- section: 1 checklist/1-preflight.md -->
|
|
28
|
+
|
|
29
|
+
- [2. Claude Code Extensions (`forge extension enable`)](checklist/2-extensions.md)
|
|
30
|
+
|
|
31
|
+
<!-- section: 2 checklist/2-extensions.md -->
|
|
32
|
+
|
|
33
|
+
- [3. Authentication (`forge authentication`)](checklist/3-auth.md)
|
|
34
|
+
|
|
35
|
+
<!-- section: 3 checklist/3-auth.md -->
|
|
36
|
+
|
|
37
|
+
- [4. Proxy Management](checklist/4-proxy.md)
|
|
38
|
+
|
|
39
|
+
<!-- section: 4 checklist/4-proxy.md -->
|
|
40
|
+
|
|
41
|
+
- [5. Session Management](checklist/5-session.md)
|
|
42
|
+
|
|
43
|
+
<!-- section: 5 checklist/5-session.md -->
|
|
44
|
+
|
|
45
|
+
- [6. Hooks Testing](checklist/6-hooks.md)
|
|
46
|
+
|
|
47
|
+
<!-- section: 6 checklist/6-hooks.md -->
|
|
48
|
+
|
|
49
|
+
- [7. Cost Tracking & Spend Caps](checklist/7-costs.md)
|
|
50
|
+
|
|
51
|
+
<!-- section: 7 checklist/7-costs.md -->
|
|
52
|
+
|
|
53
|
+
- [8. Status Line](checklist/8-status-line.md)
|
|
54
|
+
|
|
55
|
+
<!-- section: 8 checklist/8-status-line.md -->
|
|
56
|
+
|
|
57
|
+
- [9. Direct Commands (% commands)](checklist/9-direct-commands.md)
|
|
58
|
+
|
|
59
|
+
<!-- section: 9 checklist/9-direct-commands.md -->
|
|
60
|
+
|
|
61
|
+
- [10. Session Resume (Phase 10 Feature)](checklist/10-resume.md)
|
|
62
|
+
|
|
63
|
+
<!-- section: 10 checklist/10-resume.md -->
|
|
64
|
+
|
|
65
|
+
- [11. Runtime Config + Claude Preset (`forge config`, `forge claude preset`)](checklist/11-config.md)
|
|
66
|
+
|
|
67
|
+
<!-- section: 11 checklist/11-config.md -->
|
|
68
|
+
|
|
69
|
+
- [12. Search (`forge search`)](checklist/12-search.md)
|
|
70
|
+
|
|
71
|
+
<!-- section: 12 checklist/12-search.md -->
|
|
72
|
+
|
|
73
|
+
- [13. Policy/Guard (`forge guard`)](checklist/13-guard.md)
|
|
74
|
+
|
|
75
|
+
<!-- section: 13 checklist/13-guard.md -->
|
|
76
|
+
|
|
77
|
+
- [14. Workflow Runners (`forge workflow`)](checklist/14-workflow.md)
|
|
78
|
+
|
|
79
|
+
<!-- section: 14 checklist/14-workflow.md -->
|
|
80
|
+
|
|
81
|
+
- [15. Skills (`/forge:review`, `/forge:understand`, `/forge:panel`, `/forge:consensus`)](checklist/15-skills.md)
|
|
82
|
+
|
|
83
|
+
<!-- section: 15 checklist/15-skills.md -->
|
|
84
|
+
|
|
85
|
+
- [16. Handoff Agent](checklist/16-handoff.md)
|
|
86
|
+
|
|
87
|
+
<!-- section: 16 checklist/16-handoff.md -->
|
|
88
|
+
|
|
89
|
+
- [17. System Info](checklist/17-info.md)
|
|
90
|
+
|
|
91
|
+
<!-- section: 17 checklist/17-info.md -->
|
|
92
|
+
|
|
93
|
+
- [18. Uninstallation (Incremental)](checklist/18-disable.md)
|
|
94
|
+
|
|
95
|
+
<!-- section: 18 checklist/18-disable.md -->
|
|
96
|
+
|
|
97
|
+
- [19. Complete Uninstallation (setup.sh --uninstall)](checklist/19-uninstall.md)
|
|
98
|
+
|
|
99
|
+
<!-- section: 19 checklist/19-uninstall.md -->
|
|
100
|
+
|
|
101
|
+
- [20. Cleanup](checklist/20-cleanup.md)
|
|
102
|
+
|
|
103
|
+
<!-- section: 20 checklist/20-cleanup.md -->
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Forge QA Report
|
|
2
|
+
|
|
3
|
+
| Field | Value |
|
|
4
|
+
| --------------------- | ------------------------------------------------------- |
|
|
5
|
+
| **Date** | YYYY-MM-DD |
|
|
6
|
+
| **Forge Version** | X.Y.Z (output of `forge --version`) |
|
|
7
|
+
| **Container** | container name (from `start-container.sh`) |
|
|
8
|
+
| **Checklist Version** | X.Y.Z (from checklist header `<!-- version: ... -->`) |
|
|
9
|
+
| **Duration** | HH:MM (from state file started_at to last_updated) |
|
|
10
|
+
| **Debug Logging** | Enabled by default in QA; artifacts copied when present |
|
|
11
|
+
|
|
12
|
+
## Summary
|
|
13
|
+
|
|
14
|
+
| Category | Total | Pass | Fail | Skip |
|
|
15
|
+
| --------------------- | ----- | ----- | ----- | ----- |
|
|
16
|
+
| Enable (New User) | 0 | 0 | 0 | 0 |
|
|
17
|
+
| Pre-Flight | 0 | 0 | 0 | 0 |
|
|
18
|
+
| Extensions | 0 | 0 | 0 | 0 |
|
|
19
|
+
| Auth | 0 | 0 | 0 | 0 |
|
|
20
|
+
| Proxy | 0 | 0 | 0 | 0 |
|
|
21
|
+
| Session | 0 | 0 | 0 | 0 |
|
|
22
|
+
| Hooks | 0 | 0 | 0 | 0 |
|
|
23
|
+
| Status Line | 0 | 0 | 0 | 0 |
|
|
24
|
+
| Direct Commands | 0 | 0 | 0 | 0 |
|
|
25
|
+
| Session Resume | 0 | 0 | 0 | 0 |
|
|
26
|
+
| Runtime Config | 0 | 0 | 0 | 0 |
|
|
27
|
+
| Search | 0 | 0 | 0 | 0 |
|
|
28
|
+
| Guard | 0 | 0 | 0 | 0 |
|
|
29
|
+
| Workflow Runners | 0 | 0 | 0 | 0 |
|
|
30
|
+
| Skills | 0 | 0 | 0 | 0 |
|
|
31
|
+
| Handoff | 0 | 0 | 0 | 0 |
|
|
32
|
+
| System Info | 0 | 0 | 0 | 0 |
|
|
33
|
+
| Disable (Incremental) | 0 | 0 | 0 | 0 |
|
|
34
|
+
| Uninstall (Complete) | 0 | 0 | 0 | 0 |
|
|
35
|
+
| Cleanup | 0 | 0 | 0 | 0 |
|
|
36
|
+
| **TOTAL** | **0** | **0** | **0** | **0** |
|
|
37
|
+
|
|
38
|
+
## Issues Found
|
|
39
|
+
|
|
40
|
+
| # | Section | Severity | Description |
|
|
41
|
+
| --- | ------- | --------------- | --------------------------------------------- |
|
|
42
|
+
| 1 | X.Y | high/medium/low | Brief description of what failed or was wrong |
|
|
43
|
+
|
|
44
|
+
If no issues: "No issues found."
|
|
45
|
+
|
|
46
|
+
## Infrastructure
|
|
47
|
+
|
|
48
|
+
- **Forge**: version, install method (pip/uv)
|
|
49
|
+
- **Docker**: available/unavailable (docker info output)
|
|
50
|
+
- **Proxies**: count from `forge proxy list`, or "not tested"
|
|
51
|
+
- **Credentials**: auth status from hermetic FORGE_HOME, or "not tested"
|
|
52
|
+
|
|
53
|
+
## Artifacts
|
|
54
|
+
|
|
55
|
+
- **step-logs/**: raw command output per checklist step (copied from the mounted QA state dir)
|
|
56
|
+
- **forge-logs/final/**: final Forge debug logs copied from the container at artifact-save time
|
|
57
|
+
- **forge-logs-snapshots/**: pre-clean snapshots captured before any checklist step runs `forge logs --clean`
|
|
58
|
+
- **transcript.jsonl**: copied when the QA session exits (if the transcript claim token is satisfied)
|
|
59
|
+
|
|
60
|
+
## Notes
|
|
61
|
+
|
|
62
|
+
Observations from human checkpoint verifications, edge cases noticed, or anything that passed but looked suspicious.
|