@popoverai/dotrequirements 0.26.0 → 0.26.1
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/dist/codebase-to-spec/area-name.d.ts +13 -0
- package/dist/codebase-to-spec/area-name.js +18 -0
- package/dist/codebase-to-spec/cache.d.ts +31 -0
- package/dist/codebase-to-spec/cache.js +29 -1
- package/dist/codebase-to-spec/compose.d.ts +7 -4
- package/dist/codebase-to-spec/compose.js +10 -21
- package/dist/codebase-to-spec/dispatch.js +1 -1
- package/dist/codebase-to-spec/present.js +7 -2
- package/dist/codebase-to-spec/prompts/planner-initial.d.ts +3 -2
- package/dist/codebase-to-spec/prompts/planner-initial.js +3 -2
- package/dist/codebase-to-spec/renumber.d.ts +52 -0
- package/dist/codebase-to-spec/renumber.js +105 -0
- package/dist/codebase-to-spec/schemas.d.ts +35 -240
- package/dist/codebase-to-spec/schemas.js +5 -173
- package/dist/commands/codebase-to-spec/dispatch-editor.js +1 -1
- package/dist/commands/codebase-to-spec/dispatch-spec.js +1 -1
- package/dist/commands/codebase-to-spec/index.js +7 -103
- package/dist/commands/codebase-to-spec/pack.js +8 -1
- package/dist/commands/codebase-to-spec/present-orchestrator.d.ts +3 -1
- package/dist/commands/codebase-to-spec/present-orchestrator.js +11 -4
- package/dist/templates/skills/codebase-to-spec/SKILL.md +10 -4
- package/package.json +1 -1
- package/dist/codebase-to-spec/edit-loop.d.ts +0 -54
- package/dist/codebase-to-spec/edit-loop.js +0 -195
- package/dist/codebase-to-spec/editor.d.ts +0 -54
- package/dist/codebase-to-spec/editor.js +0 -74
- package/dist/codebase-to-spec/fan-out.d.ts +0 -63
- package/dist/codebase-to-spec/fan-out.js +0 -215
- package/dist/codebase-to-spec/outline-review-loop.d.ts +0 -51
- package/dist/codebase-to-spec/outline-review-loop.js +0 -187
- package/dist/codebase-to-spec/planner.d.ts +0 -41
- package/dist/codebase-to-spec/planner.js +0 -76
- package/dist/codebase-to-spec/prompts/outline-reviewer.d.ts +0 -12
- package/dist/codebase-to-spec/prompts/outline-reviewer.js +0 -89
- package/dist/codebase-to-spec/slice.d.ts +0 -49
- package/dist/codebase-to-spec/slice.js +0 -111
- package/dist/codebase-to-spec/specifier.d.ts +0 -60
- package/dist/codebase-to-spec/specifier.js +0 -85
- package/dist/codebase-to-spec/summary.d.ts +0 -51
- package/dist/codebase-to-spec/summary.js +0 -183
- package/dist/commands/codebase-to-spec/compose.d.ts +0 -14
- package/dist/commands/codebase-to-spec/compose.js +0 -57
- package/dist/commands/codebase-to-spec/edit-loop.d.ts +0 -16
- package/dist/commands/codebase-to-spec/edit-loop.js +0 -83
- package/dist/commands/codebase-to-spec/fan-out.d.ts +0 -19
- package/dist/commands/codebase-to-spec/fan-out.js +0 -77
- package/dist/commands/codebase-to-spec/plan-loop.d.ts +0 -26
- package/dist/commands/codebase-to-spec/plan-loop.js +0 -105
- package/dist/commands/codebase-to-spec/present.d.ts +0 -26
- package/dist/commands/codebase-to-spec/present.js +0 -97
- package/dist/commands/codebase-to-spec/run.d.ts +0 -20
- package/dist/commands/codebase-to-spec/run.js +0 -86
- package/dist/commands/codebase-to-spec/specify-area.d.ts +0 -18
- package/dist/commands/codebase-to-spec/specify-area.js +0 -82
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Planner functions (initial and revise).
|
|
3
|
-
*
|
|
4
|
-
* Two modes correspond to two places the planner is invoked:
|
|
5
|
-
* - initial: first outline from the compressed pack (CTS-PLAN-1)
|
|
6
|
-
* - revise: address reviewer feedback — works for both
|
|
7
|
-
* `requires-another-review` (CTS-PLAN-5) and
|
|
8
|
-
* `approved-with-revisions` (CTS-PLAN-4). The orchestration
|
|
9
|
-
* decides whether to loop back to the reviewer or proceed to
|
|
10
|
-
* fan-out.
|
|
11
|
-
*
|
|
12
|
-
* Each mode is stateless — a fresh claude -p session per call.
|
|
13
|
-
*/
|
|
14
|
-
import { runClaude } from "./claude.js";
|
|
15
|
-
import { PLANNER_INITIAL_PROMPT } from "./prompts/planner-initial.js";
|
|
16
|
-
import { PLANNER_REVISE_PROMPT } from "./prompts/planner-revise.js";
|
|
17
|
-
import { OUTLINE_JSON_SCHEMA, parseOutline, } from "./schemas.js";
|
|
18
|
-
/**
|
|
19
|
-
* Run the planner in initial mode and return a parsed outline.
|
|
20
|
-
* Requirement: CTS-PLAN-1
|
|
21
|
-
*/
|
|
22
|
-
export async function runInitialPlanner(ctx) {
|
|
23
|
-
const runner = ctx.runner ?? runClaude;
|
|
24
|
-
const result = await runner({
|
|
25
|
-
systemPrompt: PLANNER_INITIAL_PROMPT,
|
|
26
|
-
userMessage: `The compressed packed codebase is at: ${ctx.overviewPath}\n\nRead it and produce the outline JSON described in your system prompt.`,
|
|
27
|
-
model: ctx.model,
|
|
28
|
-
tools: ["Read"],
|
|
29
|
-
addDirs: ctx.addDirs,
|
|
30
|
-
jsonSchema: OUTLINE_JSON_SCHEMA,
|
|
31
|
-
});
|
|
32
|
-
if (result.exitCode !== 0) {
|
|
33
|
-
throw new Error(`Planner failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);
|
|
34
|
-
}
|
|
35
|
-
return parseOutline(result.stdout);
|
|
36
|
-
}
|
|
37
|
-
/**
|
|
38
|
-
* Run the planner in revise mode — produce a new outline that addresses the
|
|
39
|
-
* reviewer's output. Handles both verdicts that trigger another planner pass:
|
|
40
|
-
* `requires-another-review` (categorized findings, judgment-based) and
|
|
41
|
-
* `approved-with-revisions` (explicit revisions list). The same prompt handles
|
|
42
|
-
* both shapes; the prompt switches behavior based on what's in the review.
|
|
43
|
-
*
|
|
44
|
-
* Requirements: CTS-PLAN-4, CTS-PLAN-5
|
|
45
|
-
*/
|
|
46
|
-
export async function runRevisingPlanner(ctx, priorOutline, review) {
|
|
47
|
-
const runner = ctx.runner ?? runClaude;
|
|
48
|
-
const userMessage = [
|
|
49
|
-
`The compressed packed codebase is at: ${ctx.overviewPath}`,
|
|
50
|
-
``,
|
|
51
|
-
`## Prior outline`,
|
|
52
|
-
`\`\`\`json`,
|
|
53
|
-
JSON.stringify(priorOutline, null, 2),
|
|
54
|
-
`\`\`\``,
|
|
55
|
-
``,
|
|
56
|
-
`## Reviewer output`,
|
|
57
|
-
`\`\`\`json`,
|
|
58
|
-
JSON.stringify(review, null, 2),
|
|
59
|
-
`\`\`\``,
|
|
60
|
-
``,
|
|
61
|
-
`Produce a revised outline JSON that addresses the reviewer's output. Output JSON only.`,
|
|
62
|
-
].join("\n");
|
|
63
|
-
const result = await runner({
|
|
64
|
-
systemPrompt: PLANNER_REVISE_PROMPT,
|
|
65
|
-
userMessage,
|
|
66
|
-
model: ctx.model,
|
|
67
|
-
tools: ["Read"],
|
|
68
|
-
addDirs: ctx.addDirs,
|
|
69
|
-
jsonSchema: OUTLINE_JSON_SCHEMA,
|
|
70
|
-
});
|
|
71
|
-
if (result.exitCode !== 0) {
|
|
72
|
-
throw new Error(`Revising planner failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);
|
|
73
|
-
}
|
|
74
|
-
return parseOutline(result.stdout);
|
|
75
|
-
}
|
|
76
|
-
//# sourceMappingURL=planner.js.map
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* System prompt for the outline reviewer.
|
|
3
|
-
*
|
|
4
|
-
* Stateful across review turns (same conversation, same session-id). Reads
|
|
5
|
-
* the outline and the compressed pack, produces a JSON object with
|
|
6
|
-
* categorized findings and a verdict.
|
|
7
|
-
*
|
|
8
|
-
* Requirements covered:
|
|
9
|
-
* - CTS-PLAN-2: Outline reviewer critiques the outline in a stateful session
|
|
10
|
-
*/
|
|
11
|
-
export declare const OUTLINE_REVIEWER_PROMPT = "You are an outline reviewer for a codebase-to-spec pipeline. The pipeline takes a codebase, generates a planning outline (areas of behavior), then fans out specifier agents to produce detailed requirements per area. Your job: gate fan-out on outline quality. Bad outlines \u2192 wasted specifier work.\n\nThis is a **stateful conversation**. Across turns, you may receive multiple revisions of the outline, each addressing prior feedback. Track what you asked for and whether the planner addressed it.\n\nOutput a JSON object matching the supplied schema. No prose, no markdown fences.\n\n## What you receive on each turn\n\n- The first turn includes the compressed packed codebase and the planner's first outline JSON.\n- Each subsequent turn includes a revised outline JSON. The codebase is unchanged.\n- Some turns may include a convergence nudge \u2014 read and respect it.\n\n## What counts as a customer\n\nThe outline's summary should describe what the system is and who it's for. The \"who\" is the customer \u2014 the kind of person whose needs shape what counts as behavior.\n\nA useful customer description is **specific enough to shape behavior** \u2014 it goes one level deeper than generic categories like \"end-user,\" \"administrator,\" or \"developer.\"\n\n- Not \"an end-user\" but \"a shopper\" or \"a guest checking out without an account.\"\n- Not \"an administrator\" but \"a store manager who fulfills orders\" and \"a business owner who runs reports.\"\n- Not \"a developer\" but \"a React developer integrating an eCommerce SDK,\" \"a Python data engineer building ETL pipelines,\" or \"a distributed-systems engineer wiring up a message broker.\"\n\nMost large or sprawling codebases serve more than one customer. A system whose outline reads as if built for a single customer when the code clearly serves several is missing something \u2014 and surfacing that gap is one of the most useful things you can do.\n\n**Customers consume the software; contributors work on it.** A developer can be a legitimate customer when they consume the software being specified \u2014 a React developer integrating an SDK, a Python data engineer using a library, an operator running a CLI in CI, a contributor to an open-source project who uses it as much as they extend it. But a developer whose only role is to *work on this codebase* \u2014 described as \"a contributor,\" \"an internal maintainer,\" \"a stage author building the next feature,\" or similar \u2014 is not a customer. They're the audience for code comments and architecture docs, not for behavioral requirements. Data contracts between architectural components can still be (and often should be) specified, but think about whose experience they matter for. If an interface mediates business logic between a front-end and a server, that logic should be specified in terms of what it does for the user, not what it does for the front-end developer.\n\n## What to evaluate\n\nThe outline names its customers in the summary and breaks the system into areas. Your evaluation has two parts.\n\n### Part 1 \u2014 Per-area outcome checks\n\nFor each area, apply these four criteria:\n\n1. **Relevant to a customer.** Each area must declare at least one customer in its `customers` field. Apply the consume-vs-work-on test from \"What counts as a customer\" above: a customer is someone who *uses* the software being specified, not someone who works on its codebase. An area whose `customers` field is empty, missing, or contains only developers-of-this-codebase (contributors, maintainers, stage authors) is a `framing_error` \u2014 propose either reframing the area for a real customer or dropping it. When the area's description is written in mechanism-only voice (\"the subprocess wrapper that spawns...\", \"how the pipeline generates...\") with no customer named, that's the same finding even if a customer name was bolted on after the fact.\n2. **Speaks the customer's vocabulary.** Would the relevant customer go looking for this behavior under this area's name? The same name might be right for one kind of customer and wrong for another \u2014 what matters is whether it matches whom this area serves.\n3. **Groups a collection of functionality.** Does the area cover multiple related behaviors with a shared customer-meaningful purpose? An area with one isolated function, or a \"miscellaneous\" bucket of unrelated things, fails this test.\n4. **Has customer-observable outcomes.** Could the relevant customer verify whether the behavior is present or absent (return value, visible UI state, logged event, thrown error)? \"The system manages memory efficiently\" is true but not customer-observable.\n\nFailures of criterion 1, 2, or 4 are `framing_errors`. Failures of criterion 3 are `granularity_issues` \u2014 which also covers sizing problems more broadly.\n\n#### On sizing\n\nThink of organizing a big box of 100 crayons.\n\n- One drawer for all 100 crayons \u2192 impossible to find what you need.\n- 100 drawers, one crayon each \u2192 you've recreated the same problem with different semantics.\n- Organize by ROYGBIV \u2192 each drawer is a meaningful group, and you can find any crayon quickly.\n\nThe same logic applies to areas. An area too broad covers fundamentally distinct concerns; an area too narrow fragments what should hang together. Two areas that describe the same thing from different angles are a sizing problem \u2014 they should be one area, or split along a different axis. The right sizing for *this* codebase is whatever lets each area be coherent on its own and the whole set be complete.\n\n### Part 2 \u2014 Coverage and file assignment\n\n- What behavior is in the codebase but missing from any area? \u2192 `coverage_gaps`. Gaps matter most when they map to something a real customer would expect.\n- Are file paths actually present in the pack as written? Are files assigned to areas where they don't fit? Are public-contract docs (README, package metadata, LICENSE, CHANGELOG) unassigned? \u2192 `file_assignment_issues`.\n\n## On second and later turns\n\nAlso evaluate:\n\n- Did the revision address what you asked for in the prior turn? Be honest if it did or didn't.\n- Did the revision introduce new problems? Sometimes fixing one gap creates another.\n\n## Findings must be actionable\n\nA finding is only useful if the planner can act on it. Two principles:\n\n**Show your reasoning.** If your finding rests on a judgment about who the system is for, what the customer would want, or how an area should be reshaped, surface that reasoning. \"This outline doesn't read like it's for any specific customer\" gives the planner nothing to act on. \"I think this is most plausibly for a React developer integrating an eCommerce SDK; areas X and Y are organized around backend storage rather than what that developer would reach for; suggest reframing as Z\" does. Same pattern for any other \"this feels off\" finding \u2014 propose the alternative.\n\n**Be specific.** Cite paths and area names by exact spelling. \"Could be more comprehensive\" is not actionable. \"The outline has no area covering [behavior X], visible in [file Y]\" is.\n\n## Verdict types\n\nThe `verdict` field is exactly one of:\n\n- `approved` \u2014 outline is ready for fan-out as-is. No findings, or findings are negligible. Reserve for genuinely good outlines.\n- `approved-with-revisions` \u2014 outline is fundamentally sound and ready for fan-out, but includes specific small revisions that should be applied first. List the revisions in the `revisions` array. The planner will apply them mechanically without further review. Use for inline tweaks: rename a file path, split one bloated area into two, add a missing public-contract file to an area, tighten the customer description in the summary.\n- `requires-another-review` \u2014 outline has meaningful issues that need a structural fix, not just tweaks. Coverage gaps for whole subsystems, framing errors at the area level, customer set in the summary wrong or incomplete in ways that ripple through area design. The planner needs to think again, not just tweak.";
|
|
12
|
-
//# sourceMappingURL=outline-reviewer.d.ts.map
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* System prompt for the outline reviewer.
|
|
3
|
-
*
|
|
4
|
-
* Stateful across review turns (same conversation, same session-id). Reads
|
|
5
|
-
* the outline and the compressed pack, produces a JSON object with
|
|
6
|
-
* categorized findings and a verdict.
|
|
7
|
-
*
|
|
8
|
-
* Requirements covered:
|
|
9
|
-
* - CTS-PLAN-2: Outline reviewer critiques the outline in a stateful session
|
|
10
|
-
*/
|
|
11
|
-
export const OUTLINE_REVIEWER_PROMPT = `You are an outline reviewer for a codebase-to-spec pipeline. The pipeline takes a codebase, generates a planning outline (areas of behavior), then fans out specifier agents to produce detailed requirements per area. Your job: gate fan-out on outline quality. Bad outlines → wasted specifier work.
|
|
12
|
-
|
|
13
|
-
This is a **stateful conversation**. Across turns, you may receive multiple revisions of the outline, each addressing prior feedback. Track what you asked for and whether the planner addressed it.
|
|
14
|
-
|
|
15
|
-
Output a JSON object matching the supplied schema. No prose, no markdown fences.
|
|
16
|
-
|
|
17
|
-
## What you receive on each turn
|
|
18
|
-
|
|
19
|
-
- The first turn includes the compressed packed codebase and the planner's first outline JSON.
|
|
20
|
-
- Each subsequent turn includes a revised outline JSON. The codebase is unchanged.
|
|
21
|
-
- Some turns may include a convergence nudge — read and respect it.
|
|
22
|
-
|
|
23
|
-
## What counts as a customer
|
|
24
|
-
|
|
25
|
-
The outline's summary should describe what the system is and who it's for. The "who" is the customer — the kind of person whose needs shape what counts as behavior.
|
|
26
|
-
|
|
27
|
-
A useful customer description is **specific enough to shape behavior** — it goes one level deeper than generic categories like "end-user," "administrator," or "developer."
|
|
28
|
-
|
|
29
|
-
- Not "an end-user" but "a shopper" or "a guest checking out without an account."
|
|
30
|
-
- Not "an administrator" but "a store manager who fulfills orders" and "a business owner who runs reports."
|
|
31
|
-
- Not "a developer" but "a React developer integrating an eCommerce SDK," "a Python data engineer building ETL pipelines," or "a distributed-systems engineer wiring up a message broker."
|
|
32
|
-
|
|
33
|
-
Most large or sprawling codebases serve more than one customer. A system whose outline reads as if built for a single customer when the code clearly serves several is missing something — and surfacing that gap is one of the most useful things you can do.
|
|
34
|
-
|
|
35
|
-
**Customers consume the software; contributors work on it.** A developer can be a legitimate customer when they consume the software being specified — a React developer integrating an SDK, a Python data engineer using a library, an operator running a CLI in CI, a contributor to an open-source project who uses it as much as they extend it. But a developer whose only role is to *work on this codebase* — described as "a contributor," "an internal maintainer," "a stage author building the next feature," or similar — is not a customer. They're the audience for code comments and architecture docs, not for behavioral requirements. Data contracts between architectural components can still be (and often should be) specified, but think about whose experience they matter for. If an interface mediates business logic between a front-end and a server, that logic should be specified in terms of what it does for the user, not what it does for the front-end developer.
|
|
36
|
-
|
|
37
|
-
## What to evaluate
|
|
38
|
-
|
|
39
|
-
The outline names its customers in the summary and breaks the system into areas. Your evaluation has two parts.
|
|
40
|
-
|
|
41
|
-
### Part 1 — Per-area outcome checks
|
|
42
|
-
|
|
43
|
-
For each area, apply these four criteria:
|
|
44
|
-
|
|
45
|
-
1. **Relevant to a customer.** Each area must declare at least one customer in its \`customers\` field. Apply the consume-vs-work-on test from "What counts as a customer" above: a customer is someone who *uses* the software being specified, not someone who works on its codebase. An area whose \`customers\` field is empty, missing, or contains only developers-of-this-codebase (contributors, maintainers, stage authors) is a \`framing_error\` — propose either reframing the area for a real customer or dropping it. When the area's description is written in mechanism-only voice ("the subprocess wrapper that spawns...", "how the pipeline generates...") with no customer named, that's the same finding even if a customer name was bolted on after the fact.
|
|
46
|
-
2. **Speaks the customer's vocabulary.** Would the relevant customer go looking for this behavior under this area's name? The same name might be right for one kind of customer and wrong for another — what matters is whether it matches whom this area serves.
|
|
47
|
-
3. **Groups a collection of functionality.** Does the area cover multiple related behaviors with a shared customer-meaningful purpose? An area with one isolated function, or a "miscellaneous" bucket of unrelated things, fails this test.
|
|
48
|
-
4. **Has customer-observable outcomes.** Could the relevant customer verify whether the behavior is present or absent (return value, visible UI state, logged event, thrown error)? "The system manages memory efficiently" is true but not customer-observable.
|
|
49
|
-
|
|
50
|
-
Failures of criterion 1, 2, or 4 are \`framing_errors\`. Failures of criterion 3 are \`granularity_issues\` — which also covers sizing problems more broadly.
|
|
51
|
-
|
|
52
|
-
#### On sizing
|
|
53
|
-
|
|
54
|
-
Think of organizing a big box of 100 crayons.
|
|
55
|
-
|
|
56
|
-
- One drawer for all 100 crayons → impossible to find what you need.
|
|
57
|
-
- 100 drawers, one crayon each → you've recreated the same problem with different semantics.
|
|
58
|
-
- Organize by ROYGBIV → each drawer is a meaningful group, and you can find any crayon quickly.
|
|
59
|
-
|
|
60
|
-
The same logic applies to areas. An area too broad covers fundamentally distinct concerns; an area too narrow fragments what should hang together. Two areas that describe the same thing from different angles are a sizing problem — they should be one area, or split along a different axis. The right sizing for *this* codebase is whatever lets each area be coherent on its own and the whole set be complete.
|
|
61
|
-
|
|
62
|
-
### Part 2 — Coverage and file assignment
|
|
63
|
-
|
|
64
|
-
- What behavior is in the codebase but missing from any area? → \`coverage_gaps\`. Gaps matter most when they map to something a real customer would expect.
|
|
65
|
-
- Are file paths actually present in the pack as written? Are files assigned to areas where they don't fit? Are public-contract docs (README, package metadata, LICENSE, CHANGELOG) unassigned? → \`file_assignment_issues\`.
|
|
66
|
-
|
|
67
|
-
## On second and later turns
|
|
68
|
-
|
|
69
|
-
Also evaluate:
|
|
70
|
-
|
|
71
|
-
- Did the revision address what you asked for in the prior turn? Be honest if it did or didn't.
|
|
72
|
-
- Did the revision introduce new problems? Sometimes fixing one gap creates another.
|
|
73
|
-
|
|
74
|
-
## Findings must be actionable
|
|
75
|
-
|
|
76
|
-
A finding is only useful if the planner can act on it. Two principles:
|
|
77
|
-
|
|
78
|
-
**Show your reasoning.** If your finding rests on a judgment about who the system is for, what the customer would want, or how an area should be reshaped, surface that reasoning. "This outline doesn't read like it's for any specific customer" gives the planner nothing to act on. "I think this is most plausibly for a React developer integrating an eCommerce SDK; areas X and Y are organized around backend storage rather than what that developer would reach for; suggest reframing as Z" does. Same pattern for any other "this feels off" finding — propose the alternative.
|
|
79
|
-
|
|
80
|
-
**Be specific.** Cite paths and area names by exact spelling. "Could be more comprehensive" is not actionable. "The outline has no area covering [behavior X], visible in [file Y]" is.
|
|
81
|
-
|
|
82
|
-
## Verdict types
|
|
83
|
-
|
|
84
|
-
The \`verdict\` field is exactly one of:
|
|
85
|
-
|
|
86
|
-
- \`approved\` — outline is ready for fan-out as-is. No findings, or findings are negligible. Reserve for genuinely good outlines.
|
|
87
|
-
- \`approved-with-revisions\` — outline is fundamentally sound and ready for fan-out, but includes specific small revisions that should be applied first. List the revisions in the \`revisions\` array. The planner will apply them mechanically without further review. Use for inline tweaks: rename a file path, split one bloated area into two, add a missing public-contract file to an area, tighten the customer description in the summary.
|
|
88
|
-
- \`requires-another-review\` — outline has meaningful issues that need a structural fix, not just tweaks. Coverage gaps for whole subsystems, framing errors at the area level, customer set in the summary wrong or incomplete in ways that ripple through area design. The planner needs to think again, not just tweak.`;
|
|
89
|
-
//# sourceMappingURL=outline-reviewer.js.map
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slice extraction: given a Repomix pack and a list of file paths (or
|
|
3
|
-
* directory-prefix paths), produce a smaller pack containing only the matching
|
|
4
|
-
* files.
|
|
5
|
-
*
|
|
6
|
-
* Pack format (from Repomix --style plain):
|
|
7
|
-
*
|
|
8
|
-
* ================
|
|
9
|
-
* File: path/to/file
|
|
10
|
-
* ================
|
|
11
|
-
* <file contents>
|
|
12
|
-
*
|
|
13
|
-
* ================
|
|
14
|
-
* File: next/file
|
|
15
|
-
* ================
|
|
16
|
-
* ...
|
|
17
|
-
*
|
|
18
|
-
* We preserve the pack header (everything before the first File: section) and
|
|
19
|
-
* the matching sections.
|
|
20
|
-
*
|
|
21
|
-
* Requirements covered:
|
|
22
|
-
* - CTS-SPEC-1: CLI fans out one specifier worker per area; each worker
|
|
23
|
-
* receives a slice extracted from the uncompressed pack
|
|
24
|
-
*/
|
|
25
|
-
/**
|
|
26
|
-
* Return true when `path` matches one of the entries in `wanted`.
|
|
27
|
-
*
|
|
28
|
-
* Each entry can be:
|
|
29
|
-
* - An exact file path (e.g., `src/foo.ts`) — matches that exact path.
|
|
30
|
-
* - A directory prefix ending in `/` (e.g., `src/services/browser/`) — matches
|
|
31
|
-
* any file under that directory tree.
|
|
32
|
-
*/
|
|
33
|
-
export declare function pathMatchesWanted(path: string, wanted: Iterable<string>): boolean;
|
|
34
|
-
export interface SliceExtractionResult {
|
|
35
|
-
/** Number of file sections matched (and written to the output). */
|
|
36
|
-
matched: number;
|
|
37
|
-
/** Total number of file sections in the input pack. */
|
|
38
|
-
total: number;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Extract sections matching `wanted` from the pack at `inputPath` and write
|
|
42
|
-
* them to `outputPath`. Preserves the pack header (Repomix metadata).
|
|
43
|
-
*/
|
|
44
|
-
export declare function extractSlice(inputPath: string, outputPath: string, wanted: Iterable<string>): SliceExtractionResult;
|
|
45
|
-
/**
|
|
46
|
-
* Pure variant operating on already-loaded text. Useful for tests.
|
|
47
|
-
*/
|
|
48
|
-
export declare function extractSliceFromText(text: string, outputPath: string, wanted: Iterable<string>): SliceExtractionResult;
|
|
49
|
-
//# sourceMappingURL=slice.d.ts.map
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Slice extraction: given a Repomix pack and a list of file paths (or
|
|
3
|
-
* directory-prefix paths), produce a smaller pack containing only the matching
|
|
4
|
-
* files.
|
|
5
|
-
*
|
|
6
|
-
* Pack format (from Repomix --style plain):
|
|
7
|
-
*
|
|
8
|
-
* ================
|
|
9
|
-
* File: path/to/file
|
|
10
|
-
* ================
|
|
11
|
-
* <file contents>
|
|
12
|
-
*
|
|
13
|
-
* ================
|
|
14
|
-
* File: next/file
|
|
15
|
-
* ================
|
|
16
|
-
* ...
|
|
17
|
-
*
|
|
18
|
-
* We preserve the pack header (everything before the first File: section) and
|
|
19
|
-
* the matching sections.
|
|
20
|
-
*
|
|
21
|
-
* Requirements covered:
|
|
22
|
-
* - CTS-SPEC-1: CLI fans out one specifier worker per area; each worker
|
|
23
|
-
* receives a slice extracted from the uncompressed pack
|
|
24
|
-
*/
|
|
25
|
-
import { readFileSync, writeFileSync } from "node:fs";
|
|
26
|
-
const SEPARATOR = "================";
|
|
27
|
-
const FILE_PREFIX = "File: ";
|
|
28
|
-
/**
|
|
29
|
-
* Return true when `path` matches one of the entries in `wanted`.
|
|
30
|
-
*
|
|
31
|
-
* Each entry can be:
|
|
32
|
-
* - An exact file path (e.g., `src/foo.ts`) — matches that exact path.
|
|
33
|
-
* - A directory prefix ending in `/` (e.g., `src/services/browser/`) — matches
|
|
34
|
-
* any file under that directory tree.
|
|
35
|
-
*/
|
|
36
|
-
export function pathMatchesWanted(path, wanted) {
|
|
37
|
-
for (const w of wanted) {
|
|
38
|
-
if (w === path)
|
|
39
|
-
return true;
|
|
40
|
-
if (w.endsWith("/") && path.startsWith(w))
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Extract sections matching `wanted` from the pack at `inputPath` and write
|
|
47
|
-
* them to `outputPath`. Preserves the pack header (Repomix metadata).
|
|
48
|
-
*/
|
|
49
|
-
export function extractSlice(inputPath, outputPath, wanted) {
|
|
50
|
-
const wantedSet = new Set(wanted);
|
|
51
|
-
const text = readFileSync(inputPath, "utf-8");
|
|
52
|
-
return extractSliceFromText(text, outputPath, wantedSet);
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Pure variant operating on already-loaded text. Useful for tests.
|
|
56
|
-
*/
|
|
57
|
-
export function extractSliceFromText(text, outputPath, wanted) {
|
|
58
|
-
const wantedSet = wanted instanceof Set ? wanted : new Set(wanted);
|
|
59
|
-
const lines = text.split("\n");
|
|
60
|
-
const out = [];
|
|
61
|
-
// Find the start of the first File: section.
|
|
62
|
-
let firstFileIdx = -1;
|
|
63
|
-
for (let i = 0; i + 1 < lines.length; i++) {
|
|
64
|
-
if (lines[i].trim() === SEPARATOR && lines[i + 1].startsWith(FILE_PREFIX)) {
|
|
65
|
-
firstFileIdx = i;
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
if (firstFileIdx === -1) {
|
|
70
|
-
throw new Error("Input pack has no File: sections");
|
|
71
|
-
}
|
|
72
|
-
// Preserve the pack header (lines 0..firstFileIdx-1).
|
|
73
|
-
for (let i = 0; i < firstFileIdx; i++) {
|
|
74
|
-
out.push(lines[i]);
|
|
75
|
-
}
|
|
76
|
-
let matched = 0;
|
|
77
|
-
let total = 0;
|
|
78
|
-
let i = firstFileIdx;
|
|
79
|
-
while (i < lines.length) {
|
|
80
|
-
if (lines[i].trim() === SEPARATOR &&
|
|
81
|
-
i + 1 < lines.length &&
|
|
82
|
-
lines[i + 1].startsWith(FILE_PREFIX)) {
|
|
83
|
-
const path = lines[i + 1].slice(FILE_PREFIX.length).trim();
|
|
84
|
-
total++;
|
|
85
|
-
// Find the end of this section (next ====/File: pair or EOF).
|
|
86
|
-
let j = i + 3; // past the closing separator
|
|
87
|
-
while (j < lines.length) {
|
|
88
|
-
if (lines[j].trim() === SEPARATOR &&
|
|
89
|
-
j + 1 < lines.length &&
|
|
90
|
-
lines[j + 1].startsWith(FILE_PREFIX)) {
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
j++;
|
|
94
|
-
}
|
|
95
|
-
const contentEnd = j; // exclusive
|
|
96
|
-
if (pathMatchesWanted(path, wantedSet)) {
|
|
97
|
-
matched++;
|
|
98
|
-
for (let k = i; k < contentEnd; k++) {
|
|
99
|
-
out.push(lines[k]);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
i = j;
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
i++;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
writeFileSync(outputPath, out.join("\n"), "utf-8");
|
|
109
|
-
return { matched, total };
|
|
110
|
-
}
|
|
111
|
-
//# sourceMappingURL=slice.js.map
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Specifier worker: run a single specifier for one area.
|
|
3
|
-
*
|
|
4
|
-
* The specifier is given its slice + the outline + a target partial path, and
|
|
5
|
-
* it orchestrates its own work via tools (Read, Write, Edit, Grep, Glob, Bash).
|
|
6
|
-
* Self-style-check happens via `Bash dotrequirements cts style-check <path>`.
|
|
7
|
-
*
|
|
8
|
-
* Requirements covered:
|
|
9
|
-
* - CTS-SPEC-1: per-area worker invocation
|
|
10
|
-
* - CTS-SPEC-2: write partial to known path via Write tool
|
|
11
|
-
* - CTS-SPEC-3: self-style-check via Bash
|
|
12
|
-
* - CTS-SPEC-4: access to the full pack for cross-area context
|
|
13
|
-
* - CTS-SPEC-5: failure detection and retry orchestrated by fan-out (this file
|
|
14
|
-
* produces a single attempt; fan-out wraps it with retry policy)
|
|
15
|
-
*/
|
|
16
|
-
import { type ClaudeRunner } from "./claude.js";
|
|
17
|
-
import type { Area, Outline } from "./schemas.js";
|
|
18
|
-
export interface SpecifierContext {
|
|
19
|
-
outline: Outline;
|
|
20
|
-
area: Area;
|
|
21
|
-
/** Path to the area's slice (extracted from the uncompressed pack). */
|
|
22
|
-
slicePath: string;
|
|
23
|
-
/** Path to the full uncompressed pack (for cross-area discovery). */
|
|
24
|
-
fullPackPath: string;
|
|
25
|
-
/** Where the specifier should write its partial. */
|
|
26
|
-
partialPath: string;
|
|
27
|
-
/**
|
|
28
|
-
* The command the specifier should run to invoke schema validation on its
|
|
29
|
-
* own partial — typically `dotrequirements cts validate`. Run BEFORE
|
|
30
|
-
* style-check.
|
|
31
|
-
*/
|
|
32
|
-
validateCommand: string;
|
|
33
|
-
/**
|
|
34
|
-
* The command the specifier should run to invoke style-check on its own
|
|
35
|
-
* partial — typically `dotrequirements cts style-check`. Run AFTER
|
|
36
|
-
* validate.
|
|
37
|
-
*/
|
|
38
|
-
styleCheckCommand: string;
|
|
39
|
-
/** Directories the agent should have read+write access to. */
|
|
40
|
-
addDirs: string[];
|
|
41
|
-
runner?: ClaudeRunner;
|
|
42
|
-
model?: string;
|
|
43
|
-
}
|
|
44
|
-
export interface SpecifierResult {
|
|
45
|
-
/** True if the agent wrote a non-empty partial file at the expected path. */
|
|
46
|
-
wrotePartial: boolean;
|
|
47
|
-
/** Size of the partial in bytes, or 0 if missing. */
|
|
48
|
-
partialBytes: number;
|
|
49
|
-
/** Process exit code. */
|
|
50
|
-
exitCode: number;
|
|
51
|
-
/** Captured stdout. */
|
|
52
|
-
stdout: string;
|
|
53
|
-
/** Captured stderr. */
|
|
54
|
-
stderr: string;
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Run a single specifier. Returns details about whether it succeeded.
|
|
58
|
-
*/
|
|
59
|
-
export declare function runSpecifier(ctx: SpecifierContext): Promise<SpecifierResult>;
|
|
60
|
-
//# sourceMappingURL=specifier.d.ts.map
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Specifier worker: run a single specifier for one area.
|
|
3
|
-
*
|
|
4
|
-
* The specifier is given its slice + the outline + a target partial path, and
|
|
5
|
-
* it orchestrates its own work via tools (Read, Write, Edit, Grep, Glob, Bash).
|
|
6
|
-
* Self-style-check happens via `Bash dotrequirements cts style-check <path>`.
|
|
7
|
-
*
|
|
8
|
-
* Requirements covered:
|
|
9
|
-
* - CTS-SPEC-1: per-area worker invocation
|
|
10
|
-
* - CTS-SPEC-2: write partial to known path via Write tool
|
|
11
|
-
* - CTS-SPEC-3: self-style-check via Bash
|
|
12
|
-
* - CTS-SPEC-4: access to the full pack for cross-area context
|
|
13
|
-
* - CTS-SPEC-5: failure detection and retry orchestrated by fan-out (this file
|
|
14
|
-
* produces a single attempt; fan-out wraps it with retry policy)
|
|
15
|
-
*/
|
|
16
|
-
import { existsSync, statSync } from "node:fs";
|
|
17
|
-
import { runClaude } from "./claude.js";
|
|
18
|
-
import { SPECIFIER_PROMPT } from "./prompts/specifier.js";
|
|
19
|
-
function buildUserMessage(ctx) {
|
|
20
|
-
return [
|
|
21
|
-
`You are specifying ONE area of the system.`,
|
|
22
|
-
``,
|
|
23
|
-
`Area name: ${ctx.area.name}`,
|
|
24
|
-
`Area description: ${ctx.area.description}`,
|
|
25
|
-
`Document defaultPrefix: ${ctx.outline.defaultPrefix}`,
|
|
26
|
-
`Area prefix: ${ctx.area.prefix}`,
|
|
27
|
-
``,
|
|
28
|
-
`## Customers this area serves`,
|
|
29
|
-
`(Pick one of these as the named persona for your requirements. Do not invent a different customer. If none of these is a real user of the software — e.g., all entries describe a contributor to this codebase — follow the AREA-LACKS-CUSTOMER escape in your system prompt instead of writing requirements.)`,
|
|
30
|
-
`\`\`\`json`,
|
|
31
|
-
JSON.stringify(ctx.area.customers, null, 2),
|
|
32
|
-
`\`\`\``,
|
|
33
|
-
`Use full requirement IDs of the form: ${ctx.outline.defaultPrefix}-${ctx.area.prefix}-1, ${ctx.outline.defaultPrefix}-${ctx.area.prefix}-2, etc. (sequential, 1-indexed, no zero-padding).`,
|
|
34
|
-
``,
|
|
35
|
-
`## Paths`,
|
|
36
|
-
`- Slice (your area's files): ${ctx.slicePath}`,
|
|
37
|
-
`- Full uncompressed pack (for discovering behaviors in tests/recipes/docs): ${ctx.fullPackPath}`,
|
|
38
|
-
`- Where to write your partial: ${ctx.partialPath}`,
|
|
39
|
-
`- Validate command (run FIRST after writing your draft — deterministic syntax check):`,
|
|
40
|
-
` Bash: ${ctx.validateCommand} ${ctx.partialPath}`,
|
|
41
|
-
`- Style-check command (run SECOND, only after validate passes — AI clarity feedback):`,
|
|
42
|
-
` Bash: ${ctx.styleCheckCommand} ${ctx.partialPath}`,
|
|
43
|
-
``,
|
|
44
|
-
`## Full system outline (so you know what is in scope vs. not)`,
|
|
45
|
-
`\`\`\`json`,
|
|
46
|
-
JSON.stringify(ctx.outline, null, 2),
|
|
47
|
-
`\`\`\``,
|
|
48
|
-
``,
|
|
49
|
-
`Follow the three-phase workflow in your system prompt: draft (Phase A) → validate (Phase B) → style-check (Phase C) → confirm.`,
|
|
50
|
-
].join("\n");
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Run a single specifier. Returns details about whether it succeeded.
|
|
54
|
-
*/
|
|
55
|
-
export async function runSpecifier(ctx) {
|
|
56
|
-
const runner = ctx.runner ?? runClaude;
|
|
57
|
-
const result = await runner({
|
|
58
|
-
systemPrompt: SPECIFIER_PROMPT,
|
|
59
|
-
userMessage: buildUserMessage(ctx),
|
|
60
|
-
model: ctx.model,
|
|
61
|
-
tools: ["Read", "Write", "Edit", "Grep", "Glob", "Bash"],
|
|
62
|
-
addDirs: ctx.addDirs,
|
|
63
|
-
});
|
|
64
|
-
// Inspect the partial file to determine whether the specifier wrote
|
|
65
|
-
// something usable.
|
|
66
|
-
let wrotePartial = false;
|
|
67
|
-
let partialBytes = 0;
|
|
68
|
-
if (existsSync(ctx.partialPath)) {
|
|
69
|
-
try {
|
|
70
|
-
partialBytes = statSync(ctx.partialPath).size;
|
|
71
|
-
wrotePartial = partialBytes > 0;
|
|
72
|
-
}
|
|
73
|
-
catch {
|
|
74
|
-
// ignore; treat as not written
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return {
|
|
78
|
-
wrotePartial,
|
|
79
|
-
partialBytes,
|
|
80
|
-
exitCode: result.exitCode,
|
|
81
|
-
stdout: result.stdout,
|
|
82
|
-
stderr: result.stderr,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
//# sourceMappingURL=specifier.js.map
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pipeline summary generation.
|
|
3
|
-
*
|
|
4
|
-
* Reads cached artifacts to assemble a structured summary of what the
|
|
5
|
-
* pipeline produced. Surfaced both as JSON (parseable by wrappers like the
|
|
6
|
-
* skill) and as a short human-readable block.
|
|
7
|
-
*
|
|
8
|
-
* Requirements covered:
|
|
9
|
-
* - CTS-PRESENT-4: Final pipeline summary is surfaced
|
|
10
|
-
* - CTS-OBSERVE-2 (partial): structured failure information available
|
|
11
|
-
*/
|
|
12
|
-
import type { CachePaths } from "./cache.js";
|
|
13
|
-
import { type Outline } from "./schemas.js";
|
|
14
|
-
export interface PipelineSummary {
|
|
15
|
-
totalAreas: number;
|
|
16
|
-
totalRequirements: number;
|
|
17
|
-
outline: {
|
|
18
|
-
turnsUsed: number;
|
|
19
|
-
finalVerdict: string | null;
|
|
20
|
-
residualNotes: string[];
|
|
21
|
-
};
|
|
22
|
-
specifiers: {
|
|
23
|
-
completed: number;
|
|
24
|
-
missing: number;
|
|
25
|
-
/** Area names that have no usable partial. */
|
|
26
|
-
missingAreas: string[];
|
|
27
|
-
};
|
|
28
|
-
specReview: {
|
|
29
|
-
turnsUsed: number;
|
|
30
|
-
finalVerdict: string | null;
|
|
31
|
-
residualNotes: string[];
|
|
32
|
-
};
|
|
33
|
-
outputs: {
|
|
34
|
-
/** Paths under .requirements/ that were written. */
|
|
35
|
-
paths: string[];
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
export interface BuildSummaryInput {
|
|
39
|
-
outline: Outline;
|
|
40
|
-
paths: CachePaths;
|
|
41
|
-
/** Paths the present stage wrote (under .requirements/). */
|
|
42
|
-
outputPaths: string[];
|
|
43
|
-
}
|
|
44
|
-
export declare function buildPipelineSummary(input: BuildSummaryInput): PipelineSummary;
|
|
45
|
-
/**
|
|
46
|
-
* Render a short human-readable block for the summary. Designed to fit on a
|
|
47
|
-
* small number of lines (CTS-PRESENT-4.2). Wrappers that want richer
|
|
48
|
-
* presentation can read the JSON form instead.
|
|
49
|
-
*/
|
|
50
|
-
export declare function renderSummaryText(summary: PipelineSummary): string;
|
|
51
|
-
//# sourceMappingURL=summary.d.ts.map
|