@popoverai/dotrequirements 0.32.1 → 0.34.0

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 (135) hide show
  1. package/dist/cli.js +32 -7
  2. package/dist/cloud.d.ts +18 -0
  3. package/dist/cloud.js +38 -0
  4. package/dist/commands/board/index.d.ts +13 -0
  5. package/dist/commands/board/index.js +96 -0
  6. package/dist/commands/branch-merge.d.ts +78 -0
  7. package/dist/commands/branch-merge.js +129 -0
  8. package/dist/commands/create-requirement-document.js +2 -2
  9. package/dist/commands/diff.js +15 -5
  10. package/dist/commands/init.js +7 -6
  11. package/dist/commands/link.js +27 -21
  12. package/dist/commands/mockup/index.d.ts +11 -0
  13. package/dist/commands/mockup/index.js +82 -0
  14. package/dist/commands/report.js +22 -9
  15. package/dist/commands/review-test.js +3 -2
  16. package/dist/commands/scores/index.d.ts +50 -0
  17. package/dist/commands/scores/index.js +190 -0
  18. package/dist/commands/solution/ask.d.ts +9 -0
  19. package/dist/commands/solution/ask.js +27 -0
  20. package/dist/commands/solution/author.d.ts +19 -0
  21. package/dist/commands/solution/author.js +202 -0
  22. package/dist/commands/solution/branch.d.ts +103 -0
  23. package/dist/commands/solution/branch.js +341 -0
  24. package/dist/commands/solution/brief.d.ts +81 -0
  25. package/dist/commands/solution/brief.js +47 -0
  26. package/dist/commands/solution/checkout.d.ts +27 -0
  27. package/dist/commands/solution/checkout.js +66 -0
  28. package/dist/commands/solution/client.d.ts +16 -0
  29. package/dist/commands/solution/client.js +46 -0
  30. package/dist/commands/solution/contract.d.ts +9 -0
  31. package/dist/commands/solution/contract.js +23 -0
  32. package/dist/commands/solution/create.d.ts +14 -0
  33. package/dist/commands/solution/create.js +52 -0
  34. package/dist/commands/solution/demo-script.d.ts +28 -0
  35. package/dist/commands/solution/demo-script.js +43 -0
  36. package/dist/commands/solution/image.d.ts +60 -0
  37. package/dist/commands/solution/image.js +148 -0
  38. package/dist/commands/solution/index.d.ts +12 -0
  39. package/dist/commands/solution/index.js +281 -0
  40. package/dist/commands/solution/look-up.d.ts +9 -0
  41. package/dist/commands/solution/look-up.js +69 -0
  42. package/dist/commands/solution/next.d.ts +12 -0
  43. package/dist/commands/solution/next.js +48 -0
  44. package/dist/commands/solution/plan-file.d.ts +22 -0
  45. package/dist/commands/solution/plan-file.js +33 -0
  46. package/dist/commands/solution/preview-screenshot.d.ts +21 -0
  47. package/dist/commands/solution/preview-screenshot.js +56 -0
  48. package/dist/commands/solution/pull-request.d.ts +25 -0
  49. package/dist/commands/solution/pull-request.js +117 -0
  50. package/dist/commands/solution/pushing.d.ts +66 -0
  51. package/dist/commands/solution/pushing.js +185 -0
  52. package/dist/commands/solution/rehearse.d.ts +10 -0
  53. package/dist/commands/solution/rehearse.js +24 -0
  54. package/dist/commands/solution/request.d.ts +3 -0
  55. package/dist/commands/solution/request.js +13 -0
  56. package/dist/commands/solution/review.d.ts +27 -0
  57. package/dist/commands/solution/review.js +104 -0
  58. package/dist/commands/solution/run-file.d.ts +42 -0
  59. package/dist/commands/solution/run-file.js +63 -0
  60. package/dist/commands/solution/share.d.ts +62 -0
  61. package/dist/commands/solution/share.js +346 -0
  62. package/dist/commands/solution/stall.d.ts +14 -0
  63. package/dist/commands/solution/stall.js +41 -0
  64. package/dist/commands/solution/start.d.ts +11 -0
  65. package/dist/commands/solution/start.js +20 -0
  66. package/dist/commands/solution/status.d.ts +39 -0
  67. package/dist/commands/solution/status.js +145 -0
  68. package/dist/commands/solution/summary.d.ts +13 -0
  69. package/dist/commands/solution/summary.js +5 -0
  70. package/dist/commands/solution/things.d.ts +118 -0
  71. package/dist/commands/solution/things.js +78 -0
  72. package/dist/commands/solution/thread.d.ts +13 -0
  73. package/dist/commands/solution/thread.js +53 -0
  74. package/dist/commands/solution/upload.d.ts +24 -0
  75. package/dist/commands/solution/upload.js +27 -0
  76. package/dist/commands/solution/video.d.ts +88 -0
  77. package/dist/commands/solution/video.js +364 -0
  78. package/dist/commands/solution/working-folder.d.ts +44 -0
  79. package/dist/commands/solution/working-folder.js +64 -0
  80. package/dist/commands/style-check.js +4 -4
  81. package/dist/commands/sync.d.ts +2 -1
  82. package/dist/commands/sync.js +21 -5
  83. package/dist/convex.d.ts +64 -10
  84. package/dist/convex.js +75 -10
  85. package/dist/harness/finalize.js +16 -8
  86. package/dist/harness/reportingStatus.js +2 -11
  87. package/dist/push/core.js +7 -2
  88. package/dist/rehearsal/derive.d.ts +23 -0
  89. package/dist/rehearsal/derive.js +112 -0
  90. package/dist/rehearsal/driver.d.ts +44 -0
  91. package/dist/rehearsal/driver.js +337 -0
  92. package/dist/rehearsal/earlier.d.ts +25 -0
  93. package/dist/rehearsal/earlier.js +138 -0
  94. package/dist/rehearsal/index.d.ts +5 -0
  95. package/dist/rehearsal/index.js +4 -0
  96. package/dist/rehearsal/live.d.ts +72 -0
  97. package/dist/rehearsal/live.js +301 -0
  98. package/dist/rehearsal/report.d.ts +4 -0
  99. package/dist/rehearsal/report.js +69 -0
  100. package/dist/rehearsal/types.d.ts +377 -0
  101. package/dist/rehearsal/types.js +8 -0
  102. package/dist/requirements/cloud-ai.d.ts +0 -6
  103. package/dist/requirements/cloud-ai.js +2 -11
  104. package/dist/requirements/cloud-coverage.js +4 -4
  105. package/dist/requirements/index.d.ts +6 -0
  106. package/dist/requirements/index.js +24 -0
  107. package/dist/schema/browser.d.ts +1 -1
  108. package/dist/schema/browser.js +3 -1
  109. package/dist/schema/file-writer.d.ts +5 -0
  110. package/dist/schema/file-writer.js +4 -0
  111. package/dist/schema/parser.d.ts +11 -2
  112. package/dist/schema/parser.js +11 -7
  113. package/dist/schema/schemas.d.ts +40 -0
  114. package/dist/schema/schemas.js +4 -0
  115. package/dist/sync/execute.d.ts +10 -1
  116. package/dist/sync/execute.js +76 -24
  117. package/dist/sync/index.d.ts +1 -1
  118. package/dist/sync/index.js +1 -1
  119. package/dist/sync/publish.d.ts +7 -0
  120. package/dist/sync/publish.js +2 -2
  121. package/dist/sync/segment.js +4 -1
  122. package/dist/sync/snapshot.d.ts +27 -5
  123. package/dist/sync/snapshot.js +92 -15
  124. package/dist/sync/solution-documents.d.ts +64 -0
  125. package/dist/sync/solution-documents.js +97 -0
  126. package/dist/sync/types.d.ts +19 -1
  127. package/dist/utils/command-error.d.ts +19 -0
  128. package/dist/utils/command-error.js +44 -0
  129. package/dist/utils/oauth-flow.js +2 -2
  130. package/dist/utils/project-selector.js +4 -4
  131. package/dist/version-messages.d.ts +28 -0
  132. package/dist/version-messages.js +87 -0
  133. package/package.json +3 -2
  134. package/dist/config.d.ts +0 -5
  135. package/dist/config.js +0 -12
