@popoverai/dotrequirements 0.24.0 → 0.24.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +4 -3
  2. package/dist/cli.js +0 -0
  3. package/dist/codebase-to-spec/claude.d.ts +1 -0
  4. package/dist/codebase-to-spec/claude.js +9 -0
  5. package/dist/codebase-to-spec/pack.d.ts +16 -0
  6. package/dist/codebase-to-spec/pack.js +17 -3
  7. package/dist/codebase-to-spec/present.d.ts +8 -1
  8. package/dist/codebase-to-spec/present.js +7 -4
  9. package/dist/codebase-to-spec/progress.d.ts +6 -0
  10. package/dist/codebase-to-spec/progress.js +34 -0
  11. package/dist/codebase-to-spec/prompts/outline-reviewer.d.ts +1 -1
  12. package/dist/codebase-to-spec/prompts/outline-reviewer.js +3 -1
  13. package/dist/codebase-to-spec/prompts/planner-initial.d.ts +1 -1
  14. package/dist/codebase-to-spec/prompts/planner-initial.js +4 -0
  15. package/dist/codebase-to-spec/prompts/planner-revise.d.ts +1 -1
  16. package/dist/codebase-to-spec/prompts/planner-revise.js +2 -2
  17. package/dist/codebase-to-spec/prompts/spec-reviewer.d.ts +1 -1
  18. package/dist/codebase-to-spec/prompts/spec-reviewer.js +6 -1
  19. package/dist/codebase-to-spec/prompts/specifier.d.ts +1 -1
  20. package/dist/codebase-to-spec/prompts/specifier.js +6 -4
  21. package/dist/codebase-to-spec/prompts/style-check.d.ts +10 -2
  22. package/dist/codebase-to-spec/prompts/style-check.js +76 -46
  23. package/dist/codebase-to-spec/schemas.d.ts +85 -1
  24. package/dist/codebase-to-spec/schemas.js +25 -1
  25. package/dist/codebase-to-spec/specifier.js +6 -0
  26. package/dist/commands/codebase-to-spec/index.js +13 -0
  27. package/dist/commands/codebase-to-spec/pack.d.ts +6 -0
  28. package/dist/commands/codebase-to-spec/pack.js +1 -0
  29. package/dist/commands/codebase-to-spec/present.d.ts +5 -0
  30. package/dist/commands/codebase-to-spec/present.js +6 -1
  31. package/dist/commands/codebase-to-spec/run.js +1 -0
  32. package/package.json +5 -6
  33. package/dist/codebase-to-spec/prompts/planner-apply.d.ts +0 -12
  34. package/dist/codebase-to-spec/prompts/planner-apply.js +0 -32
  35. package/dist/commands/browsertest.d.ts +0 -6
  36. package/dist/commands/browsertest.js +0 -212
  37. package/dist/commands/login.d.ts +0 -12
  38. package/dist/commands/login.js +0 -117
  39. package/dist/commands/logout.d.ts +0 -5
  40. package/dist/commands/logout.js +0 -17
  41. package/dist/commands/mcp-setup.d.ts +0 -5
  42. package/dist/commands/mcp-setup.js +0 -441
  43. package/dist/commands/test.d.ts +0 -6
  44. package/dist/commands/test.js +0 -72
  45. package/dist/mcp/grep.d.ts +0 -24
  46. package/dist/mcp/grep.js +0 -306
  47. package/dist/mcp/handlers/coverage.d.ts +0 -44
  48. package/dist/mcp/handlers/coverage.js +0 -103
  49. package/dist/mcp/requirements.d.ts +0 -57
  50. package/dist/mcp/requirements.js +0 -155
  51. package/dist/mcp/testCodeExtractor.d.ts +0 -22
  52. package/dist/mcp/testCodeExtractor.js +0 -150
  53. package/dist/mcp/types.d.ts +0 -27
  54. package/dist/mcp/types.js +0 -2
  55. package/dist/utils/local-project.d.ts +0 -31
  56. package/dist/utils/local-project.js +0 -33
  57. package/dist/utils/token-refresh.d.ts +0 -24
  58. package/dist/utils/token-refresh.js +0 -69
  59. package/dist/utils/token-storage.d.ts +0 -31
  60. package/dist/utils/token-storage.js +0 -57
@@ -2,11 +2,19 @@
2
2
  * System prompt for the local style-check tool.
3
3
  *
4
4
  * Reads a partial-spec file and produces severity-categorized feedback.
5
- * Stateless — same "fresh set of eyes" pattern as the existing cloud
5
+ * Stateless — same "fresh set of eyes" pattern as the cloud
6
6
  * `mcp__dotrequirements__style_check`.
7
7
  *
8
+ * IMPORTANT: This prompt is a verbatim copy of the cloud style-check prompt
9
+ * (REQUIREMENTS_STYLE_PRINCIPLES + severityGuidance) defined in
10
+ * `packages/convex/lib/prompts.ts`. The cts-local style-check is required to
11
+ * MIRROR the cloud tool (CTS-SPEC-3) — when the cloud principles change, this
12
+ * file must be updated in lock-step. A follow-up task should extract the
13
+ * principles into a shared module so this duplication can go away.
14
+ *
8
15
  * Requirements covered:
9
16
  * - CTS-SPEC-3: Specifier worker runs a local style-check on its own draft
17
+ * that mirrors `mcp__dotrequirements__style_check`
10
18
  */
