deepflow 0.1.111 → 0.1.112
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/install.js +68 -84
- package/bin/install.test.js +1 -0
- package/bin/ratchet.js +185 -8
- package/bin/ratchet.test.js +4 -4
- package/hooks/ac-coverage.js +66 -60
- package/hooks/df-check-update.js +1 -0
- package/hooks/df-command-usage.js +1 -0
- package/hooks/df-dashboard-push.js +1 -0
- package/hooks/df-execution-history.js +1 -0
- package/hooks/df-explore-protocol.js +1 -21
- package/hooks/df-harness-score.js +389 -0
- package/hooks/df-invariant-check.js +154 -1
- package/hooks/df-quota-logger.js +1 -0
- package/hooks/df-snapshot-guard.js +1 -0
- package/hooks/df-spec-lint.js +6 -0
- package/hooks/df-spec-lint.test.js +57 -1
- package/hooks/df-statusline.js +1 -0
- package/hooks/df-subagent-registry.js +1 -0
- package/hooks/df-tool-usage-spike.js +2 -0
- package/hooks/df-tool-usage.js +1 -0
- package/hooks/df-worktree-guard.js +157 -0
- package/hooks/lib/installer-utils.js +114 -0
- package/package.json +1 -1
- package/src/commands/df/debate.md +20 -4
- package/src/commands/df/discover.md +1 -1
- package/src/commands/df/execute.md +66 -11
- package/src/commands/df/plan.md +4 -5
- package/src/commands/df/spec.md +1 -0
- package/src/skills/repo-inspect/SKILL.md +205 -0
- package/templates/config-template.yaml +3 -0
- package/templates/spec-template.md +17 -0
|
@@ -148,7 +148,7 @@ Context ≥50% → checkpoint and exit. Before spawning: `TaskUpdate(status: "in
|
|
|
148
148
|
|
|
149
149
|
**Token tracking start:** Store `start_percentage` (from context.json) and `start_timestamp` (ISO 8601) keyed by task_id. Omit if unavailable.
|
|
150
150
|
|
|
151
|
-
**
|
|
151
|
+
**Intra-wave isolation:** Each task in a wave runs with `isolation: "worktree"` — tasks from the same spec share that spec's worktree branch so wave 2 sees wave 1 commits; tasks from different specs run in different worktrees and never interleave. **Spawn ALL ready tasks in ONE message** except file conflicts.
|
|
152
152
|
|
|
153
153
|
**Per-spec routing (CRITICAL):** Each task in `WAVE_JSON` carries a `spec` field (from `bin/wave-runner.js`). When building the agent prompt (§6), you MUST set `Working directory: ${SPEC_WORKTREES[task.spec].path}` — the worktree for that task's spec, NOT the first spec in the map. Cross-spec contamination (spawning a task from spec B into spec A's worktree) corrupts branch history and breaks `/df:verify`. If `task.spec` is absent from the JSON, fall back to deriving it from the task's mini-plan file `.deepflow/plans/doing-{specName}.md`; if still unresolvable, defer the task and log `"⚠ T{N} deferred — cannot resolve spec"`.
|
|
154
154
|
|
|
@@ -156,11 +156,26 @@ Context ≥50% → checkpoint and exit. Before spawning: `TaskUpdate(status: "in
|
|
|
156
156
|
|
|
157
157
|
**≥2 [SPIKE] tasks same problem →** Parallel Spike Probes (§5.7). **[OPTIMIZE] tasks →** Optimize Cycle (§5.9), one at a time. **[INTEGRATION] tasks** (`task.isIntegration === true` in WAVE_JSON) **→** use the Integration Task prompt template (§6 Integration Task), not the Standard Task template. Integration tasks always land in the final wave via `Blocked by:` — wave-runner guarantees this, so they execute after all producer/consumer implementation tasks have committed. Route them to the **consumer spec's** worktree via `SPEC_WORKTREES[task.spec].path` (plan.md §4.8.2 places the integration task under the consumer's section header, so `task.spec` is already the consumer).
|
|
158
158
|
|
|
159
|
+
### 5.1. INTRA-WAVE CHERRY-PICK MERGE
|
|
160
|
+
|
|
161
|
+
After ALL wave-N agents complete, cherry-pick each wave-N commit back to the main branch BEFORE wave N+1 begins. This ensures wave N+1 agents see all wave-N changes regardless of which worktree they run in.
|
|
162
|
+
|
|
163
|
+
**Wave gate:** Wave N+1 MUST NOT start until all wave-N cherry-picks complete.
|
|
164
|
+
|
|
165
|
+
**Ordering:** Apply cherry-picks in ascending task-number order (e.g., T1 before T2 before T3) for determinism.
|
|
166
|
+
|
|
167
|
+
**Steps (per wave completion):**
|
|
168
|
+
1. Collect all task commits from wave N (from ratchet PASS records).
|
|
169
|
+
2. Sort commits by ascending task-number order.
|
|
170
|
+
3. For each commit, spawn haiku context-fork (§5.8): `git cherry-pick {sha}`. Receive one-line summary.
|
|
171
|
+
4. On conflict: log `"⚠ cherry-pick conflict: {sha} — {file}"`, abort cherry-pick, mark task as needing manual resolution.
|
|
172
|
+
5. Only after all wave-N cherry-picks finish → proceed to spawn wave N+1 agents.
|
|
173
|
+
|
|
159
174
|
### 5.5. RATCHET CHECK
|
|
160
175
|
|
|
161
|
-
Run `node
|
|
176
|
+
Run `node bin/ratchet.js` in the **task's spec worktree** after each agent completes, using that spec's snapshot file:
|
|
162
177
|
```bash
|
|
163
|
-
node
|
|
178
|
+
node bin/ratchet.js --worktree ${SPEC_WORKTREES[task.spec].path} --snapshot .deepflow/auto-snapshot-{task.spec}.txt --task T{N}
|
|
164
179
|
```
|
|
165
180
|
|
|
166
181
|
The script handles all health checks internally and outputs structured JSON:
|
|
@@ -187,7 +202,7 @@ The script handles all health checks internally and outputs structured JSON:
|
|
|
187
202
|
```
|
|
188
203
|
(Fall back to text mode if `--json` is unavailable: `node "${HOME}/.claude/bin/wave-runner.js" --plan PLAN.md --recalc --failed T{N}`)
|
|
189
204
|
Report: `"✗ T{n}: reverted"`.
|
|
190
|
-
- **Exit 2 (SALVAGEABLE):** Spawn `Agent(model="sonnet")` to fix lint/typecheck issues. Re-run `node
|
|
205
|
+
- **Exit 2 (SALVAGEABLE):** Spawn `Agent(model="sonnet")` to fix lint/typecheck issues. Re-run `node bin/ratchet.js`. If still non-zero → revert both commits, set status pending.
|
|
191
206
|
|
|
192
207
|
#### 5.5.1. AC COVERAGE CHECK (after ratchet pass)
|
|
193
208
|
|
|
@@ -207,11 +222,12 @@ where `{spec_path}` is the path to `specs/doing-{spec_name}.md` and `{agent_outp
|
|
|
207
222
|
|
|
208
223
|
Parse the agent's response for `DECISIONS:` line. If present:
|
|
209
224
|
1. Split by ` | ` to get individual decisions
|
|
210
|
-
2.
|
|
211
|
-
3.
|
|
212
|
-
4.
|
|
225
|
+
2. If any entry does not start with `[TAG]` where TAG ∈ {APPROACH, PROVISIONAL, ASSUMPTION, FUTURE, UPDATE}, emit SALVAGEABLE and skip writing that entry to decisions.md (valid entries still get written).
|
|
226
|
+
3. Each decision has format `[TAG] description — rationale` where TAG ∈ {APPROACH, PROVISIONAL, ASSUMPTION, FUTURE, UPDATE}
|
|
227
|
+
4. Append to `.deepflow/decisions.md` under `### {date} — {spec_name}` header (create header if first decision for this spec today, reuse if exists)
|
|
228
|
+
5. Format: `- [TAG] description — rationale`
|
|
213
229
|
|
|
214
|
-
If no `DECISIONS:` line in agent output → skip silently (mechanical tasks don't produce decisions).
|
|
230
|
+
If no `DECISIONS:` line in agent output and the task effort is not `low` → emit SALVAGEABLE (non-trivial tasks without a decision line may indicate the agent skipped documenting architectural choices). For tasks with effort `low`, skip silently (mechanical tasks don't produce decisions).
|
|
215
231
|
|
|
216
232
|
**This runs on every ratchet pass, not just at verify time.** Decisions are captured incrementally as tasks complete, so they're never lost even if verify fails or merge is manual.
|
|
217
233
|
|
|
@@ -232,6 +248,20 @@ tokens:
|
|
|
232
248
|
```
|
|
233
249
|
Omit if context.json/token-history.jsonl/awk unavailable. Never fail ratchet for tracking errors.
|
|
234
250
|
|
|
251
|
+
### 5.6. WAVE TEST AGENT
|
|
252
|
+
|
|
253
|
+
Trigger: task type is [TEST] or orchestrator spawns a dedicated test-writing agent for a wave.
|
|
254
|
+
|
|
255
|
+
Before spawning the test agent, collect context:
|
|
256
|
+
```bash
|
|
257
|
+
SNAPSHOT_FILES=!`cat .deepflow/auto-snapshot.txt 2>/dev/null || echo ''`
|
|
258
|
+
EXISTING_TEST_NAMES=!`grep -h -E "^\s*(it|test|describe)\(" ${SNAPSHOT_FILES} 2>/dev/null | sed "s/^[[:space:]]*//" || echo ''`
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Pass `SNAPSHOT_FILES` and `EXISTING_TEST_NAMES` into the agent prompt so it can avoid duplication.
|
|
262
|
+
|
|
263
|
+
**Implementation diff:** The wave test agent reads the implementation diff itself using the `Read` tool or `git diff` — do NOT capture or pass the raw diff to the wave test prompt inline. Injecting large diffs inflates context and causes rot.
|
|
264
|
+
|
|
235
265
|
### 5.7. PARALLEL SPIKE PROBES
|
|
236
266
|
|
|
237
267
|
Trigger: ≥2 [SPIKE] tasks with same blocker or identical hypothesis.
|
|
@@ -399,7 +429,7 @@ Success criteria: {ACs from spec relevant to this task}
|
|
|
399
429
|
{If spec contains ## Domain Model section:
|
|
400
430
|
--- CONTEXT: Domain Model ---
|
|
401
431
|
{Domain Model section content from doing-*.md, extracted via shell injection:
|
|
402
|
-
DOMAIN_MODEL=!`sed -n '/^## Domain Model$/,/^##
|
|
432
|
+
DOMAIN_MODEL=!`sed -n '/^## Domain Model$/,/^## /p' specs/doing-{spec_name}.md | head -n -1 2>/dev/null || echo 'NOT_FOUND'`
|
|
403
433
|
}
|
|
404
434
|
}
|
|
405
435
|
{If EXISTING_TYPES is non-empty:
|
|
@@ -421,7 +451,7 @@ AC-2:skip:reason here (if applicable)
|
|
|
421
451
|
AC_COVERAGE_END
|
|
422
452
|
```
|
|
423
453
|
Format: one line per AC with either `AC-N:done` or `AC-N:skip:reason`. Omit this block if the spec has no acceptance criteria.
|
|
424
|
-
DECISIONS: If you made non-obvious choices,
|
|
454
|
+
DECISIONS: If you made non-obvious choices, cite with [APPROACH]. Append to the LAST LINE BEFORE TASK_STATUS:
|
|
425
455
|
DECISIONS: [TAG] {decision} — {rationale} | [TAG] {decision2} — {rationale2}
|
|
426
456
|
Tags:
|
|
427
457
|
[APPROACH] — chose X over Y (architectural/design choice)
|
|
@@ -430,6 +460,7 @@ Tags:
|
|
|
430
460
|
[FUTURE] — deferred X because Y; revisit when Z
|
|
431
461
|
[UPDATE] — changed prior decision from X to Y because Z
|
|
432
462
|
Skip for trivial/mechanical changes.
|
|
463
|
+
Files: List every file you modified or created, one per line, in the format `Files: path/to/file.ts, path/to/other.ts`. This is required so the orchestrator can detect file conflicts across concurrent tasks.
|
|
433
464
|
Last line of your response MUST be: TASK_STATUS:pass (if successful) or TASK_STATUS:fail (if failed) or TASK_STATUS:revert (if reverted)
|
|
434
465
|
```
|
|
435
466
|
|
|
@@ -442,6 +473,7 @@ Integration ACs: {list from PLAN.md}
|
|
|
442
473
|
Specs involved: {spec file paths}
|
|
443
474
|
Interface Map: {from integration task detail}
|
|
444
475
|
Contract Risks: {from integration task detail}
|
|
476
|
+
LSP documentSymbol on Impact files → Read with offset/limit on relevant ranges only (never read full files)
|
|
445
477
|
--- END ---
|
|
446
478
|
RULES:
|
|
447
479
|
- Fix the CONSUMER to match the PRODUCER's declared interface. Never weaken the producer.
|
|
@@ -464,7 +496,28 @@ Last line: TASK_STATUS:pass or TASK_STATUS:fail
|
|
|
464
496
|
|
|
465
497
|
**Bootstrap:** `BOOTSTRAP: Write tests for edit_scope files. Do NOT change implementation. Commit as test({spec}): bootstrap. Last line: TASK_STATUS:pass or TASK_STATUS:fail`
|
|
466
498
|
|
|
467
|
-
**
|
|
499
|
+
**Wave Test** (`Agent(model="sonnet")`):
|
|
500
|
+
```
|
|
501
|
+
--- START ---
|
|
502
|
+
{task_id} [TEST]: Write tests for {spec_name}. Files+Spec.
|
|
503
|
+
Pre-existing test files:
|
|
504
|
+
{SNAPSHOT_FILES}
|
|
505
|
+
|
|
506
|
+
Existing test function names (do NOT duplicate these):
|
|
507
|
+
{EXISTING_TEST_NAMES}
|
|
508
|
+
--- MIDDLE ---
|
|
509
|
+
Spec: {spec_path}
|
|
510
|
+
Edit scope: {edit_scope}
|
|
511
|
+
--- END ---
|
|
512
|
+
RULES:
|
|
513
|
+
- Use the `Read` tool (or `git diff HEAD~1`) to inspect what the implementation changed before writing tests.
|
|
514
|
+
- Do not duplicate tests that already exist in the pre-existing test files listed above.
|
|
515
|
+
- Do not modify pre-existing test files — write new test files only.
|
|
516
|
+
- Commit as test({spec}): {description}.
|
|
517
|
+
Last line of your response MUST be: TASK_STATUS:pass (if successful) or TASK_STATUS:fail (if failed)
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
**Spike**: `{task_id} [SPIKE]: {hypothesis}. Files+Spec. {reverted warnings}. Minimal spike. Commit as spike({spec}): {desc}. If you discovered constraints, rejected approaches, or made assumptions, report: DECISIONS: [TAG] {finding} — {why it matters} (use PROVISIONAL for "works but needs revisit", ASSUMPTION for "assumed X; if wrong Y breaks", APPROACH for definitive choices). Last line: TASK_STATUS:pass or TASK_STATUS:fail`
|
|
468
521
|
|
|
469
522
|
**Optimize Task** (`Agent(model="opus")`):
|
|
470
523
|
```
|
|
@@ -474,6 +527,7 @@ Current: {val} (baseline: {b}, best: {best}). Target: {t} ({dir}). Metric: {cmd}
|
|
|
474
527
|
CONSTRAINT: ONE atomic change.
|
|
475
528
|
--- MIDDLE ---
|
|
476
529
|
Last 5 cycles + failed hypotheses + Impact/deps.
|
|
530
|
+
LSP documentSymbol on Impact files → Read with offset/limit on relevant ranges only (never read full files)
|
|
477
531
|
--- END ---
|
|
478
532
|
{Learnings}. ONE change + commit. No metric run, no multiple changes.
|
|
479
533
|
Last line of your response MUST be: TASK_STATUS:pass or TASK_STATUS:fail or TASK_STATUS:revert
|
|
@@ -489,6 +543,7 @@ Current/Target. Role instruction:
|
|
|
489
543
|
ingenua: "Ignore prior. Fresh approach."
|
|
490
544
|
--- MIDDLE ---
|
|
491
545
|
Full history + all failed hypotheses.
|
|
546
|
+
LSP documentSymbol on Impact files → Read with offset/limit on relevant ranges only (never read full files)
|
|
492
547
|
--- END ---
|
|
493
548
|
ONE atomic change. Commit. STOP.
|
|
494
549
|
Last line of your response MUST be: TASK_STATUS:pass or TASK_STATUS:fail or TASK_STATUS:revert
|
package/src/commands/df/plan.md
CHANGED
|
@@ -230,7 +230,7 @@ You are a spec planner. Your job is to independently analyze a spec and produce
|
|
|
230
230
|
2. **Compute spec layer** — determine L0–L3 based on sections present (see layer rules below)
|
|
231
231
|
3. **Check experiments** — glob `.deepflow/experiments/{topic}--*` for past spikes
|
|
232
232
|
4. **Explore the codebase** — detect code style, patterns, integration points relevant to this spec
|
|
233
|
-
5. **Impact analysis** (L3 only) — LSP
|
|
233
|
+
5. **Impact analysis** (L3 only) — LSP documentSymbol on impact files → Read with offset/limit on relevant ranges only (never read full files)
|
|
234
234
|
6. **Targeted exploration** — follow `templates/explore-agent.md` spawn rules for post-LSP gaps
|
|
235
235
|
7. **Generate tasks** — produce a mini-plan following the output format below
|
|
236
236
|
|
|
@@ -402,10 +402,9 @@ The reasoner prompt:
|
|
|
402
402
|
```
|
|
403
403
|
You are the plan reasoner. Analyze this spec and produce a prioritized task plan.
|
|
404
404
|
|
|
405
|
-
## Spec
|
|
406
|
-
{
|
|
407
|
-
|
|
408
|
-
Read the spec using the Read tool on the path above. Do NOT read any implementation files.
|
|
405
|
+
## Spec content
|
|
406
|
+
<!-- {spec_content} — injected by orchestrator before spawning; do NOT use Read tool on the spec -->
|
|
407
|
+
{spec_content}
|
|
409
408
|
|
|
410
409
|
## Agent summaries (from §3 parallel agents)
|
|
411
410
|
|
package/src/commands/df/spec.md
CHANGED
|
@@ -55,6 +55,7 @@ Spawn reasoner agent (`subagent_type: "reasoner"`, `model: "opus"`). The reasone
|
|
|
55
55
|
- Flags conflicts with existing code
|
|
56
56
|
- Verifies every REQ-N has a corresponding AC; flags uncovered requirements
|
|
57
57
|
- Flags vague/untestable requirements (e.g., "should be fast" without a metric)
|
|
58
|
+
- If Explore agents found type definitions or interfaces relevant to this spec, include a ## Domain Model section with Key Types (signatures only) and Ubiquitous Language (domain terms). Omit if no relevant types found.
|
|
58
59
|
|
|
59
60
|
### 4. GENERATE SPEC
|
|
60
61
|
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: repo-inspect
|
|
3
|
+
description: Produces structured JSON intelligence for a remote GitHub repo — fetches metadata and file tree via gh api, reads key files via WebFetch. No local clone. Use when evaluating an unfamiliar repo before planning integration work.
|
|
4
|
+
context: fork
|
|
5
|
+
allowed-tools: [Bash, WebFetch]
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Repo-Inspect
|
|
9
|
+
|
|
10
|
+
Inspect a GitHub repository and emit a single JSON object describing its architecture. No clones, no tmpdir, no local filesystem writes.
|
|
11
|
+
|
|
12
|
+
**Input:** `{owner}/{repo}` or a full GitHub URL (e.g., `https://github.com/owner/repo`).
|
|
13
|
+
**Output:** Raw JSON only — no markdown, no commentary.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Protocol
|
|
18
|
+
|
|
19
|
+
### Step 0 — Parse Input
|
|
20
|
+
|
|
21
|
+
Strip `https://github.com/` prefix if present. Extract `{owner}` and `{repo}` from the remaining `owner/repo` string.
|
|
22
|
+
|
|
23
|
+
### Step 1 — Fetch Repo Metadata (1 Bash call)
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
gh api repos/{owner}/{repo}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Extract: `description`, `language`, `topics`, `default_branch`, `stargazers_count`, `forks_count`.
|
|
30
|
+
|
|
31
|
+
On error (non-zero exit or JSON with `message` field indicating 404/403):
|
|
32
|
+
```json
|
|
33
|
+
{"error": "api_failed", "message": "<gh api error text>"}
|
|
34
|
+
```
|
|
35
|
+
Stop and return this error JSON immediately.
|
|
36
|
+
|
|
37
|
+
### Step 2 — Fetch Full File Tree (1 Bash call)
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
gh api "repos/{owner}/{repo}/git/trees/{default_branch}?recursive=1"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Parse `tree[]` array. Each item has: `path`, `type` (`blob`|`tree`), `size`.
|
|
44
|
+
|
|
45
|
+
If tree is truncated (`truncated: true`), note it but proceed — the tree API returns up to ~100K entries which covers virtually all repos.
|
|
46
|
+
|
|
47
|
+
### Step 3 — Language Detection
|
|
48
|
+
|
|
49
|
+
Scan tree paths for manifest files in priority order:
|
|
50
|
+
|
|
51
|
+
| Manifest | Language |
|
|
52
|
+
|---|---|
|
|
53
|
+
| `Cargo.toml` | Rust |
|
|
54
|
+
| `package.json` | JavaScript/TypeScript |
|
|
55
|
+
| `pyproject.toml` or `setup.py` or `requirements.txt` | Python |
|
|
56
|
+
| `go.mod` | Go |
|
|
57
|
+
| `pom.xml` or `build.gradle` | Java |
|
|
58
|
+
| `mix.exs` | Elixir |
|
|
59
|
+
| `Gemfile` | Ruby |
|
|
60
|
+
| `build.zig` | Zig |
|
|
61
|
+
| `CMakeLists.txt` | C/C++ |
|
|
62
|
+
|
|
63
|
+
Use the **first match** (highest priority). If no manifest found, fall back to `language` field from Step 1 metadata.
|
|
64
|
+
|
|
65
|
+
Record: `detected_language`, `manifest_path` (path of matched manifest, or null).
|
|
66
|
+
|
|
67
|
+
### Step 4 — File Selection (3–6 files)
|
|
68
|
+
|
|
69
|
+
Build a prioritized list of files to fetch. Select 3–6 total:
|
|
70
|
+
|
|
71
|
+
1. **README** — find `README.md` or `README.rst` or `README` in tree root (depth 0). Always include if present.
|
|
72
|
+
2. **Manifest** — the manifest file detected in Step 3. Always include if present.
|
|
73
|
+
3. **Primary entry point** — search tree for (in order): `src/main.*`, `src/lib.*`, `src/index.*`, `index.*`, `app.*`, `main.*`. Pick the first match at the shallowest depth.
|
|
74
|
+
4. **Supplemental files** — from remaining blobs: prefer shallowest paths, then largest `size`. Pick source files (`.rs`, `.ts`, `.js`, `.py`, `.go`, `.java`, `.ex`, `.rb`, `.zig`, `.c`, `.cpp`, `.h`). Fill up to 6 total.
|
|
75
|
+
|
|
76
|
+
For monorepos (detected when tree contains `packages/*/`, `crates/*/`, `apps/*/` directories, or manifest workspace field): select 1-2 representative sub-package manifests/entry points instead of generic supplemental files.
|
|
77
|
+
|
|
78
|
+
### Step 5 — Fetch File Contents (3–6 WebFetch calls)
|
|
79
|
+
|
|
80
|
+
For each selected file path, fetch:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
https://raw.githubusercontent.com/{owner}/{repo}/{default_branch}/{path}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Use WebFetch. If a fetch fails (404 or network error), skip that file and note it. Do not retry.
|
|
87
|
+
|
|
88
|
+
Collect: list of `{path, content}` pairs for all successfully fetched files.
|
|
89
|
+
|
|
90
|
+
### Step 6 — Extract Intelligence from Fetched Content
|
|
91
|
+
|
|
92
|
+
From manifest content (if fetched):
|
|
93
|
+
|
|
94
|
+
- **dependency_count**: Count entries in `[dependencies]` (Cargo.toml), `dependencies` + `devDependencies` keys (package.json), `[tool.poetry.dependencies]` (pyproject.toml), `require` directives (go.mod/Gemfile), `<dependency>` tags (pom.xml). Use 0 if manifest not fetched.
|
|
95
|
+
- **test_framework**: Check dev-dependencies for known test frameworks:
|
|
96
|
+
- JS/TS: `jest`, `vitest`, `mocha`, `jasmine`, `tap`, `ava`
|
|
97
|
+
- Python: `pytest`, `unittest` (stdlib), `nose`
|
|
98
|
+
- Rust: built-in (`#[test]`), `rstest`, `proptest`
|
|
99
|
+
- Go: built-in (`testing` package)
|
|
100
|
+
- Java: `junit`, `testng`
|
|
101
|
+
- Ruby: `rspec`, `minitest`
|
|
102
|
+
- Elixir: built-in (`ExUnit`)
|
|
103
|
+
Also check tree for `test/`, `tests/`, `spec/`, `__tests__/` directories as corroboration.
|
|
104
|
+
- **monorepo**: true if tree contains at least 2 of `packages/`, `crates/`, `apps/`, `libs/` top-level dirs, OR if manifest has workspace/workspaces field.
|
|
105
|
+
|
|
106
|
+
From README content (if fetched):
|
|
107
|
+
- Extract the first non-heading paragraph as a candidate for `purpose`. Trim to ≤ 200 chars.
|
|
108
|
+
|
|
109
|
+
Fallback for `purpose`: use repo `description` from Step 1 metadata.
|
|
110
|
+
|
|
111
|
+
### Step 7 — Derive key_modules
|
|
112
|
+
|
|
113
|
+
From the tree blob paths, identify directories containing 2+ source files (files with extensions `.rs`, `.ts`, `.js`, `.tsx`, `.jsx`, `.py`, `.go`, `.java`, `.ex`, `.rb`, `.zig`, `.c`, `.cpp`, `.h`, `.swift`, `.kt`).
|
|
114
|
+
|
|
115
|
+
Algorithm:
|
|
116
|
+
1. For each blob, extract parent directory path.
|
|
117
|
+
2. Count source files per directory.
|
|
118
|
+
3. Keep directories with count >= 2.
|
|
119
|
+
4. Sort by file count descending, then by path depth ascending (shallower = more significant).
|
|
120
|
+
5. Take up to 10 modules.
|
|
121
|
+
6. Strip common prefixes (e.g., if all modules share `src/`, keep `src/` as a module too).
|
|
122
|
+
|
|
123
|
+
Return directory names (last path segment) for the `key_modules` array. If fewer than 3 candidate directories exist, include directories with 1 source file to reach 3, or return what's available.
|
|
124
|
+
|
|
125
|
+
### Step 8 — Derive concepts_applicable
|
|
126
|
+
|
|
127
|
+
Based on language, test framework, monorepo status, and key module names, suggest applicable engineering concepts. Examples:
|
|
128
|
+
|
|
129
|
+
- Monorepo → `"workspace-management"`, `"cross-package-testing"`
|
|
130
|
+
- Rust → `"ownership-model"`, `"cargo-workspace"` (if monorepo)
|
|
131
|
+
- TypeScript → `"type-safety"`, `"module-resolution"`
|
|
132
|
+
- Has `auth` module → `"authentication-patterns"`
|
|
133
|
+
- Has `db` or `models` module → `"data-modeling"`
|
|
134
|
+
- Has `api` or `routes` module → `"rest-api-design"`
|
|
135
|
+
- Has tests → `"tdd"` or `"bdd"` (if rspec/jasmine)
|
|
136
|
+
|
|
137
|
+
Limit to 3–7 concepts. These are suggestions for the caller — not exhaustive.
|
|
138
|
+
|
|
139
|
+
### Step 9 — Confidence Score
|
|
140
|
+
|
|
141
|
+
Set `confidence` based on data quality:
|
|
142
|
+
|
|
143
|
+
| Condition | Confidence |
|
|
144
|
+
|---|---|
|
|
145
|
+
| README + manifest + entry point all fetched | `high` |
|
|
146
|
+
| README or manifest fetched, but not both | `medium` |
|
|
147
|
+
| Neither README nor manifest fetched | `low` |
|
|
148
|
+
|
|
149
|
+
### Step 10 — Emit JSON Output
|
|
150
|
+
|
|
151
|
+
Output **exactly one JSON object** with no surrounding text, no markdown code fences, no comments:
|
|
152
|
+
|
|
153
|
+
```json
|
|
154
|
+
{
|
|
155
|
+
"repo": "{owner}/{repo}",
|
|
156
|
+
"purpose": "<first non-heading README paragraph or repo description, ≤200 chars>",
|
|
157
|
+
"architecture": {
|
|
158
|
+
"language": "<detected language>",
|
|
159
|
+
"entry_points": ["<relative paths of main/lib/index files>"],
|
|
160
|
+
"key_modules": ["<directory names with 2+ source files>"],
|
|
161
|
+
"dependencies_count": 0,
|
|
162
|
+
"test_framework": "<framework name or 'unknown'>"
|
|
163
|
+
},
|
|
164
|
+
"concepts_applicable": ["<concept1>", "<concept2>"],
|
|
165
|
+
"files_inspected": ["<path1>", "<path2>"],
|
|
166
|
+
"confidence": "high|medium|low"
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Critical:** The very last thing you output must be this JSON object and nothing else. Do not wrap in code blocks. Do not add explanation.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
## Error Handling
|
|
175
|
+
|
|
176
|
+
| Scenario | Action |
|
|
177
|
+
|---|---|
|
|
178
|
+
| `gh api` returns non-zero exit for metadata | Return `{"error": "api_failed", "message": "<stderr>"}` and stop |
|
|
179
|
+
| `gh api` returns 404 JSON | Return `{"error": "api_failed", "message": "Repository not found or not accessible"}` |
|
|
180
|
+
| Tree fetch fails | Return `{"error": "tree_failed", "message": "<stderr>"}` and stop |
|
|
181
|
+
| All WebFetch calls fail | Set confidence to "low", proceed with tree-only analysis |
|
|
182
|
+
| Single WebFetch fails | Skip file, continue |
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Efficiency Budget
|
|
187
|
+
|
|
188
|
+
- `gh api` calls: exactly 2 (metadata + tree)
|
|
189
|
+
- WebFetch calls: 3–6 (selected files)
|
|
190
|
+
- Analysis steps: ~5 (no extra Bash calls needed)
|
|
191
|
+
- **Total tool calls: ≤ 20**
|
|
192
|
+
- **Wall time: ≤ 60s**
|
|
193
|
+
- **Tokens: ≤ 30K**
|
|
194
|
+
|
|
195
|
+
Do not make extra `gh api` calls. Do not fetch files not in the selection list. The tree endpoint returns all paths in one call — no Glob, no Read, no additional listing needed.
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Rules
|
|
200
|
+
|
|
201
|
+
- Never write to local filesystem (no `> file`, no `mktemp`, no `git clone`).
|
|
202
|
+
- Never use Read, Glob, or Grep tools — this skill operates on remote data only.
|
|
203
|
+
- Output raw JSON only — the caller parses it, not reads it as prose.
|
|
204
|
+
- Private repos work automatically via `gh auth` stored token.
|
|
205
|
+
- Strip `context: fork` means this skill's token usage doesn't pollute the caller's context.
|
|
@@ -96,6 +96,9 @@ quality:
|
|
|
96
96
|
# Timeout in seconds to wait for the dev server to become ready (default: 30)
|
|
97
97
|
browser_timeout: 30
|
|
98
98
|
|
|
99
|
+
# Minimum quality score threshold for harness verification (0.0-1.0, default: 0.6)
|
|
100
|
+
harness_min_score: 0.6
|
|
101
|
+
|
|
99
102
|
# Ratchet configuration for /df:verify health gate
|
|
100
103
|
# Ratchet snapshots baseline metrics (tests passing, coverage, type checks) before execution
|
|
101
104
|
# and ensures subsequent runs don't regress. These overrides control which commands ratchet monitors.
|
|
@@ -43,6 +43,23 @@
|
|
|
43
43
|
|
|
44
44
|
- [Explicitly excluded: e.g., "Video upload is NOT included"]
|
|
45
45
|
|
|
46
|
+
## Domain Model
|
|
47
|
+
|
|
48
|
+
<!-- Optional. Define the core entities and vocabulary. -->
|
|
49
|
+
|
|
50
|
+
### Key Types
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// Core domain types and entities
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Ubiquitous Language
|
|
57
|
+
|
|
58
|
+
- **Term**: Definition
|
|
59
|
+
- **Term**: Definition
|
|
60
|
+
|
|
61
|
+
_Note: Keep to max 15 terms for clarity._
|
|
62
|
+
|
|
46
63
|
## Acceptance Criteria
|
|
47
64
|
|
|
48
65
|
- [ ] [Testable criterion: e.g., "User can upload jpg/png/webp files"]
|