package/dist/convex.d.ts CHANGED
@@ -17,13 +17,14 @@
17
17
  export declare const api: {
18
18
  documents: {
19
19
  queries: {
20
- exportForCli: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
21
- exportProjectForCli: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
22
- checkDocumentsExist: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
20
+ exportDocument: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
21
+ exportProject: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
22
+ exportProjectForShare: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
23
+ foreignDocumentIds: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
23
24
  };
24
25
  mutations: {
25
- deleteForCli: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
26
- setAttachmentsForSync: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
26
+ deleteForSync: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
27
+ syncAttachments: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
27
28
  };
28
29
  saveWithRequirements: {
29
30
  saveWithRequirements: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
@@ -37,7 +38,7 @@ export declare const api: {
37
38
  projects: {
38
39
  mutations: {
39
40
  create: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
40
- update: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
41
+ updateProject: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
41
42
  };
42
43
  };
43
44
  teams: {
@@ -53,19 +54,72 @@ export declare const api: {
53
54
  getInviteInfo: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
54
55
  };
55
56
  mutations: {
56
- createInvite: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
57
+ createInviteLink: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
57
58
  acceptInvite: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
58
59
  };
59
60
  };
60
61
  projectSecrets: {
61
62
  queries: {
62
63
  getOwnSecret: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
63
- listOwnSecretsForTeam: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
64
+ listOwnForTeam: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
64
65
  };
65
66
  mutations: {
66
- ensureOwnSecret: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
67
+ ensureOwn: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
67
68
  revokeOwnSecret: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
68
- ensureShareToken: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
69
+ ensureProjectShareToken: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
70
+ };
71
+ };
72
+ scores: {
73
+ mutations: {
74
+ create: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
75
+ update: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
76
+ };
77
+ };
78
+ mockups: {
79
+ mutations: {
80
+ create: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
81
+ };
82
+ };
83
+ solutions: {
84
+ queries: {
85
+ getPlan: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
86
+ getThread: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
87
+ getThings: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
88
+ defaultPlan: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
89
+ readPlanFile: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
90
+ getOutcomePage: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
91
+ getAgentLogs: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
92
+ forSync: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
93
+ rehearsalsOf: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
94
+ rehearsalHistory: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
95
+ };
96
+ mutations: {
97
+ create: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
98
+ start: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
99
+ next: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
100
+ complete: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
101
+ ask: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
102
+ stall: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
103
+ answer: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
104
+ approveCheckpoint: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
105
+ removeRehearsal: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
106
+ videoUploadUrl: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
107
+ };
108
+ shares: {
109
+ forCheckout: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
110
+ push: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
111
+ done: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
112
+ };
113
+ images: {
114
+ uploadUrl: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
115
+ inputUploadUrl: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
116
+ copies: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
117
+ };
118
+ branches: {
119
+ branchOf: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
120
+ claim: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
121
+ recordPush: import("convex/server").FunctionReference<"mutation", "public", any, any, string | undefined>;
122
+ removal: import("convex/server").FunctionReference<"query", "public", any, any, string | undefined>;
69
123
  };
70
124
  };
71
125
  lib: {
package/dist/convex.js CHANGED
@@ -21,15 +21,18 @@ const action = (name) => makeFunctionReference(name);
21
21
  export const api = {
22
22
  documents: {
23
23
  queries: {
24
- exportForCli: query("documents/queries:exportForCli"),
25
- exportProjectForCli: query("documents/queries:exportProjectForCli"),
26
- checkDocumentsExist: query("documents/queries:checkDocumentsExist"),
24
+ exportDocument: query("documents/queries:exportDocument"),
25
+ exportProject: query("documents/queries:exportProject"),
26
+ // SHARE-TOKEN-3: the same export for a read-only share token
27
+ exportProjectForShare: query("documents/queries:exportProjectForShare"),
28
+ // SYNC-FAIL-5: which of the workspace's ids name another project's document
29
+ foreignDocumentIds: query("documents/queries:foreignDocumentIds"),
27
30
  },
28
31
  mutations: {
29
32
  // SYNC-MODE-3: delete a cloud document from the CLI (repo-wins)
30
- deleteForCli: mutation("documents/mutations:deleteForCli"),
33
+ deleteForSync: mutation("documents/mutations:deleteForSync"),
31
34
  // ATTACH-10.2: attachment-only sync — a metadata patch, never a publish
32
- setAttachmentsForSync: mutation("documents/mutations:setAttachmentsForSync"),
35
+ syncAttachments: mutation("documents/mutations:syncAttachments"),
33
36
  },
34
37
  // SYNC-ARCH-1: Save document with requirements derivation
35
38
  saveWithRequirements: {
@@ -44,7 +47,7 @@ export const api = {
44
47
  projects: {
45
48
  mutations: {
46
49
  create: mutation("projects/mutations:create"),
47
- update: mutation("projects/mutations:update"),
50
+ updateProject: mutation("projects/mutations:updateProject"),
48
51
  },
49
52
  },
50
53
  teams: {
@@ -60,7 +63,7 @@ export const api = {
60
63
  getInviteInfo: query("teamInvites/queries:getInviteInfo"),
61
64
  },
62
65
  mutations: {
63
- createInvite: mutation("teamInvites/mutations:createInvite"),
66
+ createInviteLink: mutation("teamInvites/mutations:createInviteLink"),
64
67
  // Joins the team and reconciles paid-team seats via a scheduled sync
65
68
  // (POLAR-SEATS-3). Replaced the deleted polar:acceptTeamInvite action.
66
69
  acceptInvite: mutation("teamInvites/mutations:acceptInvite"),
@@ -69,12 +72,74 @@ export const api = {
69
72
  projectSecrets: {
70
73
  queries: {
71
74
  getOwnSecret: query("projectSecrets/queries:getOwnSecret"),
72
- listOwnSecretsForTeam: query("projectSecrets/queries:listOwnSecretsForTeam"),
75
+ listOwnForTeam: query("projectSecrets/queries:listOwnForTeam"),
73
76
  },
74
77
  mutations: {
75
- ensureOwnSecret: mutation("projectSecrets/mutations:ensureOwnSecret"),
78
+ ensureOwn: mutation("projectSecrets/mutations:ensureOwn"),
76
79
  revokeOwnSecret: mutation("projectSecrets/mutations:revokeOwnSecret"),
77
- ensureShareToken: mutation("projectSecrets/mutations:ensureShareToken"),
80
+ ensureProjectShareToken: mutation("projectSecrets/mutations:ensureProjectShareToken"),
81
+ },
82
+ },
83
+ // VERB-7: scores made and revised from the shell, submitted as scores:<id>
84
+ scores: {
85
+ mutations: {
86
+ create: mutation("scores/mutations:create"),
87
+ update: mutation("scores/mutations:update"),
88
+ },
89
+ },
90
+ mockups: {
91
+ mutations: {
92
+ create: mutation("mockups/mutations:create"),
93
+ },
94
+ },
95
+ solutions: {
96
+ queries: {
97
+ getPlan: query("solutions/queries:getPlan"),
98
+ getThread: query("solutions/queries:getThread"),
99
+ getThings: query("solutions/queries:getThings"),
100
+ defaultPlan: query("solutions/queries:defaultPlan"),
101
+ readPlanFile: query("solutions/queries:readPlanFile"),
102
+ // An outcome's page: where it stands, and the decision open on it.
103
+ getOutcomePage: query("solutions/queries:getOutcomePage"),
104
+ getAgentLogs: query("solutions/queries:getAgentLogs"),
105
+ forSync: query("solutions/queries:forSync"),
106
+ rehearsalsOf: query("solutions/queries:rehearsalsOf"),
107
+ rehearsalHistory: query("solutions/queries:rehearsalHistory"),
108
+ },
109
+ mutations: {
110
+ create: mutation("solutions/mutations:create"),
111
+ start: mutation("solutions/mutations:start"),
112
+ next: mutation("solutions/mutations:next"),
113
+ complete: mutation("solutions/mutations:complete"),
114
+ ask: mutation("solutions/mutations:ask"),
115
+ stall: mutation("solutions/mutations:stall"),
116
+ answer: mutation("solutions/mutations:answer"),
117
+ // A rehearsal's scripted approval of a checkpoint (CHECKPOINT-1.1).
118
+ approveCheckpoint: mutation("solutions/mutations:approveCheckpoint"),
119
+ removeRehearsal: mutation("solutions/mutations:removeRehearsal"),
120
+ // SIGHT-7.0: where a video is uploaded before it is submitted
121
+ videoUploadUrl: mutation("solutions/mutations:videoUploadUrl"),
122
+ },
123
+ // SOLSHARE: a solution's share command, on its token alone.
124
+ shares: {
125
+ forCheckout: query("solutions/shares:forCheckout"),
126
+ push: mutation("solutions/shares:push"),
127
+ done: mutation("solutions/shares:done"),
128
+ },
129
+ // SIGHT-9: where an image is uploaded before it is submitted, and where
130
+ // the copies an outcome works on are fetched from.
131
+ images: {
132
+ uploadUrl: mutation("solutions/images:uploadUrl"),
133
+ // REHEARSE-4.7: an image a scenario names for an input, before the solution exists
134
+ inputUploadUrl: mutation("solutions/images:inputUploadUrl"),
135
+ copies: query("solutions/images:copies"),
136
+ },
137
+ // SOLBRANCH, REHEARSE-6.7: a solution's branch and its pushes.
138
+ branches: {
139
+ branchOf: query("solutions/branches:branchOf"),
140
+ claim: mutation("solutions/branches:claim"),
141
+ recordPush: mutation("solutions/branches:recordPush"),
142
+ removal: query("solutions/branches:removal"),
78
143
  },
79
144
  },
80
145
  lib: {
@@ -11,8 +11,10 @@
11
11
  */
12
12
  import { execSync } from "node:child_process";
13
13
  import { randomUUID } from "node:crypto";
14
+ import { convexUrl } from "../cloud.js";
14
15
  import { canonicalRequirementPath } from "../schema/index.js";
15
16
  import { getProjectInfo } from "../utils/project-settings.js";
17
+ import { enableVersionMessages, formatVersionMessages, markVersionMessagesShown, versionMessages, } from "../version-messages.js";
16
18
  import { cleanupTestRunId, clearCoverageReportFailure, deleteTrackingFile, findProjectRoot, findRequirementsDir, getTestRunId, needsReporting, readCoverageCache, readLookupCache, readTrackingEntries, recordCoverageReplayed, recordCoverageReported, recordCoverageReportFailure, updateCoverageCache, } from "./cache.js";
17
19
  import { formatFailureNotice, formatUnrecordedNotice, refusalReason, } from "./reportingStatus.js";
18
20
  import { toProjectRelativePath } from "./tracking.js";
@@ -130,10 +132,6 @@ function printLocalReport(testedKeys, lookup, options) {
130
132
  console.log(report);
131
133
  }
132
134
  }
133
- /**
134
- * Production Convex deployment URL
135
- */
136
- const CONVEX_URL = "https://data.dotrequirements.io";
137
135
  /**
138
136
  * Record a reporting attempt that did not reach the cloud, so later runs and
139
137
  * `dotreq report` keep saying so (COVERAGE-REPORT-3), and hand the reason back
@@ -190,18 +188,18 @@ const REPORT_TIMEOUT_MS = 15_000;
190
188
  */
191
189
  async function postCoverage(credentials, report) {
192
190
  // Note: projectId from env is always a slug (e.g., "reduced-cephalopod-288"),
193
- // not a Convex ID. Use projectSlug field for authentication and slug for target.
194
- const response = await fetch(`${CONVEX_URL}/api/mutation`, {
191
+ // not a Convex ID. It names the project both to authenticate and as the report's project.
192
+ const response = await fetch(`${convexUrl()}/api/mutation`, {
195
193
  method: "POST",
196
194
  headers: { "Content-Type": "application/json" },
197
195
  body: JSON.stringify({
198
- path: "testCoverage/mutations:recordCoverage",
196
+ path: "testCoverage/mutations:record",
199
197
  args: {
200
198
  projectAuth: {
201
199
  projectSlug: credentials.projectId,
202
200
  projectSecret: credentials.projectSecret,
203
201
  },
204
- target: { type: "project", slug: credentials.projectId },
202
+ project: credentials.projectId,
205
203
  branch: report.branch,
206
204
  context: report.context,
207
205
  runId: report.runId,
@@ -528,6 +526,9 @@ export async function finalize(options = {}) {
528
526
  count: 0,
529
527
  };
530
528
  if (shouldReportToCloud) {
529
+ // CLI-MSG-1.4: a run that reports to the cloud hears what it has to say
530
+ // to this version.
531
+ enableVersionMessages();
531
532
  cloudResult = await reportToConvex(projectRoot, testRunId, aggregated, showCloudStatus, context);
532
533
  }
533
534
  // Read once, after reporting has had its say, for both the report header and
@@ -551,6 +552,13 @@ export async function finalize(options = {}) {
551
552
  (recordedThisRun ? null : coverageCache?.lastFailure)),
552
553
  });
553
554
  }
555
+ // CLI-MSG-1.4: the summary closes with the cloud's messages for this
556
+ // version — ahead of the notice below, which keeps the last word.
557
+ const messages = await versionMessages();
558
+ if (messages.length > 0) {
559
+ console.error(`${formatVersionMessages(messages)}\n`);
560
+ }
561
+ markVersionMessagesShown();
554
562
  // COVERAGE-REPORT-2.1, -3.0: the run's last word is whether coverage
555
563
  // recorded. Written to stderr so it cannot be silenced by a quiet run or
556
564
  // swallowed by a caller parsing stdout — a failure nobody sees is the whole
@@ -5,6 +5,7 @@
5
5
  * COVERAGE-REPORT-2 / -3 (the run says coverage did not record, and keeps
6
6
  * saying it until it does).
7
7
  */
8
+ import { userFacingMessage } from "../utils/command-error.js";
8
9
  /**
9
10
  * Shown when a refusal carries nothing a developer could act on
10
11
  * (COVERAGE-REPORT-1.2). The raw `errorMessage` is deliberately not used in its
@@ -19,17 +20,7 @@ export const REFUSAL_WITHOUT_REASON = "the cloud refused the report without givi
19
20
  * ConvexError's data is either a plain string or an object carrying `message`.
20
21
  */
21
22
  export function refusalReason(response) {
22
- const data = response.errorData;
23
- if (typeof data === "string" && data.trim()) {
24
- return data;
25
- }
26
- if (data && typeof data === "object" && "message" in data) {
27
- const { message } = data;
28
- if (typeof message === "string" && message.trim()) {
29
- return message;
30
- }
31
- }
32
- return REFUSAL_WITHOUT_REASON;
23
+ return userFacingMessage(response.errorData) ?? REFUSAL_WITHOUT_REASON;
33
24
  }
34
25
  const MONTHS = [
35
26
  "January",
package/dist/push/core.js CHANGED
@@ -35,8 +35,13 @@ export function parseFilesForPush(filePaths) {
35
35
  for (const filePath of filePaths) {
36
36
  // Read raw file content
37
37
  const rawContent = fs.readFileSync(filePath, "utf-8");
38
- // Parse to get metadata and requirements
39
- const parsed = parseRequirementsFromFile(filePath);
38
+ // Parse to get metadata and requirements. A file without the
39
+ // `.requirements.md` name is a solution's other document (SOLDOC-3): it
40
+ // has no requirement blocks, maybe no frontmatter yet, and is still a
41
+ // document.
42
+ const parsed = parseRequirementsFromFile(filePath, {
43
+ solutionDocument: !filePath.endsWith(".requirements.md"),
44
+ });
40
45
  const flatRequirements = getAllRequirements(parsed.requirements);
41
46
  // Extract markdown content (everything after frontmatter)
42
47
  const markdownContent = extractMarkdownContent(rawContent);
@@ -0,0 +1,23 @@
1
+ import type { Plan, PlanPart } from "./types.js";
2
+ /**
3
+ * Some of a plan's outcomes given their inputs (REHEARSE-1.0, 1.6, 1.8):
4
+ * the smallest plan holding those outcomes, in the plan's order and
5
+ * phases, whose inputs are what they await, are against or are on that
6
+ * none of them is, so they run as if the outcomes before them were made.
7
+ * So a scenario naming Scores alone, of the default plan, runs the scores
8
+ * with the pitch an input. An outcome on one left out is kept on that
9
+ * one's surface instead. The checkpoints on what is kept stay, presenting
10
+ * what is still there; loops go, since part of a plan starts or ends
11
+ * nothing.
12
+ *
13
+ * The one exception is the outcome that makes the solution exist: the
14
+ * plan's first outcome when the person makes it at creation, with an agent
15
+ * (the Idea in the default plan, which is the solution itself). When a
16
+ * chosen outcome works from it, it is kept at the head of the derived plan,
17
+ * so the solution is the idea there as in production, and the scenario
18
+ * names nothing for it.
19
+ */
20
+ export declare function planForOutcomes(plan: Plan, names: readonly string[]): Plan;
21
+ /** The plan a scenario names: the whole one, or some of its outcomes derived from it. */
22
+ export declare function planOf(plan: Plan | PlanPart): Plan;
23
+ //# sourceMappingURL=derive.d.ts.map
@@ -0,0 +1,112 @@
1
+ /** Every outcome in the plan, in its order. */
2
+ const outcomesOf = (plan) => plan.phases.flatMap((phase) => phase.outcomes);
3
+ /** The surface an outcome is kept on: its own, or the one the outcome it is on is kept on. */
4
+ function surfaceOf(plan, name) {
5
+ const seen = new Set();
6
+ let current = name;
7
+ for (;;) {
8
+ if (seen.has(current))
9
+ return undefined;
10
+ seen.add(current);
11
+ const outcome = outcomesOf(plan).find((each) => each.name === current);
12
+ if (!outcome) {
13
+ return plan.surfaces.find((surface) => surface.name === current)?.name;
14
+ }
15
+ if (plan.surfaces.some((surface) => surface.name === outcome.on)) {
16
+ return outcome.on;
17
+ }
18
+ current = outcome.on;
19
+ }
20
+ }
21
+ /** What an outcome waits on or works from: what it and its review await, what it is against, and the outcome it is on. */
22
+ const worksFrom = (plan, outcome) => [
23
+ ...(outcome.awaits ?? []),
24
+ ...(outcome.reviewAwaits ?? []),
25
+ ...(outcome.against ?? []),
26
+ ...(outcomesOf(plan).some((each) => each.name === outcome.on)
27
+ ? [outcome.on]
28
+ : []),
29
+ ];
30
+ /**
31
+ * Some of a plan's outcomes given their inputs (REHEARSE-1.0, 1.6, 1.8):
32
+ * the smallest plan holding those outcomes, in the plan's order and
33
+ * phases, whose inputs are what they await, are against or are on that
34
+ * none of them is, so they run as if the outcomes before them were made.
35
+ * So a scenario naming Scores alone, of the default plan, runs the scores
36
+ * with the pitch an input. An outcome on one left out is kept on that
37
+ * one's surface instead. The checkpoints on what is kept stay, presenting
38
+ * what is still there; loops go, since part of a plan starts or ends
39
+ * nothing.
40
+ *
41
+ * The one exception is the outcome that makes the solution exist: the
42
+ * plan's first outcome when the person makes it at creation, with an agent
43
+ * (the Idea in the default plan, which is the solution itself). When a
44
+ * chosen outcome works from it, it is kept at the head of the derived plan,
45
+ * so the solution is the idea there as in production, and the scenario
46
+ * names nothing for it.
47
+ */
48
+ export function planForOutcomes(plan, names) {
49
+ const all = outcomesOf(plan);
50
+ for (const name of names) {
51
+ if (!all.some((outcome) => outcome.name === name)) {
52
+ throw new Error(`The plan has no outcome called "${name}". Its outcomes: ${all.map((outcome) => outcome.name).join(", ")}.`);
53
+ }
54
+ }
55
+ const chosen = new Set(names);
56
+ const first = all[0];
57
+ const creation = first?.createdWith !== undefined && !chosen.has(first.name)
58
+ ? first
59
+ : undefined;
60
+ const picked = all.filter((outcome) => chosen.has(outcome.name));
61
+ const needed = [
62
+ ...new Set(picked.flatMap((outcome) => worksFrom(plan, outcome))),
63
+ ].filter((name) => !chosen.has(name));
64
+ const keepsCreation = !!creation && needed.includes(creation.name);
65
+ const kept = new Set([
66
+ ...chosen,
67
+ ...(keepsCreation && creation ? [creation.name] : []),
68
+ ]);
69
+ const inputs = [
70
+ ...plan.inputs.filter((name) => needed.includes(name)),
71
+ ...all
72
+ .map((outcome) => outcome.name)
73
+ .filter((name) => needed.includes(name) && !kept.has(name)),
74
+ ];
75
+ const phases = plan.phases.flatMap((phase) => {
76
+ const outcomes = phase.outcomes
77
+ .filter((outcome) => kept.has(outcome.name))
78
+ .map((outcome) =>
79
+ // On an outcome left out, it is kept on that one's surface.
80
+ all.some((each) => each.name === outcome.on) && !kept.has(outcome.on)
81
+ ? { ...outcome, on: surfaceOf(plan, outcome.on) ?? outcome.on }
82
+ : outcome);
83
+ return outcomes.length > 0 ? [{ ...phase, outcomes }] : [];
84
+ });
85
+ const known = new Set([...kept, ...inputs]);
86
+ const keptOn = (on) => kept.has(on) ||
87
+ [...kept].some((name) => surfaceOf(plan, name) === on && name !== on);
88
+ const checkpoints = plan.checkpoints.flatMap((checkpoint) => {
89
+ if (!keptOn(checkpoint.on))
90
+ return [];
91
+ if (!checkpoint.presents?.length)
92
+ return [checkpoint];
93
+ const presents = checkpoint.presents.filter((name) => known.has(name));
94
+ return presents.length > 0 ? [{ ...checkpoint, presents }] : [];
95
+ });
96
+ return {
97
+ format: "outcomes",
98
+ inputs,
99
+ surfaces: plan.surfaces,
100
+ phases,
101
+ checkpoints,
102
+ agents: plan.agents,
103
+ loops: [],
104
+ };
105
+ }
106
+ /** The plan a scenario names: the whole one, or some of its outcomes derived from it. */
107
+ export function planOf(plan) {
108
+ if (!("from" in plan))
109
+ return plan;
110
+ return planForOutcomes(plan.from, plan.outcomes);
111
+ }
112
+ //# sourceMappingURL=derive.js.map
@@ -0,0 +1,44 @@
1
+ import type { Party, Plan, RehearsalClient, RehearsalReport, Scenario } from "./types.js";
2
+ /**
3
+ * The plan a scenario rehearses, refused when it names an outcome the plan
4
+ * doesn't have or leaves one of its inputs holding nothing: what a live
5
+ * rehearsal checks before it removes the scenario's earlier runs, so a
6
+ * mistake in the scenario never costs the run under review. An input the
7
+ * scenario doesn't name holds something when the earlier rehearsal it
8
+ * starts from holds it (REHEARSE-4.8).
9
+ */
10
+ export declare function checkScenario(scenario: Scenario): Plan;
11
+ /** A part of an outcome's work: drafting it, reviewing it, or, with no agent, making it from outside. */
12
+ export type Part = {
13
+ outcome: string;
14
+ part: "draft" | "review" | "outside";
15
+ /** The agent; absent for an outcome someone outside, or the owner with an agent, makes. */
16
+ agent?: string;
17
+ /** Who makes it from outside, when the panel says. */
18
+ party?: string;
19
+ };
20
+ /**
21
+ * Who plays an agent at a part of an outcome's work in a scenario: the key
22
+ * naming that agent on that outcome (`Code/Code Reviewer`), then the key
23
+ * naming the part — the outcome's name for its drafter or whoever makes it
24
+ * from outside (`Pitch`), "<outcome>/reviewer" for its reviewers
25
+ * (`Pitch/reviewer`) — then the agent's own name (`Acceptance Tester`, or
26
+ * `Pitch/drafter` for one dedicated to its outcome), then whoever outside
27
+ * makes it (`release manager`). Unnamed, an agent is real. The key that
28
+ * matched, for counting turns.
29
+ */
30
+ export declare function partiesOf(parties: Scenario["parties"]): (at: Part) => {
31
+ party: Party;
32
+ key: string;
33
+ };
34
+ /**
35
+ * The driver (docs/working/rehearsing-steps.md): the orchestrator the
36
+ * product has as events, as a loop. Look at where every outcome stands;
37
+ * for each part of the work due, find who plays its agent; play a script
38
+ * through the same verbs an agent uses — `next` for the agent, then what
39
+ * its script records — or wait for a real one; answer decisions and
40
+ * checkpoints from the person's script; stop when nothing is ready, or
41
+ * when something needs a person nobody scripted, or an agent stalls.
42
+ */
43
+ export declare function rehearse(client: RehearsalClient, scenario: Scenario): Promise<RehearsalReport>;
44
+ //# sourceMappingURL=driver.d.ts.map