11
- export declare const STYLE_CHECK_PROMPT = "You are a stateless style reviewer for a single dotrequirements partial spec \u2014 one or more `dotrequirements` fenced blocks plus an optional one-line description above them. Your job is to give the author actionable feedback on per-requirement writing quality.\n\nThis check is a \"fresh set of eyes\" \u2014 you have no memory of prior feedback rounds. You are looking only at this file as it currently stands.\n\n## How to categorize feedback\n\n### MUST FIX\n\n- **The requirement does not describe an observable outcome.** \"The system manages memory efficiently\" gives a tester nothing to verify. The requirement needs to be rephrased around what the customer can observe.\n\n### SHOULD FIX\n\n- **Vague language** where concrete behavior is needed.\n- **Missing preconditions** that anchor the test \u2014 a When/Then with no Given-equivalent context.\n- **Internal-mechanics drift** \u2014 describing how the implementation works (library function names, syscall flags, internal scheduling vocabulary, buffer sizes) instead of what the customer observes.\n- **Documentation prose dressed as a requirement** \u2014 \"the documentation directs users to...\" style commentary that isn't testable behavior.\n- **Persona inconsistency** \u2014 the spec doesn't name a persona, or child requirements drop the persona established by their parent.\n- **Chained actions** \u2014 a single requirement covering multiple discrete actions that should be separate requirements.\n- **Hidden sibling dependencies** \u2014 a requirement that only makes sense if read alongside its siblings.\n- **Imposed format labels** \u2014 Given/When/Then or other framework labels applied uniformly without sharpening meaning. The dotrequirements default is unlabeled criteria; labels are used only when they help.\n\n### COULD IMPROVE\n\n- Over-long titles that read like full sentences.\n- Inconsistent terminology with the rest of the area.\n- Redundant sub-criteria that re-state the parent.\n- UI or design specifics where behavior alone would suffice.\n\n## How to write findings\n\nFor each finding:\n- Cite the specific requirement ID (e.g., `AUTH-LOGIN-1`).\n- Quote the offending text.\n- Explain why it's an issue.\n- Suggest a rephrasing, or recommend dropping the requirement.\n\nKeep findings specific and concrete. Vague critiques like \"could be more comprehensive\" are not useful \u2014 name the requirement and quote the issue.\n\n## When to be brief\n\nIf the partial is genuinely good, say so. Don't manufacture findings to fill space. A clean style check is the right outcome more often than not.\n\n## Output format\n\nMarkdown with these headings:\n\n```\n## MUST FIX\n\n- ...\n\n## SHOULD FIX\n\n- ...\n\n## COULD IMPROVE\n\n- ...\n```\n\nOmit any heading with no findings. End with a one-line summary like `OVERALL: <terse assessment>`.\n\n## Output discipline\n\n- Output ONLY the categorized feedback, beginning with the first heading.\n- No preamble, no chain-of-thought, no explanation of your process.\n- Be honest. Accurate signal helps the author iterate.";
19
+ export declare const STYLE_CHECK_PROMPT = "You are a style checker for requirements documentation in the dotrequirements format.\n\nReview the requirements file and provide actionable feedback based on these principles:\n\n**IMPORTANT**: The arrow notation format (position. Label \u2192 content) is the standard dotrequirements format. NEVER suggest changing or removing this format. Focus on the CONTENT of requirements, not the format itself.\n\n1. **Use Concrete Examples**: Replace abstract descriptions with specific testable scenarios\n - \u274C Bad: \"users can log in\"\n - \uD83D\uDD36 Better: \"when a registered user provides valid credentials, they are authenticated\"\n - \u2705 Best: \"when a registered user provides credentials like user123/pass123, they are authenticated\"\n\n2. **Write Concisely Using Natural Prose and Declarative Style**:\n - \u274C Bad: \"registered user with valid credentials is authenticated\" (too terse)\n - \u274C Bad: \"A registered user, whose life story is as follows...\" (too verbose)\n - \u2705 Good: \"When a registered user provides valid credentials, they are authenticated\"\n - Note: Avoid imperative constructions like \"should\" - use declarative statements that evaluate to true/false\n\n3. **Keep Arrange/Act/Assert in Mind**: Well-written requirements describe clear preconditions, a trigger, and an assertable result\n - Example: \"When [preconditions:] a registered user [trigger:] provides valid credentials, [result:] they are authenticated\"\n - This pattern helps ensure requirements are testable, regardless of the labeling format used\n\n4. **Be Framework Neutral**: Don't encourage or discourage specific requirement formats like Gherkin (Given/When/Then), BDD, or other frameworks\n - \u2705 Good: Gherkin labels are fine if the user is using them\n - \u2705 Good: Plain acceptance criteria without labels are also fine\n - \u274C Bad: Telling users to add or remove Given/When/Then labels based on preference\n - Focus on the quality of the requirement content, not the labeling style\n\n5. **Use Named Personas**: Establish personas in top-level requirements and reuse in children\n - \u2705 Good: \"A registered user, Jaime, can log in normally\" (parent)\n \"When Jaime provides valid credentials, they are authenticated\" (child)\n\n6. **Use User-Centric Language**: Describe user experience, not technical details\n - \u274C Bad: \"they are redirected to app.dotrequirements.io/redirect/dashboard\"\n - \u2705 Good: \"they are automatically brought to the dashboard\"\n\n7. **Avoid Multiple Actions in Single Requirements**:\n - \u274C Bad: \"When Robin provides credentials, requests an OTP, then provides the OTP...\"\n - \u2705 Good: Break into separate requirements for each action\n\n8. **Each Requirement Should Be Independent**: Requirements within a block should be independently testable. If requirements depend on each other (they share preconditions or form a sequence), they should either be nested or restate enough context to stand on their own\n - \u274C Bad: Sibling requirements that share context but don't restate it\n \"0. \u2192 When Jordan submits signup, an account is created\"\n \"1. \u2192 Welcome email is sent\"\n \"2. \u2192 Dashboard appears\"\n Problem: Requirements 1-2 can't be tested without knowing the preconditions from 0\n - \u2705 Good: Restate context so each is independently testable\n \"0. \u2192 When Jordan submits signup, an account is created\"\n \"1. \u2192 When Jordan submits signup, a welcome email is sent\"\n \"2. \u2192 When Jordan submits signup, the dashboard appears\"\n - \u2705 Also good: Use nesting to show the dependency\n \"0. When \u2192 Jordan submits signup\"\n \" 0.0. Then \u2192 an account is created\"\n \" 0.1. Then \u2192 a welcome email is sent\"\n \" 0.2. Then \u2192 the dashboard appears\"\n - Test: Can you understand what's being tested by reading just one requirement, or do you need to read its siblings?\n\n9. **Focus on Behavior, Not Design**:\n - \u274C Bad: \"enters valid credentials into two single-line input fields and presses a green button...\"\n - \u2705 Good: \"provides valid credentials\"\n\n10. **Focus on User Outcomes, Not Implementation**:\n - \u274C Bad: \"When the app requests that Twilio send Casey an OTP from /email/POST endpoint...\"\n - \u2705 Good: \"When Casey requests an email OTP...\"\n - Even technical requirements can be user-centric: \"95 percent of users experience under 1 second of delay\"\n\n11. **Flag Decomposition Issues**: If a requirement looks too large to validate with a single test, identify it\n\nProvide specific, actionable feedback. Do not use emojis. Format as a bulleted list of issues found, or \"No style issues found\" if the file follows best practices.\n\n## Severity Categorization\n\nOrganize your feedback by severity to help users prioritize:\n\n**MUST FIX** - Critical issues that block understanding or testability\n**SHOULD FIX** - Important issues that reduce quality\n**COULD IMPROVE** - Minor suggestions and polish\n\n**IMPORTANT**: Categorize each issue based on its actual impact, not to balance categories. Some files may have many issues in one category and none in others - that's expected and correct.\n\nDo not use emojis. Format your response as:\n\n## MUST FIX\n[List critical issues, or \"None\"]\n\n## SHOULD FIX\n[List important issues, or \"None\"]\n\n## COULD IMPROVE\n[List minor suggestions, or \"None\"]";
12
20
  //# sourceMappingURL=style-check.d.ts.map
