@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.
- package/dist/cli.js +32 -7
- package/dist/cloud.d.ts +18 -0
- package/dist/cloud.js +38 -0
- package/dist/commands/board/index.d.ts +13 -0
- package/dist/commands/board/index.js +96 -0
- package/dist/commands/branch-merge.d.ts +78 -0
- package/dist/commands/branch-merge.js +129 -0
- package/dist/commands/create-requirement-document.js +2 -2
- package/dist/commands/diff.js +15 -5
- package/dist/commands/init.js +7 -6
- package/dist/commands/link.js +27 -21
- package/dist/commands/mockup/index.d.ts +11 -0
- package/dist/commands/mockup/index.js +82 -0
- package/dist/commands/report.js +22 -9
- package/dist/commands/review-test.js +3 -2
- package/dist/commands/scores/index.d.ts +50 -0
- package/dist/commands/scores/index.js +190 -0
- package/dist/commands/solution/ask.d.ts +9 -0
- package/dist/commands/solution/ask.js +27 -0
- package/dist/commands/solution/author.d.ts +19 -0
- package/dist/commands/solution/author.js +202 -0
- package/dist/commands/solution/branch.d.ts +103 -0
- package/dist/commands/solution/branch.js +341 -0
- package/dist/commands/solution/brief.d.ts +81 -0
- package/dist/commands/solution/brief.js +47 -0
- package/dist/commands/solution/checkout.d.ts +27 -0
- package/dist/commands/solution/checkout.js +66 -0
- package/dist/commands/solution/client.d.ts +16 -0
- package/dist/commands/solution/client.js +46 -0
- package/dist/commands/solution/contract.d.ts +9 -0
- package/dist/commands/solution/contract.js +23 -0
- package/dist/commands/solution/create.d.ts +14 -0
- package/dist/commands/solution/create.js +52 -0
- package/dist/commands/solution/demo-script.d.ts +28 -0
- package/dist/commands/solution/demo-script.js +43 -0
- package/dist/commands/solution/image.d.ts +60 -0
- package/dist/commands/solution/image.js +148 -0
- package/dist/commands/solution/index.d.ts +12 -0
- package/dist/commands/solution/index.js +281 -0
- package/dist/commands/solution/look-up.d.ts +9 -0
- package/dist/commands/solution/look-up.js +69 -0
- package/dist/commands/solution/next.d.ts +12 -0
- package/dist/commands/solution/next.js +48 -0
- package/dist/commands/solution/plan-file.d.ts +22 -0
- package/dist/commands/solution/plan-file.js +33 -0
- package/dist/commands/solution/preview-screenshot.d.ts +21 -0
- package/dist/commands/solution/preview-screenshot.js +56 -0
- package/dist/commands/solution/pull-request.d.ts +25 -0
- package/dist/commands/solution/pull-request.js +117 -0
- package/dist/commands/solution/pushing.d.ts +66 -0
- package/dist/commands/solution/pushing.js +185 -0
- package/dist/commands/solution/rehearse.d.ts +10 -0
- package/dist/commands/solution/rehearse.js +24 -0
- package/dist/commands/solution/request.d.ts +3 -0
- package/dist/commands/solution/request.js +13 -0
- package/dist/commands/solution/review.d.ts +27 -0
- package/dist/commands/solution/review.js +104 -0
- package/dist/commands/solution/run-file.d.ts +42 -0
- package/dist/commands/solution/run-file.js +63 -0
- package/dist/commands/solution/share.d.ts +62 -0
- package/dist/commands/solution/share.js +346 -0
- package/dist/commands/solution/stall.d.ts +14 -0
- package/dist/commands/solution/stall.js +41 -0
- package/dist/commands/solution/start.d.ts +11 -0
- package/dist/commands/solution/start.js +20 -0
- package/dist/commands/solution/status.d.ts +39 -0
- package/dist/commands/solution/status.js +145 -0
- package/dist/commands/solution/summary.d.ts +13 -0
- package/dist/commands/solution/summary.js +5 -0
- package/dist/commands/solution/things.d.ts +118 -0
- package/dist/commands/solution/things.js +78 -0
- package/dist/commands/solution/thread.d.ts +13 -0
- package/dist/commands/solution/thread.js +53 -0
- package/dist/commands/solution/upload.d.ts +24 -0
- package/dist/commands/solution/upload.js +27 -0
- package/dist/commands/solution/video.d.ts +88 -0
- package/dist/commands/solution/video.js +364 -0
- package/dist/commands/solution/working-folder.d.ts +44 -0
- package/dist/commands/solution/working-folder.js +64 -0
- package/dist/commands/style-check.js +4 -4
- package/dist/commands/sync.d.ts +2 -1
- package/dist/commands/sync.js +21 -5
- package/dist/convex.d.ts +64 -10
- package/dist/convex.js +75 -10
- package/dist/harness/finalize.js +16 -8
- package/dist/harness/reportingStatus.js +2 -11
- package/dist/push/core.js +7 -2
- package/dist/rehearsal/derive.d.ts +23 -0
- package/dist/rehearsal/derive.js +112 -0
- package/dist/rehearsal/driver.d.ts +44 -0
- package/dist/rehearsal/driver.js +337 -0
- package/dist/rehearsal/earlier.d.ts +25 -0
- package/dist/rehearsal/earlier.js +138 -0
- package/dist/rehearsal/index.d.ts +5 -0
- package/dist/rehearsal/index.js +4 -0
- package/dist/rehearsal/live.d.ts +72 -0
- package/dist/rehearsal/live.js +301 -0
- package/dist/rehearsal/report.d.ts +4 -0
- package/dist/rehearsal/report.js +69 -0
- package/dist/rehearsal/types.d.ts +377 -0
- package/dist/rehearsal/types.js +8 -0
- package/dist/requirements/cloud-ai.d.ts +0 -6
- package/dist/requirements/cloud-ai.js +2 -11
- package/dist/requirements/cloud-coverage.js +4 -4
- package/dist/requirements/index.d.ts +6 -0
- package/dist/requirements/index.js +24 -0
- package/dist/schema/browser.d.ts +1 -1
- package/dist/schema/browser.js +3 -1
- package/dist/schema/file-writer.d.ts +5 -0
- package/dist/schema/file-writer.js +4 -0
- package/dist/schema/parser.d.ts +11 -2
- package/dist/schema/parser.js +11 -7
- package/dist/schema/schemas.d.ts +40 -0
- package/dist/schema/schemas.js +4 -0
- package/dist/sync/execute.d.ts +10 -1
- package/dist/sync/execute.js +76 -24
- package/dist/sync/index.d.ts +1 -1
- package/dist/sync/index.js +1 -1
- package/dist/sync/publish.d.ts +7 -0
- package/dist/sync/publish.js +2 -2
- package/dist/sync/segment.js +4 -1
- package/dist/sync/snapshot.d.ts +27 -5
- package/dist/sync/snapshot.js +92 -15
- package/dist/sync/solution-documents.d.ts +64 -0
- package/dist/sync/solution-documents.js +97 -0
- package/dist/sync/types.d.ts +19 -1
- package/dist/utils/command-error.d.ts +19 -0
- package/dist/utils/command-error.js +44 -0
- package/dist/utils/oauth-flow.js +2 -2
- package/dist/utils/project-selector.js +4 -4
- package/dist/version-messages.d.ts +28 -0
- package/dist/version-messages.js +87 -0
- package/package.json +3 -2
- package/dist/config.d.ts +0 -5
- package/dist/config.js +0 -12
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `dotreq solution next` prints. The brief for an outcome is composed
|
|
3
|
+
* in the backend, entirely from blocks (docs/working/prompt-blocks.md), and
|
|
4
|
+
* arrives as `text`; the CLI prints it as given and renders nothing of its
|
|
5
|
+
* own. The shapes mirror what `solutions/mutations:next` and
|
|
6
|
+
* `solutions/queries:getPlan` return, as far as the CLI reads them (the CLI
|
|
7
|
+
* doesn't import the backend's types).
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* An outcome to draft (`step`) or to review (`review`): the outcome, the
|
|
11
|
+
* brief the agent reads, and the outcomes it reviews and works from, whose
|
|
12
|
+
* images and demo scripts `next` saves in the checkout (SIGHT-9.3, 13.1).
|
|
13
|
+
*/
|
|
14
|
+
export type Brief = {
|
|
15
|
+
kind: "step" | "review";
|
|
16
|
+
/** The outcome the agent took; `label` is its name too. */
|
|
17
|
+
step: {
|
|
18
|
+
label: string;
|
|
19
|
+
outcome?: string;
|
|
20
|
+
};
|
|
21
|
+
text: string;
|
|
22
|
+
reviewing?: BriefOutcome[];
|
|
23
|
+
against?: BriefOutcome[];
|
|
24
|
+
};
|
|
25
|
+
/** An outcome the brief lists, as far as the CLI reads it. */
|
|
26
|
+
export type BriefOutcome = {
|
|
27
|
+
name: string;
|
|
28
|
+
things?: Array<{
|
|
29
|
+
kind: string;
|
|
30
|
+
storageId?: string;
|
|
31
|
+
name?: string;
|
|
32
|
+
script?: string;
|
|
33
|
+
}>;
|
|
34
|
+
};
|
|
35
|
+
/** An outcome on the plan panel, as far as the CLI reads it. */
|
|
36
|
+
export type PanelOutcome = {
|
|
37
|
+
name: string;
|
|
38
|
+
/** The one word it stands in: ready, drafting, reviewing, awaiting decision, stalled, done... */
|
|
39
|
+
status: string;
|
|
40
|
+
/** The agent that drafts it, when an agent of ours does. */
|
|
41
|
+
drafter?: string;
|
|
42
|
+
/** The agents that review it. */
|
|
43
|
+
reviewers?: string[];
|
|
44
|
+
/** Why one of its agents stalled. */
|
|
45
|
+
reason?: string;
|
|
46
|
+
/** Who it waits on, when someone outside creates it. */
|
|
47
|
+
party?: string;
|
|
48
|
+
/** For an outcome not started: what it can't begin without. */
|
|
49
|
+
waitingFor?: string[];
|
|
50
|
+
/** Its drafter's work was set aside and its new draft isn't taken yet: a session at it owes nothing more (CHECKPOINT-6.3.2.3). */
|
|
51
|
+
setAside?: boolean;
|
|
52
|
+
};
|
|
53
|
+
/** A checkpoint on the plan panel, as far as the CLI reads it. */
|
|
54
|
+
export type PanelCheckpoint = {
|
|
55
|
+
name: string;
|
|
56
|
+
/** waiting, deciding (on the owner now), fixing, deferred or approved. */
|
|
57
|
+
stands: string;
|
|
58
|
+
};
|
|
59
|
+
/** The plan panel (`getPlan`): its outcomes by phase, and its checkpoints. */
|
|
60
|
+
export type Panel = {
|
|
61
|
+
title: string;
|
|
62
|
+
phases: Array<{
|
|
63
|
+
name: string;
|
|
64
|
+
outcomes: PanelOutcome[];
|
|
65
|
+
}>;
|
|
66
|
+
checkpoints?: PanelCheckpoint[];
|
|
67
|
+
};
|
|
68
|
+
export type Standing = {
|
|
69
|
+
kind: "nothing ready";
|
|
70
|
+
plan: Panel;
|
|
71
|
+
};
|
|
72
|
+
export type NextResult = Brief | Standing;
|
|
73
|
+
export declare const EXIT: {
|
|
74
|
+
/** Nothing is ready: a loop of `next` can stop here. */
|
|
75
|
+
readonly nothingReady: 3;
|
|
76
|
+
};
|
|
77
|
+
/** Every outcome on the panel, in the plan's order. */
|
|
78
|
+
export declare function outcomesOf(panel: Pick<Panel, "phases">): PanelOutcome[];
|
|
79
|
+
/** Nothing ready: every outcome and what it waits on, then any checkpoint the owner is at. */
|
|
80
|
+
export declare function renderStanding({ plan }: Standing): string;
|
|
81
|
+
//# sourceMappingURL=brief.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What `dotreq solution next` prints. The brief for an outcome is composed
|
|
3
|
+
* in the backend, entirely from blocks (docs/working/prompt-blocks.md), and
|
|
4
|
+
* arrives as `text`; the CLI prints it as given and renders nothing of its
|
|
5
|
+
* own. The shapes mirror what `solutions/mutations:next` and
|
|
6
|
+
* `solutions/queries:getPlan` return, as far as the CLI reads them (the CLI
|
|
7
|
+
* doesn't import the backend's types).
|
|
8
|
+
*/
|
|
9
|
+
export const EXIT = {
|
|
10
|
+
/** Nothing is ready: a loop of `next` can stop here. */
|
|
11
|
+
nothingReady: 3,
|
|
12
|
+
};
|
|
13
|
+
/** Every outcome on the panel, in the plan's order. */
|
|
14
|
+
export function outcomesOf(panel) {
|
|
15
|
+
return panel.phases.flatMap((phase) => phase.outcomes);
|
|
16
|
+
}
|
|
17
|
+
/** Nothing ready: every outcome and what it waits on, then any checkpoint the owner is at. */
|
|
18
|
+
export function renderStanding({ plan }) {
|
|
19
|
+
const lines = [`Nothing is ready on "${plan.title}".`, ""];
|
|
20
|
+
for (const outcome of outcomesOf(plan)) {
|
|
21
|
+
lines.push(`- ${outcome.name}: ${standing(outcome)}`);
|
|
22
|
+
}
|
|
23
|
+
for (const checkpoint of plan.checkpoints ?? []) {
|
|
24
|
+
const stands = CHECKPOINT_STANDS[checkpoint.stands];
|
|
25
|
+
if (stands)
|
|
26
|
+
lines.push(`- The ${checkpoint.name} checkpoint: ${stands}`);
|
|
27
|
+
}
|
|
28
|
+
return `${lines.join("\n")}\n`;
|
|
29
|
+
}
|
|
30
|
+
/** A checkpoint worth a line when nothing is ready: one that holds the work up. */
|
|
31
|
+
const CHECKPOINT_STANDS = {
|
|
32
|
+
deciding: "waiting on the owner's decision",
|
|
33
|
+
fixing: "a fix is running",
|
|
34
|
+
deferred: "deferred by the owner",
|
|
35
|
+
};
|
|
36
|
+
function standing(outcome) {
|
|
37
|
+
if (outcome.status === "stalled" && outcome.reason)
|
|
38
|
+
return `stalled — ${outcome.reason}`;
|
|
39
|
+
if (outcome.status === "awaiting external" && outcome.party) {
|
|
40
|
+
return `awaiting ${outcome.party}`;
|
|
41
|
+
}
|
|
42
|
+
if (outcome.status === "not started" && outcome.waitingFor?.length) {
|
|
43
|
+
return `not started — after ${outcome.waitingFor.join(", ")}`;
|
|
44
|
+
}
|
|
45
|
+
return outcome.status;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=brief.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type WhereOptions } from "./run-file.js";
|
|
2
|
+
/**
|
|
3
|
+
* `dotreq solution checkout`: what the runner runs in its checkout before
|
|
4
|
+
* each session (SOLBRANCH-1, 2). Puts the checkout on the branch of the
|
|
5
|
+
* surface the outcome is kept on (1.5), making it on that surface's first
|
|
6
|
+
* session, and brings in what other agents pushed to it. Prints the branch and what the agent is to
|
|
7
|
+
* be told before its brief, if anything; with `--json`, as one line the
|
|
8
|
+
* runner reads.
|
|
9
|
+
*/
|
|
10
|
+
export declare function checkoutCommand(options: WhereOptions & {
|
|
11
|
+
json?: boolean;
|
|
12
|
+
share?: string;
|
|
13
|
+
branchWins?: boolean;
|
|
14
|
+
}): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* `dotreq solution push`: what the runner runs when a session ends
|
|
17
|
+
* (SOLBRANCH-4.0). Pushes the commits the agent made after its last record
|
|
18
|
+
* to the run's branch, its commits after any other agents pushed since;
|
|
19
|
+
* never commits what it left uncommitted (SOLBRANCH-6.0). Prints whether
|
|
20
|
+
* it pushed and, when it couldn't, why; with `--json`, as one line.
|
|
21
|
+
* Outside a runner there is no branch to push to, and nothing happens.
|
|
22
|
+
*/
|
|
23
|
+
export declare function pushCommand(options: WhereOptions & {
|
|
24
|
+
json?: boolean;
|
|
25
|
+
repoWins?: boolean;
|
|
26
|
+
}): Promise<void>;
|
|
27
|
+
//# sourceMappingURL=checkout.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { solutionClient } from "./client.js";
|
|
2
|
+
import { checkOutSolution, pushWork } from "./pushing.js";
|
|
3
|
+
import { requireSolution, whereOf } from "./run-file.js";
|
|
4
|
+
import { shareCheckout, sharePush } from "./share.js";
|
|
5
|
+
/**
|
|
6
|
+
* `dotreq solution checkout`: what the runner runs in its checkout before
|
|
7
|
+
* each session (SOLBRANCH-1, 2). Puts the checkout on the branch of the
|
|
8
|
+
* surface the outcome is kept on (1.5), making it on that surface's first
|
|
9
|
+
* session, and brings in what other agents pushed to it. Prints the branch and what the agent is to
|
|
10
|
+
* be told before its brief, if anything; with `--json`, as one line the
|
|
11
|
+
* runner reads.
|
|
12
|
+
*/
|
|
13
|
+
export async function checkoutCommand(options) {
|
|
14
|
+
// SOLSHARE-2: from any repository, on a solution's share command.
|
|
15
|
+
if (options.share) {
|
|
16
|
+
await shareCheckout(options.share, (options.outcome ?? options.step)?.trim() || undefined, options.branchWins);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const { solutionId } = requireSolution(options);
|
|
20
|
+
// SOLBRANCH-1.5: the branch of the surface the outcome is kept on.
|
|
21
|
+
const outcome = (options.outcome ?? options.step)?.trim() || undefined;
|
|
22
|
+
const { branch, notice } = await checkOutSolution(solutionClient(), solutionId, process.cwd(), outcome);
|
|
23
|
+
if (options.json) {
|
|
24
|
+
process.stdout.write(`${JSON.stringify({ branch, notice })}\n`);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
console.log(`On ${branch}.`);
|
|
28
|
+
if (notice)
|
|
29
|
+
console.log(`\n${notice}`);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* `dotreq solution push`: what the runner runs when a session ends
|
|
33
|
+
* (SOLBRANCH-4.0). Pushes the commits the agent made after its last record
|
|
34
|
+
* to the run's branch, its commits after any other agents pushed since;
|
|
35
|
+
* never commits what it left uncommitted (SOLBRANCH-6.0). Prints whether
|
|
36
|
+
* it pushed and, when it couldn't, why; with `--json`, as one line.
|
|
37
|
+
* Outside a runner there is no branch to push to, and nothing happens.
|
|
38
|
+
*/
|
|
39
|
+
export async function pushCommand(options) {
|
|
40
|
+
const where = whereOf(options);
|
|
41
|
+
// SOLSHARE-3: a repository a solution was checked out into, with no run.
|
|
42
|
+
if (!where.branch && (await sharePush(options.solution, options.repoWins)))
|
|
43
|
+
return;
|
|
44
|
+
if (!where.branch && !options.json) {
|
|
45
|
+
throw new Error("No solution is checked out here: run the share command you were given first.");
|
|
46
|
+
}
|
|
47
|
+
const outcome = where.solutionId && where.branch
|
|
48
|
+
? await pushWork(solutionClient(), {
|
|
49
|
+
solutionId: where.solutionId,
|
|
50
|
+
branch: where.branch,
|
|
51
|
+
})
|
|
52
|
+
: { ok: true, pushed: false };
|
|
53
|
+
const result = outcome.ok
|
|
54
|
+
? { pushed: outcome.pushed, failure: null }
|
|
55
|
+
: { pushed: false, failure: outcome.why };
|
|
56
|
+
if (options.json) {
|
|
57
|
+
process.stdout.write(`${JSON.stringify(result)}\n`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
console.log(result.failure
|
|
61
|
+
? `Not pushed: ${result.failure}.`
|
|
62
|
+
: result.pushed
|
|
63
|
+
? `Pushed to ${where.branch}.`
|
|
64
|
+
: "Nothing to push.");
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=checkout.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FunctionReference } from "convex/server";
|
|
2
|
+
/**
|
|
3
|
+
* Calls against the linked project, for the solution verbs: the project's
|
|
4
|
+
* credentials on every call, and a refusal from the backend surfaced in its
|
|
5
|
+
* own words. A call to an endpoint that names the project passes `project`
|
|
6
|
+
* itself.
|
|
7
|
+
*/
|
|
8
|
+
export declare function solutionClient(): {
|
|
9
|
+
/** The linked project, by its slug or id. */
|
|
10
|
+
project: string;
|
|
11
|
+
mutation: <R>(fn: FunctionReference<"mutation">, args: Record<string, unknown>) => Promise<R>;
|
|
12
|
+
query: <R>(fn: FunctionReference<"query">, args: Record<string, unknown>) => Promise<R>;
|
|
13
|
+
};
|
|
14
|
+
/** A backend refusal, in the words the backend gave: a plain message, or a plan's broken rules listed. */
|
|
15
|
+
export declare function refusal(data: unknown): string;
|
|
16
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ConvexHttpClient } from "convex/browser";
|
|
2
|
+
import { ConvexError } from "convex/values";
|
|
3
|
+
import { convexUrl } from "../../cloud.js";
|
|
4
|
+
import { getProjectCredentials } from "../../utils/project-settings.js";
|
|
5
|
+
/**
|
|
6
|
+
* Calls against the linked project, for the solution verbs: the project's
|
|
7
|
+
* credentials on every call, and a refusal from the backend surfaced in its
|
|
8
|
+
* own words. A call to an endpoint that names the project passes `project`
|
|
9
|
+
* itself.
|
|
10
|
+
*/
|
|
11
|
+
export function solutionClient() {
|
|
12
|
+
const { projectId, projectSecret } = getProjectCredentials();
|
|
13
|
+
const client = new ConvexHttpClient(convexUrl());
|
|
14
|
+
const auth = { projectAuth: { projectSlug: projectId, projectSecret } };
|
|
15
|
+
return {
|
|
16
|
+
/** The linked project, by its slug or id. */
|
|
17
|
+
project: projectId,
|
|
18
|
+
mutation: (fn, args) => inWords(() => client.mutation(fn, { ...auth, ...args })),
|
|
19
|
+
query: (fn, args) => inWords(() => client.query(fn, { ...auth, ...args })),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async function inWords(call) {
|
|
23
|
+
try {
|
|
24
|
+
return await call();
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (error instanceof ConvexError)
|
|
28
|
+
throw new Error(refusal(error.data));
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** A backend refusal, in the words the backend gave: a plain message, or a plan's broken rules listed. */
|
|
33
|
+
export function refusal(data) {
|
|
34
|
+
if (typeof data === "string")
|
|
35
|
+
return data;
|
|
36
|
+
if (data && typeof data === "object") {
|
|
37
|
+
const { kind, rules, message } = data;
|
|
38
|
+
if (kind === "invalid plan" && rules?.length) {
|
|
39
|
+
return `The plan breaks these rules:\n- ${rules.join("\n- ")}`;
|
|
40
|
+
}
|
|
41
|
+
if (message)
|
|
42
|
+
return message;
|
|
43
|
+
}
|
|
44
|
+
return JSON.stringify(data);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The request file `ask` reads, in words: what `dotreq solution ask --help`
|
|
3
|
+
* prints after its options, the way `author --help` carries the reference
|
|
4
|
+
* forms. The backend's `describeContract()` renders it from the schema the
|
|
5
|
+
* request is validated against; the CLI can't import the backend, so this
|
|
6
|
+
* is that text, and a test keeps the two the same.
|
|
7
|
+
*/
|
|
8
|
+
export declare const REQUEST_CONTRACT = "Ask the person to decide something about the outcome you are drafting. A choice presents options with a recommendation. One decision per request: if two things need deciding, ask twice.\n\nA request is JSON with a \"kind\" and the fields of that kind:\n\nchoice:\n question (text, up to 200 characters): The question, phrased as a question in the words the person will read it, not as a topic.\n options (list, at least 2): The live alternatives. More than four makes deciding harder; give more only when each is a genuine choice. Leave out anything you have already ruled out.\n name (text, up to 200 characters): The option as you would say it to the person: a noun phrase they can repeat back, not a label.\n benefits (list of text, each up to 200 characters): What is better if this option is taken. One line each, in your own words.\n costs (list of text, each up to 200 characters): What is worse if this option is taken: what it would take to build, and what the person lives with afterwards. Effort is a cost like any other.\n note (text, up to 600 characters, optional): Anything you learned or checked about this option that is not a benefit or a cost. Leave it out when there is nothing to add.\n recommendation (object): Which option you would take, and the one reason why.\n option (text, up to 200 characters): The name of the option you recommend, exactly as it appears in options.\n because (text, up to 200 characters): The one reason that carries it, in one line. The full reasoning belongs in background.\n background (text, up to 4000 characters): What the person needs to know to decide well that the options do not already say. Include only context that would substantially change the quality of the decision. The person reads this after the options, so do not reiterate them.";
|
|
9
|
+
//# sourceMappingURL=contract.d.ts.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The request file `ask` reads, in words: what `dotreq solution ask --help`
|
|
3
|
+
* prints after its options, the way `author --help` carries the reference
|
|
4
|
+
* forms. The backend's `describeContract()` renders it from the schema the
|
|
5
|
+
* request is validated against; the CLI can't import the backend, so this
|
|
6
|
+
* is that text, and a test keeps the two the same.
|
|
7
|
+
*/
|
|
8
|
+
export const REQUEST_CONTRACT = `Ask the person to decide something about the outcome you are drafting. A choice presents options with a recommendation. One decision per request: if two things need deciding, ask twice.
|
|
9
|
+
|
|
10
|
+
A request is JSON with a "kind" and the fields of that kind:
|
|
11
|
+
|
|
12
|
+
choice:
|
|
13
|
+
question (text, up to 200 characters): The question, phrased as a question in the words the person will read it, not as a topic.
|
|
14
|
+
options (list, at least 2): The live alternatives. More than four makes deciding harder; give more only when each is a genuine choice. Leave out anything you have already ruled out.
|
|
15
|
+
name (text, up to 200 characters): The option as you would say it to the person: a noun phrase they can repeat back, not a label.
|
|
16
|
+
benefits (list of text, each up to 200 characters): What is better if this option is taken. One line each, in your own words.
|
|
17
|
+
costs (list of text, each up to 200 characters): What is worse if this option is taken: what it would take to build, and what the person lives with afterwards. Effort is a cost like any other.
|
|
18
|
+
note (text, up to 600 characters, optional): Anything you learned or checked about this option that is not a benefit or a cost. Leave it out when there is nothing to add.
|
|
19
|
+
recommendation (object): Which option you would take, and the one reason why.
|
|
20
|
+
option (text, up to 200 characters): The name of the option you recommend, exactly as it appears in options.
|
|
21
|
+
because (text, up to 200 characters): The one reason that carries it, in one line. The full reasoning belongs in background.
|
|
22
|
+
background (text, up to 4000 characters): What the person needs to know to decide well that the options do not already say. Include only context that would substantially change the quality of the decision. The person reads this after the options, so do not reiterate them.`;
|
|
23
|
+
//# sourceMappingURL=contract.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `dotreq solution create [file]`: with no file, a solution from the
|
|
3
|
+
* project's default plan, titled with `--title`; with a plan file (YAML or
|
|
4
|
+
* JSON), its title, its description, its plan in the stored shape, and the
|
|
5
|
+
* inputs that already exist. `--description` says what the solution is
|
|
6
|
+
* beyond its title, in Markdown, and wins over the file's. The backend validates the plan and refuses an invalid one
|
|
7
|
+
* with the rules it broke.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createCommand(file: string | undefined, options?: {
|
|
10
|
+
title?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
idea?: string[];
|
|
13
|
+
}): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=create.d.ts.map
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
import { api } from "../../convex.js";
|
|
4
|
+
import { solutionClient } from "./client.js";
|
|
5
|
+
import { planPayload, readPlanFile } from "./plan-file.js";
|
|
6
|
+
import { parseThing } from "./things.js";
|
|
7
|
+
/**
|
|
8
|
+
* `dotreq solution create [file]`: with no file, a solution from the
|
|
9
|
+
* project's default plan, titled with `--title`; with a plan file (YAML or
|
|
10
|
+
* JSON), its title, its description, its plan in the stored shape, and the
|
|
11
|
+
* inputs that already exist. `--description` says what the solution is
|
|
12
|
+
* beyond its title, in Markdown, and wins over the file's. The backend validates the plan and refuses an invalid one
|
|
13
|
+
* with the rules it broke.
|
|
14
|
+
*/
|
|
15
|
+
export async function createCommand(file, options = {}) {
|
|
16
|
+
const idea = options.idea?.map(parseThing);
|
|
17
|
+
const described = options.description?.trim() || undefined;
|
|
18
|
+
if (!file) {
|
|
19
|
+
const title = options.title?.trim();
|
|
20
|
+
if (!title) {
|
|
21
|
+
throw new Error("A solution from the project's default plan needs a title: --title <title>.");
|
|
22
|
+
}
|
|
23
|
+
const client = solutionClient();
|
|
24
|
+
const id = await client.mutation(api.solutions.mutations.create, {
|
|
25
|
+
project: client.project,
|
|
26
|
+
title,
|
|
27
|
+
description: described,
|
|
28
|
+
idea,
|
|
29
|
+
});
|
|
30
|
+
console.log(`Created "${title}" from the project's default plan: ${id}`);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const spec = readPlanFile(readFileSync(resolve(process.cwd(), file), "utf8"), file);
|
|
34
|
+
const title = options.title?.trim() ||
|
|
35
|
+
(typeof spec?.title === "string" ? spec.title : undefined);
|
|
36
|
+
if (!spec?.plan || !title) {
|
|
37
|
+
throw new Error(`${file} needs a plan, and a title in the file or as --title (docs/working/plan-surfaces.md).`);
|
|
38
|
+
}
|
|
39
|
+
const client = solutionClient();
|
|
40
|
+
const id = await client.mutation(api.solutions.mutations.create, {
|
|
41
|
+
project: client.project,
|
|
42
|
+
title,
|
|
43
|
+
description: described ??
|
|
44
|
+
(typeof spec.description === "string" ? spec.description : undefined),
|
|
45
|
+
// PLAN-1: the plan as the file writes it; the backend reads it.
|
|
46
|
+
plan: planPayload(spec),
|
|
47
|
+
inputs: Array.isArray(spec.inputs) ? spec.inputs : [],
|
|
48
|
+
idea,
|
|
49
|
+
});
|
|
50
|
+
console.log(`Created "${title}": ${id}`);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=create.js.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a demo's script is saved in the checkout of the agent reviewing it
|
|
3
|
+
* (SIGHT-13.1), relative to the repository's root: the folder git ignores,
|
|
4
|
+
* under the script's file name. Kept in step with the backend's
|
|
5
|
+
* `demoScriptCopyPath` (convex/solutions/brief.ts), which is where the brief
|
|
6
|
+
* says the copy is.
|
|
7
|
+
*/
|
|
8
|
+
export declare function demoScriptCopyPath(name: string): string;
|
|
9
|
+
/** An outcome as `dotreq solution next` returns it, as far as this reads it. */
|
|
10
|
+
type BriefOutcome = {
|
|
11
|
+
things?: Array<{
|
|
12
|
+
kind: string;
|
|
13
|
+
name?: string;
|
|
14
|
+
script?: string;
|
|
15
|
+
}>;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Save a copy of each demo's script among the outcomes a reviewer reads in
|
|
19
|
+
* its checkout, where its brief says it is, so it records the video from
|
|
20
|
+
* that file and fixes anything small there first (SIGHT-13.1, 13.3). The
|
|
21
|
+
* drafter's latest script replaces any earlier copy, as when the drafter
|
|
22
|
+
* revised it. The folder ignores itself, so nothing saved there is ever
|
|
23
|
+
* committed (13.0). The review is already started, so a copy that can't be
|
|
24
|
+
* saved is said on stderr rather than failing the run.
|
|
25
|
+
*/
|
|
26
|
+
export declare function saveDemoScriptCopies(outcomes: readonly BriefOutcome[], cwd?: string): void;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=demo-script.d.ts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { basename, dirname, join } from "node:path";
|
|
3
|
+
import { repositoryRoot } from "./branch.js";
|
|
4
|
+
/**
|
|
5
|
+
* Where a demo's script is saved in the checkout of the agent reviewing it
|
|
6
|
+
* (SIGHT-13.1), relative to the repository's root: the folder git ignores,
|
|
7
|
+
* under the script's file name. Kept in step with the backend's
|
|
8
|
+
* `demoScriptCopyPath` (convex/solutions/brief.ts), which is where the brief
|
|
9
|
+
* says the copy is.
|
|
10
|
+
*/
|
|
11
|
+
export function demoScriptCopyPath(name) {
|
|
12
|
+
return `.dotreq/demo-scripts/${name}`;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Save a copy of each demo's script among the outcomes a reviewer reads in
|
|
16
|
+
* its checkout, where its brief says it is, so it records the video from
|
|
17
|
+
* that file and fixes anything small there first (SIGHT-13.1, 13.3). The
|
|
18
|
+
* drafter's latest script replaces any earlier copy, as when the drafter
|
|
19
|
+
* revised it. The folder ignores itself, so nothing saved there is ever
|
|
20
|
+
* committed (13.0). The review is already started, so a copy that can't be
|
|
21
|
+
* saved is said on stderr rather than failing the run.
|
|
22
|
+
*/
|
|
23
|
+
export function saveDemoScriptCopies(outcomes, cwd = process.cwd()) {
|
|
24
|
+
const scripts = outcomes.flatMap((outcome) => (outcome.things ?? []).flatMap((thing) => thing.kind === "demo script" && thing.name && thing.script !== undefined
|
|
25
|
+
? [{ name: basename(thing.name), script: thing.script }]
|
|
26
|
+
: []));
|
|
27
|
+
if (scripts.length === 0)
|
|
28
|
+
return;
|
|
29
|
+
const root = repositoryRoot(cwd) ?? cwd;
|
|
30
|
+
try {
|
|
31
|
+
mkdirSync(join(root, ".dotreq"), { recursive: true });
|
|
32
|
+
writeFileSync(join(root, ".dotreq", ".gitignore"), "*\n");
|
|
33
|
+
for (const { name, script } of scripts) {
|
|
34
|
+
const path = join(root, demoScriptCopyPath(name));
|
|
35
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
36
|
+
writeFileSync(path, script);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.error(`Couldn't save a copy of the demo's script: ${error instanceof Error ? error.message : String(error)}. Its text is in your brief.`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=demo-script.js.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { solutionClient } from "./client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Images on an outcome (SIGHT-9), such as a screenshot: the drafter submits an
|
|
4
|
+
* image file from its checkout or anywhere it can read, and the app keeps a
|
|
5
|
+
* copy; nothing is committed.
|
|
6
|
+
*
|
|
7
|
+
* Every browser we support (Chrome, Edge, Firefox, Safari on macOS and iOS)
|
|
8
|
+
* shows PNG, JPEG, GIF, WebP and AVIF (MDN's image type guide; AVIF from
|
|
9
|
+
* Safari 16.4). HEIC and TIFF show only in Safari, and JPEG XL not in Edge,
|
|
10
|
+
* so they are refused. SVG is refused too: opened at full size in its own
|
|
11
|
+
* tab, an SVG runs whatever script it carries. The format is read from the
|
|
12
|
+
* file's first bytes (the WHATWG MIME Sniffing signatures; AVIF's brand in
|
|
13
|
+
* its `ftyp` box), since an extension says nothing about it. Kept in step
|
|
14
|
+
* with the backend's `ACCEPTED_IMAGE_FORMATS` (convex/solutions/images.ts).
|
|
15
|
+
*/
|
|
16
|
+
export declare const ACCEPTED_IMAGE_FORMATS = "a PNG, JPEG, GIF, WebP or AVIF image";
|
|
17
|
+
export type ImageContentType = "image/png" | "image/jpeg" | "image/gif" | "image/webp" | "image/avif";
|
|
18
|
+
/** What the file is: a format a browser shows, or why it isn't one. */
|
|
19
|
+
export type ImageFormat = {
|
|
20
|
+
contentType: ImageContentType;
|
|
21
|
+
} | {
|
|
22
|
+
refused: string;
|
|
23
|
+
};
|
|
24
|
+
/** An image read from the checkout, ready to upload. */
|
|
25
|
+
export type Image = {
|
|
26
|
+
name: string;
|
|
27
|
+
contentType: ImageContentType;
|
|
28
|
+
bytes: Uint8Array<ArrayBuffer>;
|
|
29
|
+
};
|
|
30
|
+
/** The image at a path, or a refusal naming the accepted formats (SIGHT-9.0.0). */
|
|
31
|
+
export declare function readImage(path: string): Image;
|
|
32
|
+
/** What image format the bytes hold, read from the file's signature. */
|
|
33
|
+
export declare function imageFormat(bytes: Uint8Array): ImageFormat;
|
|
34
|
+
/**
|
|
35
|
+
* Where an image's copy is saved in the checkout, relative to the
|
|
36
|
+
* repository's root (SIGHT-9.3): a folder git ignores, then one folder per
|
|
37
|
+
* stored copy, so two images of one name stay apart. Kept in step with the
|
|
38
|
+
* backend's `imageCopyPath` (convex/solutions/brief.ts), which is where
|
|
39
|
+
* the brief says the copy is.
|
|
40
|
+
*/
|
|
41
|
+
export declare function imageCopyPath(storageId: string, name: string): string;
|
|
42
|
+
/** An outcome as `dotreq solution next` returns it, as far as this reads it. */
|
|
43
|
+
type BriefOutcome = {
|
|
44
|
+
things?: Array<{
|
|
45
|
+
kind: string;
|
|
46
|
+
storageId?: string;
|
|
47
|
+
}>;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Save a copy of each image among the outcomes an agent works on in the
|
|
51
|
+
* checkout, where its brief says it is (SIGHT-9.3), in place of the copies
|
|
52
|
+
* an earlier session saved. The folder ignores itself, so nothing saved
|
|
53
|
+
* there is ever committed (9.0). The work is already started, so a copy
|
|
54
|
+
* that can't be saved is said on stderr rather than failing the run.
|
|
55
|
+
*/
|
|
56
|
+
export declare function saveImageCopies(client: ReturnType<typeof solutionClient>, solutionId: string, outcomes: readonly BriefOutcome[], cwd?: string): Promise<void>;
|
|
57
|
+
/** Upload an image to the app (SIGHT-9.0), and the stored copy's id back. */
|
|
58
|
+
export declare function uploadImage(client: ReturnType<typeof solutionClient>, solutionId: string, image: Image): Promise<string>;
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=image.d.ts.map
|