@@ -2,77 +2,107 @@
2
2
  * System prompt for the local style-check tool.
3
3
  *
4
4
  * Reads a partial-spec file and produces severity-categorized feedback.
5
- * Stateless — same "fresh set of eyes" pattern as the existing cloud
5
+ * Stateless — same "fresh set of eyes" pattern as the cloud
6
6
  * `mcp__dotrequirements__style_check`.
7
7
  *
8
+ * IMPORTANT: This prompt is a verbatim copy of the cloud style-check prompt
9
+ * (REQUIREMENTS_STYLE_PRINCIPLES + severityGuidance) defined in
10
+ * `packages/convex/lib/prompts.ts`. The cts-local style-check is required to
11
+ * MIRROR the cloud tool (CTS-SPEC-3) — when the cloud principles change, this
12
+ * file must be updated in lock-step. A follow-up task should extract the
13
+ * principles into a shared module so this duplication can go away.
14
+ *
8
15
  * Requirements covered:
9
16
  * - CTS-SPEC-3: Specifier worker runs a local style-check on its own draft
17
+ * that mirrors `mcp__dotrequirements__style_check`
10
18
  */
11
- export const STYLE_CHECK_PROMPT = `You are a stateless style reviewer for a single dotrequirements partial spec — one or more \`dotrequirements\` fenced blocks plus an optional one-line description above them. Your job is to give the author actionable feedback on per-requirement writing quality.
19
+ export const STYLE_CHECK_PROMPT = `You are a style checker for requirements documentation in the dotrequirements format.
12
20
 
13
- This check is a "fresh set of eyes" — you have no memory of prior feedback rounds. You are looking only at this file as it currently stands.
21
+ Review the requirements file and provide actionable feedback based on these principles:
14
22
 
15
- ## How to categorize feedback
23
+ **IMPORTANT**: The arrow notation format (position. Label → content) is the standard dotrequirements format. NEVER suggest changing or removing this format. Focus on the CONTENT of requirements, not the format itself.
16
24
 
17
- ### MUST FIX
25
+ 1. **Use Concrete Examples**: Replace abstract descriptions with specific testable scenarios
26
+ - ❌ Bad: "users can log in"
27
+ - 🔶 Better: "when a registered user provides valid credentials, they are authenticated"
28
+ - ✅ Best: "when a registered user provides credentials like user123/pass123, they are authenticated"
18
29
 
19
- - **The requirement does not describe an observable outcome.** "The system manages memory efficiently" gives a tester nothing to verify. The requirement needs to be rephrased around what the customer can observe.
30
+ 2. **Write Concisely Using Natural Prose and Declarative Style**:
31
+ - ❌ Bad: "registered user with valid credentials is authenticated" (too terse)
32
+ - ❌ Bad: "A registered user, whose life story is as follows..." (too verbose)
33
+ - ✅ Good: "When a registered user provides valid credentials, they are authenticated"
34
+ - Note: Avoid imperative constructions like "should" - use declarative statements that evaluate to true/false
20
35
 
21
- ### SHOULD FIX
36
+ 3. **Keep Arrange/Act/Assert in Mind**: Well-written requirements describe clear preconditions, a trigger, and an assertable result
37
+ - Example: "When [preconditions:] a registered user [trigger:] provides valid credentials, [result:] they are authenticated"
38
+ - This pattern helps ensure requirements are testable, regardless of the labeling format used
22
39
 
23
- - **Vague language** where concrete behavior is needed.
24
- - **Missing preconditions** that anchor the test — a When/Then with no Given-equivalent context.
25
- - **Internal-mechanics drift** — describing how the implementation works (library function names, syscall flags, internal scheduling vocabulary, buffer sizes) instead of what the customer observes.
26
- - **Documentation prose dressed as a requirement** — "the documentation directs users to..." style commentary that isn't testable behavior.
27
- - **Persona inconsistency** — the spec doesn't name a persona, or child requirements drop the persona established by their parent.
28
- - **Chained actions** — a single requirement covering multiple discrete actions that should be separate requirements.
29
- - **Hidden sibling dependencies** — a requirement that only makes sense if read alongside its siblings.
30
- - **Imposed format labels** — Given/When/Then or other framework labels applied uniformly without sharpening meaning. The dotrequirements default is unlabeled criteria; labels are used only when they help.
40
+ 4. **Be Framework Neutral**: Don't encourage or discourage specific requirement formats like Gherkin (Given/When/Then), BDD, or other frameworks
41
+ - ✅ Good: Gherkin labels are fine if the user is using them
42
+ - ✅ Good: Plain acceptance criteria without labels are also fine
43
+ - ❌ Bad: Telling users to add or remove Given/When/Then labels based on preference
44
+ - Focus on the quality of the requirement content, not the labeling style
31
45
 
32
- ### COULD IMPROVE
46
+ 5. **Use Named Personas**: Establish personas in top-level requirements and reuse in children
47
+ - ✅ Good: "A registered user, Jaime, can log in normally" (parent)
48
+ "When Jaime provides valid credentials, they are authenticated" (child)
33
49
 
34
- - Over-long titles that read like full sentences.
35
- - Inconsistent terminology with the rest of the area.
36
- - Redundant sub-criteria that re-state the parent.
37
- - UI or design specifics where behavior alone would suffice.
50
+ 6. **Use User-Centric Language**: Describe user experience, not technical details
51
+ - ❌ Bad: "they are redirected to app.dotrequirements.io/redirect/dashboard"
52
+ - ✅ Good: "they are automatically brought to the dashboard"
38
53
 
39
- ## How to write findings
54
+ 7. **Avoid Multiple Actions in Single Requirements**:
55
+ - ❌ Bad: "When Robin provides credentials, requests an OTP, then provides the OTP..."
56
+ - ✅ Good: Break into separate requirements for each action
40
57
 
41
- For each finding:
42
- - Cite the specific requirement ID (e.g., \`AUTH-LOGIN-1\`).
43
- - Quote the offending text.
44
- - Explain why it's an issue.
45
- - Suggest a rephrasing, or recommend dropping the requirement.
58
+ 8. **Each Requirement Should Be Independent**: Requirements within a block should be independently testable. If requirements depend on each other (they share preconditions or form a sequence), they should either be nested or restate enough context to stand on their own
59
+ - ❌ Bad: Sibling requirements that share context but don't restate it
60
+ "0. → When Jordan submits signup, an account is created"
61
+ "1. → Welcome email is sent"
62
+ "2. → Dashboard appears"
63
+ Problem: Requirements 1-2 can't be tested without knowing the preconditions from 0
64
+ - ✅ Good: Restate context so each is independently testable
65
+ "0. → When Jordan submits signup, an account is created"
66
+ "1. → When Jordan submits signup, a welcome email is sent"
67
+ "2. → When Jordan submits signup, the dashboard appears"
68
+ - ✅ Also good: Use nesting to show the dependency
69
+ "0. When → Jordan submits signup"
70
+ " 0.0. Then → an account is created"
71
+ " 0.1. Then → a welcome email is sent"
72
+ " 0.2. Then → the dashboard appears"
73
+ - Test: Can you understand what's being tested by reading just one requirement, or do you need to read its siblings?
46
74
 
47
- Keep findings specific and concrete. Vague critiques like "could be more comprehensive" are not useful — name the requirement and quote the issue.
75
+ 9. **Focus on Behavior, Not Design**:
76
+ - ❌ Bad: "enters valid credentials into two single-line input fields and presses a green button..."
77
+ - ✅ Good: "provides valid credentials"
48
78
 
49
- ## When to be brief
79
+ 10. **Focus on User Outcomes, Not Implementation**:
80
+ - ❌ Bad: "When the app requests that Twilio send Casey an OTP from /email/POST endpoint..."
81
+ - ✅ Good: "When Casey requests an email OTP..."
82
+ - Even technical requirements can be user-centric: "95 percent of users experience under 1 second of delay"
50
83
 
51
- If the partial is genuinely good, say so. Don't manufacture findings to fill space. A clean style check is the right outcome more often than not.
84
+ 11. **Flag Decomposition Issues**: If a requirement looks too large to validate with a single test, identify it
52
85
 
53
- ## Output format
86
+ Provide specific, actionable feedback. Do not use emojis. Format as a bulleted list of issues found, or "No style issues found" if the file follows best practices.
54
87
 
55
- Markdown with these headings:
88
+ ## Severity Categorization
56
89
 
57
- \`\`\`
58
- ## MUST FIX
90
+ Organize your feedback by severity to help users prioritize:
59
91
 
60
- - ...
92
+ **MUST FIX** - Critical issues that block understanding or testability
93
+ **SHOULD FIX** - Important issues that reduce quality
94
+ **COULD IMPROVE** - Minor suggestions and polish
61
95
 
62
- ## SHOULD FIX
96
+ **IMPORTANT**: Categorize each issue based on its actual impact, not to balance categories. Some files may have many issues in one category and none in others - that's expected and correct.
63
97
 
64
- - ...
65
-
66
- ## COULD IMPROVE
98
+ Do not use emojis. Format your response as:
67
99
 
68
- - ...
69
- \`\`\`
70
-
71
- Omit any heading with no findings. End with a one-line summary like \`OVERALL: <terse assessment>\`.
100
+ ## MUST FIX
101
+ [List critical issues, or "None"]
72
102
 
73
- ## Output discipline
103
+ ## SHOULD FIX
104
+ [List important issues, or "None"]
74
105
 
75
- - Output ONLY the categorized feedback, beginning with the first heading.
76
- - No preamble, no chain-of-thought, no explanation of your process.
77
- - Be honest. Accurate signal helps the author iterate.`;
106
+ ## COULD IMPROVE
107
+ [List minor suggestions, or "None"]`;
78
108
  //# sourceMappingURL=style-check.js.map
@@ -9,21 +9,56 @@
9
9
  * - CTS-PLAN-2: outline reviewer output structure (categorized findings + verdict)
10
10
  */
11
11
  import { z } from "zod";
12
+ export declare const CustomerSchema: z.ZodObject<{
13
+ name: z.ZodString;
14
+ description: z.ZodString;
15
+ }, "strip", z.ZodTypeAny, {
16
+ name: string;
17
+ description: string;
18
+ }, {
19
+ name: string;
20
+ description: string;
21
+ }>;
22
+ export type Customer = z.infer<typeof CustomerSchema>;
12
23
  export declare const AreaSchema: z.ZodObject<{
13
24
  name: z.ZodString;
14
25
  description: z.ZodString;
15
26
  prefix: z.ZodString;
16
27
  files: z.ZodArray<z.ZodString, "many">;
28
+ /**
29
+ * Customers this area serves — at least one. Each customer is a *user* of
30
+ * the software (not a contributor to its codebase). The specifier will use
31
+ * one of these as the persona it grounds the area's requirements in.
32
+ * See CTS-PLAN-1 (customer threading).
33
+ */
34
+ customers: z.ZodArray<z.ZodObject<{
35
+ name: z.ZodString;
36
+ description: z.ZodString;
37
+ }, "strip", z.ZodTypeAny, {
38
+ name: string;
39
+ description: string;
40
+ }, {
41
+ name: string;
42
+ description: string;
43
+ }>, "many">;
17
44
  }, "strip", z.ZodTypeAny, {
18
45
  prefix: string;
19
46
  files: string[];
20
47
  name: string;
21
48
  description: string;
49
+ customers: {
50
+ name: string;
51
+ description: string;
52
+ }[];
22
53
  }, {
23
54
  prefix: string;
24
55
  files: string[];
25
56
  name: string;
26
57
  description: string;
58
+ customers: {
59
+ name: string;
60
+ description: string;
61
+ }[];
27
62
  }>;
28
63
  export type Area = z.infer<typeof AreaSchema>;
29
64
  export declare const OutlineSchema: z.ZodObject<{
@@ -35,16 +70,40 @@ export declare const OutlineSchema: z.ZodObject<{
35
70
  description: z.ZodString;
36
71
  prefix: z.ZodString;
37
72
  files: z.ZodArray<z.ZodString, "many">;
73
+ /**
74
+ * Customers this area serves — at least one. Each customer is a *user* of
75
+ * the software (not a contributor to its codebase). The specifier will use
76
+ * one of these as the persona it grounds the area's requirements in.
77
+ * See CTS-PLAN-1 (customer threading).
78
+ */
79
+ customers: z.ZodArray<z.ZodObject<{
80
+ name: z.ZodString;
81
+ description: z.ZodString;
82
+ }, "strip", z.ZodTypeAny, {
83
+ name: string;
84
+ description: string;
85
+ }, {
86
+ name: string;
87
+ description: string;
88
+ }>, "many">;
38
89
  }, "strip", z.ZodTypeAny, {
39
90
  prefix: string;
40
91
  files: string[];
41
92
  name: string;
42
93
  description: string;
94
+ customers: {
95
+ name: string;
96
+ description: string;
97
+ }[];
43
98
  }, {
44
99
  prefix: string;
45
100
  files: string[];
46
101
  name: string;
47
102
  description: string;
103
+ customers: {
104
+ name: string;
105
+ description: string;
106
+ }[];
48
107
  }>, "many">;
49
108
  }, "strip", z.ZodTypeAny, {
50
109
  title: string;
@@ -55,6 +114,10 @@ export declare const OutlineSchema: z.ZodObject<{
55
114
  files: string[];
56
115
  name: string;
57
116
  description: string;
117
+ customers: {
118
+ name: string;
119
+ description: string;
120
+ }[];
58
121
  }[];
59
122
  }, {
60
123
  title: string;
@@ -65,6 +128,10 @@ export declare const OutlineSchema: z.ZodObject<{
65
128
  files: string[];
66
129
  name: string;
67
130
  description: string;
131
+ customers: {
132
+ name: string;
133
+ description: string;
134
+ }[];
68
135
  }[];
69
136
  }>;
70
137
  export type Outline = z.infer<typeof OutlineSchema>;
@@ -104,8 +171,25 @@ export declare const OUTLINE_JSON_SCHEMA: {
104
171
  readonly type: "string";
105
172
  };
106
173
  };
174
+ readonly customers: {
175
+ readonly type: "array";
176
+ readonly minItems: 1;
177
+ readonly items: {
178
+ readonly type: "object";
179
+ readonly properties: {
180
+ readonly name: {
181
+ readonly type: "string";
182
+ };
183
+ readonly description: {
184
+ readonly type: "string";
185
+ };
186
+ };
187
+ readonly required: readonly ["name", "description"];
188
+ readonly additionalProperties: false;
189
+ };
190
+ };
107
191
  };
108
- readonly required: readonly ["name", "description", "prefix", "files"];
192
+ readonly required: readonly ["name", "description", "prefix", "files", "customers"];
109
193
  readonly additionalProperties: false;
110
194
  };
111
195
  };
@@ -10,6 +10,10 @@
10
10
  */
11
11
  import { z } from "zod";
12
12
  // ---------- Outline ----------
13
+ export const CustomerSchema = z.object({
14
+ name: z.string().min(1),
15
+ description: z.string().min(1),
16
+ });
13
17
  export const AreaSchema = z.object({
14
18
  name: z.string().min(1),
15
19
  description: z.string().min(1),
@@ -17,6 +21,13 @@ export const AreaSchema = z.object({
17
21
  .string()
18
22
  .regex(/^[A-Z][A-Z0-9_]*$/, "prefix must be uppercase alphanumeric/underscore"),
19
23
  files: z.array(z.string()).min(0),
24
+ /**
25
+ * Customers this area serves — at least one. Each customer is a *user* of
26
+ * the software (not a contributor to its codebase). The specifier will use
27
+ * one of these as the persona it grounds the area's requirements in.
28
+ * See CTS-PLAN-1 (customer threading).
29
+ */
30
+ customers: z.array(CustomerSchema).min(1),
20
31
  });
21
32
  export const OutlineSchema = z.object({
22
33
  title: z.string().min(1),
@@ -45,8 +56,21 @@ export const OUTLINE_JSON_SCHEMA = {
45
56
  description: { type: "string" },
46
57
  prefix: { type: "string" },
47
58
  files: { type: "array", items: { type: "string" } },
59
+ customers: {
60
+ type: "array",
61
+ minItems: 1,
62
+ items: {
63
+ type: "object",
64
+ properties: {
65
+ name: { type: "string" },
66
+ description: { type: "string" },
67
+ },
68
+ required: ["name", "description"],
69
+ additionalProperties: false,
70
+ },
71
+ },
48
72
  },
49
- required: ["name", "description", "prefix", "files"],
73
+ required: ["name", "description", "prefix", "files", "customers"],
50
74
  additionalProperties: false,
51
75
  },
52
76
  },
@@ -24,6 +24,12 @@ function buildUserMessage(ctx) {
24
24
  `Area description: ${ctx.area.description}`,
25
25
  `Document defaultPrefix: ${ctx.outline.defaultPrefix}`,
26
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
+ `\`\`\``,
27
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).`,
28
34
  ``,
29
35
  `## Paths`,
@@ -4,6 +4,7 @@
4
4
  * Subcommands route to focused handlers in this directory. Each subcommand can
5
5
  * be invoked granularly (e.g., `dotrequirements cts pack`) per CTS-CLI-2.
6
6
  */
7
+ import { installCtsAbortHandlers } from "../../codebase-to-spec/progress.js";
7
8
  import { composeCommand } from "./compose.js";
8
9
  import { editLoopCommand } from "./edit-loop.js";
9
10
  import { fanOutCommand } from "./fan-out.js";
@@ -20,12 +21,20 @@ export function registerCodebaseToSpec(program) {
20
21
  .command("codebase-to-spec")
21
22
  .alias("cts")
22
23
  .description("Generate dotrequirements behavioral specifications from a codebase");
24
+ // Install SIGTERM/SIGINT handlers for every cts subcommand so an interrupted
25
+ // pipeline emits a structured `pipeline/aborted` line before exiting
26
+ // (CTS-OBSERVE-1.5). preAction fires after argv parsing and before the
27
+ // subcommand action runs.
28
+ cts.hook("preAction", () => {
29
+ installCtsAbortHandlers();
30
+ });
23
31
  cts
24
32
  .command("pack")
25
33
  .description("Pack the codebase (compressed and uncompressed views) into the cache")
26
34
  .option("-s, --scope <path>", "Limit to files under this path (subdir of project root)")
27
35
  .option("--fresh", "Clear the cache before running")
28
36
  .option("--budget <tokens>", "Override the working-context budget (in tokens)", (v) => parseInt(v, 10))
37
+ .option("--ignore-requirements", "Exclude `.requirements/**` from the pack (use when testing cts against a codebase whose existing requirements should not influence the output)")
29
38
  .action((opts) => packCommand({ ...opts, budgetTokens: opts.budget }));
30
39
  cts
31
40
  .command("plan-loop")
@@ -81,6 +90,7 @@ export function registerCodebaseToSpec(program) {
81
90
  .option("--non-interactive", "Force non-interactive mode (override TTY detection)")
82
91
  .option("--overwrite", "Replace existing .requirements/ files without prompting")
83
92
  .option("--skip-existing", "Leave existing .requirements/ files untouched")
93
+ .option("--ignore-requirements", "Write output to `.requirements/cts/` instead of `.requirements/` (use together with `cts pack --ignore-requirements` when isolating cts from an existing requirements directory)")
84
94
  .action((opts) => {
85
95
  const forceMode = opts.interactive
86
96
  ? "interactive"
@@ -91,6 +101,7 @@ export function registerCodebaseToSpec(program) {
91
101
  forceMode,
92
102
  overwrite: opts.overwrite,
93
103
  skipExisting: opts.skipExisting,
104
+ ignoreRequirements: opts.ignoreRequirements,
94
105
  });
95
106
  });
96
107
  cts
@@ -105,6 +116,7 @@ export function registerCodebaseToSpec(program) {
105
116
  .option("--non-interactive", "Force non-interactive mode for the present stage")
106
117
  .option("--overwrite", "Replace existing .requirements/ files without prompting")
107
118
  .option("--skip-existing", "Leave existing .requirements/ files untouched")
119
+ .option("--ignore-requirements", "Exclude `.requirements/**` from the pack and write output to `.requirements/cts/` instead of `.requirements/` (use when testing cts against a codebase whose existing requirements should not influence the output)")
108
120
  .action((opts) => {
109
121
  const forceMode = opts.interactive
110
122
  ? "interactive"
@@ -118,6 +130,7 @@ export function registerCodebaseToSpec(program) {
118
130
  forceMode,
119
131
  overwrite: opts.overwrite,
120
132
  skipExisting: opts.skipExisting,
133
+ ignoreRequirements: opts.ignoreRequirements,
121
134
  });
122
135
  });
123
136
  cts
@@ -13,6 +13,12 @@ export interface PackOptions {
13
13
  scope?: string;
14
14
  fresh?: boolean;
15
15
  budgetTokens?: number;
16
+ /**
17
+ * When true, exclude `.requirements/**` from the pack so an existing
18
+ * requirements directory does not influence the generated output.
19
+ * See CTS-PRESENT-5.
20
+ */
21
+ ignoreRequirements?: boolean;
16
22
  /** Override progress emitter, mainly for tests. */
17
23
  progress?: import("../../codebase-to-spec/progress.js").ProgressEmitter;
18
24
  /** Override the project root, mainly for tests. */
@@ -43,6 +43,7 @@ export async function packCommand(rawOptions = {}) {
43
43
  projectRoot,
44
44
  paths,
45
45
  scope: rawOptions.scope,
46
+ ignoreRequirements: rawOptions.ignoreRequirements,
46
47
  });
47
48
  progress.emit({
48
49
  stage: "pack",
@@ -15,6 +15,11 @@ export interface PresentCmdOptions {
15
15
  overwrite?: boolean;
16
16
  /** Skip writing files that would conflict (non-interactive). */
17
17
  skipExisting?: boolean;
18
+ /**
19
+ * When true, write output under `.requirements/cts/` instead of
20
+ * `.requirements/`. See CTS-PRESENT-5.
21
+ */
22
+ ignoreRequirements?: boolean;
18
23
  projectRoot?: string;
19
24
  }
20
25
  export declare function presentCommand(rawOptions?: PresentCmdOptions): Promise<void>;
@@ -51,16 +51,21 @@ export async function presentCommand(rawOptions = {}) {
51
51
  process.exitCode = ExitCode.InvalidFlags;
52
52
  return;
53
53
  }
54
+ const outputSubdir = rawOptions.ignoreRequirements ? "cts" : undefined;
55
+ const outputDirLabel = outputSubdir
56
+ ? `.requirements/${outputSubdir}/`
57
+ : ".requirements/";
54
58
  progress.emit({
55
59
  stage: "present",
56
60
  step: "start",
57
- message: `Writing final spec to .requirements/ (mode: ${isInteractive ? "interactive" : "non-interactive"}, policy: ${policy})`,
61
+ message: `Writing final spec to ${outputDirLabel} (mode: ${isInteractive ? "interactive" : "non-interactive"}, policy: ${policy})`,
58
62
  });
59
63
  const result = await runPresent({
60
64
  outline,
61
65
  finalSpecPath: paths.specFinal,
62
66
  projectRoot,
63
67
  overwritePolicy: policy,
68
+ outputSubdir,
64
69
  });
65
70
  // Per-file outcome announcements.
66
71
  for (const action of result.actions) {
@@ -77,6 +77,7 @@ export async function runCommand(options = {}) {
77
77
  forceMode: options.forceMode,
78
78
  overwrite: options.overwrite,
79
79
  skipExisting: options.skipExisting,
80
+ ignoreRequirements: options.ignoreRequirements,
80
81
  projectRoot: options.projectRoot,
81
82
  });
82
83
  // Present sets a non-zero exit code on overwrite refusal or validation
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@popoverai/dotrequirements",
3
- "version": "0.24.0",
3
+ "version": "0.24.2",
4
4
  "description": "Requirements tracking CLI, test harness, and MCP server",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,10 +24,9 @@
24
24
  "test": "vitest",
25
25
  "test:run": "vitest run",
26
26
  "test:coverage": "vitest run --coverage",
27
- "prepublish:check": "git diff-index --quiet HEAD || (echo 'Error: Uncommitted changes detected. Commit or stash them first.' && exit 1)",
28
- "publish:patch": "pnpm prepublish:check && npm version patch && pnpm build && npm publish && git push && git push --tags",
29
- "publish:minor": "pnpm prepublish:check && npm version minor && pnpm build && npm publish && git push && git push --tags",
30
- "publish:major": "pnpm prepublish:check && npm version major && pnpm build && npm publish && git push && git push --tags"
27
+ "publish:patch": "echo 'ERROR: publish:patch is decommissioned. CLI npm publishes now happen via the cli-publish GitHub Action when a production PR with a CLI version bump merges. Use the /release Claude Code skill to queue a bump and open the production PR. See docs/working/cli-publish-workflow.md for details.' && exit 1",
28
+ "publish:minor": "echo 'ERROR: publish:minor is decommissioned. CLI npm publishes now happen via the cli-publish GitHub Action when a production PR with a CLI version bump merges. Use the /release Claude Code skill to queue a bump and open the production PR. See docs/working/cli-publish-workflow.md for details.' && exit 1",
29
+ "publish:major": "echo 'ERROR: publish:major is decommissioned. CLI npm publishes now happen via the cli-publish GitHub Action when a production PR with a CLI version bump merges. Use the /release Claude Code skill to queue a bump and open the production PR. See docs/working/cli-publish-workflow.md for details.' && exit 1"
31
30
  },
32
31
  "keywords": [
33
32
  "requirements",
@@ -42,7 +41,7 @@
42
41
  "license": "MIT",
43
42
  "homepage": "https://dotrequirements.io",
44
43
  "bugs": {
45
- "email": "support@popover.ca"
44
+ "email": "support@dotrequirements.io"
46
45
  },
47
46
  "engines": {
48
47
  "node": ">=18"
@@ -1,12 +0,0 @@
1
- /**
2
- * System prompt for the applying planner (apply mode).
3
- *
4
- * Receives the prior outline + an explicit list of mechanical revisions and
5
- * applies them verbatim. Used when the reviewer's verdict was
6
- * `approved-with-revisions`.
7
- *
8
- * Requirements covered:
9
- * - CTS-PLAN-4: Approved-with-revisions outline triggers one mechanical revision
10
- */
11
- export declare const PLANNER_APPLY_PROMPT = "You are applying mechanical revisions to a planning outline. A reviewer has approved the outline subject to a specific list of small revisions. Your job is to apply each revision verbatim and emit the revised outline.\n\nYou are NOT revising the outline using your own judgment. You are NOT adding new areas, dropping existing areas, or restructuring. You ONLY apply the listed revisions.\n\nYou will output a JSON object matching the schema you have been given. No prose preamble, no explanation, no markdown fences \u2014 JSON only.\n\nYou will receive:\n1. The previous outline as JSON\n2. An explicit list of revisions, each phrased as a directive\n\n## Process\n\nFor each revision in the list:\n- Apply the directive exactly as stated.\n- If the directive is ambiguous or would require new judgment, leave that area unchanged and proceed.\n\nPreserve everything else from the prior outline byte-for-byte (modulo the listed changes).\n\n## Output\n\nOutput ONLY the JSON object matching the supplied schema. No preamble. Begin with `{`.";
12
- //# sourceMappingURL=planner-apply.d.ts.map
@@ -1,32 +0,0 @@
1
- /**
2
- * System prompt for the applying planner (apply mode).
3
- *
4
- * Receives the prior outline + an explicit list of mechanical revisions and
5
- * applies them verbatim. Used when the reviewer's verdict was
6
- * `approved-with-revisions`.
7
- *
8
- * Requirements covered:
9
- * - CTS-PLAN-4: Approved-with-revisions outline triggers one mechanical revision
10
- */
11
- export const PLANNER_APPLY_PROMPT = `You are applying mechanical revisions to a planning outline. A reviewer has approved the outline subject to a specific list of small revisions. Your job is to apply each revision verbatim and emit the revised outline.
12
-
13
- You are NOT revising the outline using your own judgment. You are NOT adding new areas, dropping existing areas, or restructuring. You ONLY apply the listed revisions.
14
-
15
- You will output a JSON object matching the schema you have been given. No prose preamble, no explanation, no markdown fences — JSON only.
16
-
17
- You will receive:
18
- 1. The previous outline as JSON
19
- 2. An explicit list of revisions, each phrased as a directive
20
-
21
- ## Process
22
-
23
- For each revision in the list:
24
- - Apply the directive exactly as stated.
25
- - If the directive is ambiguous or would require new judgment, leave that area unchanged and proceed.
26
-
27
- Preserve everything else from the prior outline byte-for-byte (modulo the listed changes).
28
-
29
- ## Output
30
-
31
- Output ONLY the JSON object matching the supplied schema. No preamble. Begin with \`{\`.`;
32
- //# sourceMappingURL=planner-apply.js.map