cloving 1.0.1 → 1.2.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/README.md +251 -20
- package/assets/watch-fonts/fira-code-OFL.md +93 -0
- package/assets/watch-fonts/fira-code-latin-400-normal.woff2 +0 -0
- package/assets/watch-fonts/fira-code-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-OFL.md +93 -0
- package/assets/watch-fonts/heebo-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-latin-700-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-latin-800-normal.woff2 +0 -0
- package/assets/watch-fonts/manifest.json +112 -0
- package/assets/watch-fonts/space-grotesk-OFL.md +93 -0
- package/assets/watch-fonts/space-grotesk-latin-400-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-600-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-700-normal.woff2 +0 -0
- package/dist/src/authority/commands.d.ts +1 -0
- package/dist/src/authority/commands.js +33 -4
- package/dist/src/authority/dispatch-decision.d.ts +1 -0
- package/dist/src/authority/dispatch-decision.js +7 -4
- package/dist/src/authority/events.js +2 -2
- package/dist/src/authority/handoff-chain.d.ts +24 -0
- package/dist/src/authority/handoff-chain.js +46 -0
- package/dist/src/authority/reconciliation.d.ts +3 -0
- package/dist/src/authority/reconciliation.js +21 -5
- package/dist/src/authority/transitions.d.ts +1 -1
- package/dist/src/authority/transitions.js +5 -0
- package/dist/src/broker/actor/authority-queries.d.ts +4 -0
- package/dist/src/broker/actor/authority-queries.js +51 -2
- package/dist/src/broker/actor/authority-session.d.ts +2 -0
- package/dist/src/broker/actor/authority-session.js +3 -4
- package/dist/src/broker/actor/delivery-intents.d.ts +1 -0
- package/dist/src/broker/actor/effect-delivery.js +9 -0
- package/dist/src/broker/authority-admission.js +13 -5
- package/dist/src/chats/analysis-batches.d.ts +42 -0
- package/dist/src/chats/analysis-batches.js +97 -0
- package/dist/src/chats/analysis-checkpoint.d.ts +29 -0
- package/dist/src/chats/analysis-checkpoint.js +31 -0
- package/dist/src/chats/analysis-contract.d.ts +80 -0
- package/dist/src/chats/analysis-contract.js +16 -0
- package/dist/src/chats/analysis-data.d.ts +3 -0
- package/dist/src/chats/analysis-data.js +85 -0
- package/dist/src/chats/analysis-input.d.ts +18 -0
- package/dist/src/chats/analysis-input.js +97 -0
- package/dist/src/chats/analysis-links.d.ts +2 -0
- package/dist/src/chats/analysis-links.js +25 -0
- package/dist/src/chats/analysis-merge.d.ts +16 -0
- package/dist/src/chats/analysis-merge.js +134 -0
- package/dist/src/chats/analysis-prompt.d.ts +18 -0
- package/dist/src/chats/analysis-prompt.js +42 -0
- package/dist/src/chats/analysis-proposal.d.ts +4 -0
- package/dist/src/chats/analysis-proposal.js +41 -0
- package/dist/src/chats/analysis-provenance.d.ts +4 -0
- package/dist/src/chats/analysis-provenance.js +99 -0
- package/dist/src/chats/analysis-shape.d.ts +4 -0
- package/dist/src/chats/analysis-shape.js +235 -0
- package/dist/src/chats/analysis.d.ts +3 -0
- package/dist/src/chats/analysis.js +42 -0
- package/dist/src/chats/corpus-input.d.ts +5 -0
- package/dist/src/chats/corpus-input.js +288 -0
- package/dist/src/chats/destination.js +3 -1
- package/dist/src/chats/import.d.ts +8 -6
- package/dist/src/chats/import.js +195 -23
- package/dist/src/chats/input-file.d.ts +3 -0
- package/dist/src/chats/input-file.js +32 -0
- package/dist/src/chats/normalize.d.ts +11 -2
- package/dist/src/chats/normalize.js +18 -2
- package/dist/src/chats/previous-import.d.ts +5 -0
- package/dist/src/chats/previous-import.js +34 -0
- package/dist/src/chats/reader.d.ts +7 -1
- package/dist/src/chats/reader.js +46 -15
- package/dist/src/chats/redact-import.d.ts +14 -0
- package/dist/src/chats/redact-import.js +141 -0
- package/dist/src/chats/redaction.d.ts +41 -0
- package/dist/src/chats/redaction.js +161 -0
- package/dist/src/chats/reference-mapping.d.ts +16 -0
- package/dist/src/chats/reference-mapping.js +153 -0
- package/dist/src/chats/revision-input.d.ts +3 -0
- package/dist/src/chats/revision-input.js +180 -0
- package/dist/src/chats/revision.d.ts +48 -0
- package/dist/src/chats/revision.js +94 -0
- package/dist/src/chats/selection.d.ts +25 -0
- package/dist/src/chats/selection.js +109 -0
- package/dist/src/chats/source.d.ts +23 -0
- package/dist/src/chats/source.js +135 -0
- package/dist/src/chats/structure.d.ts +57 -0
- package/dist/src/chats/structure.js +216 -0
- package/dist/src/chats/workflow-generation-projection.d.ts +8 -0
- package/dist/src/chats/workflow-generation-projection.js +75 -0
- package/dist/src/chats/workflow-generation-source.d.ts +25 -0
- package/dist/src/chats/workflow-generation-source.js +124 -0
- package/dist/src/chats/workflow-generation-text.d.ts +23 -0
- package/dist/src/chats/workflow-generation-text.js +74 -0
- package/dist/src/chats/workflow-generation.d.ts +69 -0
- package/dist/src/chats/workflow-generation.js +142 -0
- package/dist/src/cli/arguments.d.ts +8 -0
- package/dist/src/cli/arguments.js +94 -13
- package/dist/src/cli/client.d.ts +1 -0
- package/dist/src/cli/client.js +38 -1
- package/dist/src/cli/commands.d.ts +3 -0
- package/dist/src/cli/commands.js +29 -11
- package/dist/src/cli/main.d.ts +2 -1
- package/dist/src/cli/main.js +61 -14
- package/dist/src/cli/render.d.ts +3 -0
- package/dist/src/cli/render.js +122 -7
- package/dist/src/cli/usage-render.d.ts +3 -0
- package/dist/src/cli/usage-render.js +28 -0
- package/dist/src/cli/usage.d.ts +3 -2
- package/dist/src/cli/usage.js +42 -7
- package/dist/src/cli/watch-actions.d.ts +10 -0
- package/dist/src/cli/watch-actions.js +58 -0
- package/dist/src/cli/watch-board-view.d.ts +44 -1
- package/dist/src/cli/watch-board-view.js +137 -18
- package/dist/src/cli/watch-board.d.ts +7 -1
- package/dist/src/cli/watch-board.js +48 -11
- package/dist/src/cli/watch-card-client.d.ts +1 -0
- package/dist/src/cli/watch-card-client.js +44 -0
- package/dist/src/cli/watch-card-forms.d.ts +2 -0
- package/dist/src/cli/watch-card-forms.js +33 -0
- package/dist/src/cli/watch-card-reply.d.ts +5 -0
- package/dist/src/cli/watch-card-reply.js +34 -0
- package/dist/src/cli/watch-card-view.d.ts +40 -0
- package/dist/src/cli/watch-card-view.js +86 -0
- package/dist/src/cli/watch-client.d.ts +1 -0
- package/dist/src/cli/watch-client.js +122 -0
- package/dist/src/cli/watch-model.d.ts +10 -4
- package/dist/src/cli/watch-model.js +61 -67
- package/dist/src/cli/watch-page.d.ts +1 -1
- package/dist/src/cli/watch-page.js +89 -86
- package/dist/src/cli/watch-phases.js +3 -3
- package/dist/src/cli/watch-pr-board.d.ts +3 -0
- package/dist/src/cli/watch-pr-board.js +26 -0
- package/dist/src/cli/watch-pr-command.d.ts +18 -0
- package/dist/src/cli/watch-pr-command.js +74 -0
- package/dist/src/cli/watch-pr-identity.d.ts +32 -0
- package/dist/src/cli/watch-pr-identity.js +87 -0
- package/dist/src/cli/watch-pr-observer.d.ts +20 -0
- package/dist/src/cli/watch-pr-observer.js +150 -0
- package/dist/src/cli/watch-pr-settings.d.ts +8 -0
- package/dist/src/cli/watch-pr-settings.js +47 -0
- package/dist/src/cli/watch-pull-request.d.ts +10 -0
- package/dist/src/cli/watch-pull-request.js +130 -0
- package/dist/src/cli/watch-reads.d.ts +7 -1
- package/dist/src/cli/watch-reads.js +44 -18
- package/dist/src/cli/watch-render.d.ts +29 -2
- package/dist/src/cli/watch-render.js +11 -3
- package/dist/src/cli/watch-run-input.d.ts +14 -0
- package/dist/src/cli/watch-run-input.js +49 -0
- package/dist/src/cli/watch-server.d.ts +3 -0
- package/dist/src/cli/watch-server.js +77 -8
- package/dist/src/cli/watch-start-view.d.ts +18 -0
- package/dist/src/cli/watch-start-view.js +77 -0
- package/dist/src/cli/watch-turn.d.ts +1 -0
- package/dist/src/cli/watch-turn.js +8 -3
- package/dist/src/cli/watch-usage.d.ts +6 -0
- package/dist/src/cli/watch-usage.js +65 -0
- package/dist/src/cli/watch-view.d.ts +22 -0
- package/dist/src/cli/watch-view.js +111 -19
- package/dist/src/cli.js +48 -6
- package/dist/src/daemon/analysis-launch.d.ts +5 -0
- package/dist/src/daemon/analysis-launch.js +81 -0
- package/dist/src/daemon/analysis-token.d.ts +6 -0
- package/dist/src/daemon/analysis-token.js +88 -0
- package/dist/src/daemon/analysis-worker.d.ts +20 -0
- package/dist/src/daemon/analysis-worker.js +271 -0
- package/dist/src/daemon/chats-batch-binding.d.ts +23 -0
- package/dist/src/daemon/chats-batch-binding.js +99 -0
- package/dist/src/daemon/chats-capture.d.ts +18 -0
- package/dist/src/daemon/chats-capture.js +194 -0
- package/dist/src/daemon/chats-checkpoints.d.ts +41 -0
- package/dist/src/daemon/chats-checkpoints.js +186 -0
- package/dist/src/daemon/chats-files.d.ts +42 -0
- package/dist/src/daemon/chats-files.js +252 -0
- package/dist/src/daemon/chats-follow-up.d.ts +38 -0
- package/dist/src/daemon/chats-follow-up.js +180 -0
- package/dist/src/daemon/chats-question.d.ts +15 -0
- package/dist/src/daemon/chats-question.js +93 -0
- package/dist/src/daemon/chats-worker.d.ts +13 -0
- package/dist/src/daemon/chats-worker.js +201 -0
- package/dist/src/daemon/claude-turn.d.ts +11 -0
- package/dist/src/daemon/claude-turn.js +96 -15
- package/dist/src/daemon/claude-worker.d.ts +2 -1
- package/dist/src/daemon/claude-worker.js +92 -45
- package/dist/src/daemon/codex-stream.js +16 -0
- package/dist/src/daemon/daemon.d.ts +8 -1
- package/dist/src/daemon/daemon.js +51 -14
- package/dist/src/daemon/delivery-router.js +6 -0
- package/dist/src/daemon/github-calls.d.ts +4 -0
- package/dist/src/daemon/github-calls.js +16 -7
- package/dist/src/daemon/github-ci.d.ts +6 -0
- package/dist/src/daemon/github-ci.js +170 -0
- package/dist/src/daemon/github-merge-call.d.ts +14 -0
- package/dist/src/daemon/github-merge-call.js +73 -0
- package/dist/src/daemon/github-merge.d.ts +3 -5
- package/dist/src/daemon/github-merge.js +52 -95
- package/dist/src/daemon/github-methods.d.ts +28 -0
- package/dist/src/daemon/github-methods.js +84 -16
- package/dist/src/daemon/github-operation.d.ts +2 -0
- package/dist/src/daemon/github-retry.d.ts +6 -0
- package/dist/src/daemon/github-retry.js +49 -0
- package/dist/src/daemon/github-ticket-status.d.ts +3 -0
- package/dist/src/daemon/github-ticket-status.js +294 -0
- package/dist/src/daemon/github-worker.js +2 -1
- package/dist/src/daemon/handoff-worker.d.ts +10 -0
- package/dist/src/daemon/handoff-worker.js +232 -0
- package/dist/src/daemon/issue-queue.d.ts +2 -0
- package/dist/src/daemon/issue-queue.js +186 -43
- package/dist/src/daemon/notify-journal.d.ts +18 -0
- package/dist/src/daemon/notify-journal.js +108 -0
- package/dist/src/daemon/notify-message.js +2 -1
- package/dist/src/daemon/notify.js +176 -37
- package/dist/src/daemon/operation-journal.d.ts +1 -0
- package/dist/src/daemon/operation-journal.js +4 -2
- package/dist/src/daemon/retrying-turn.d.ts +12 -0
- package/dist/src/daemon/retrying-turn.js +231 -0
- package/dist/src/daemon/ticket-dependency-waits.d.ts +18 -0
- package/dist/src/daemon/ticket-dependency-waits.js +60 -0
- package/dist/src/daemon/ticket-registration.d.ts +8 -4
- package/dist/src/daemon/ticket-registration.js +76 -22
- package/dist/src/daemon/ticket-source.d.ts +4 -1
- package/dist/src/daemon/ticket-source.js +8 -2
- package/dist/src/decision-visibility.d.ts +2 -0
- package/dist/src/decision-visibility.js +10 -0
- package/dist/src/execution-pin.d.ts +4 -0
- package/dist/src/execution-pin.js +23 -2
- package/dist/src/host/start-delivery.d.ts +2 -1
- package/dist/src/host/start-delivery.js +1 -1
- package/dist/src/host/step-bridge-host.d.ts +1 -0
- package/dist/src/host/step-bridge-host.js +16 -0
- package/dist/src/host/world-reconciliation.d.ts +3 -0
- package/dist/src/host/world-reconciliation.js +9 -0
- package/dist/src/host/world-runs.js +14 -1
- package/dist/src/issue-identity.d.ts +6 -0
- package/dist/src/issue-identity.js +23 -0
- package/dist/src/service/queue-runs.d.ts +3 -0
- package/dist/src/service/queue-runs.js +39 -0
- package/dist/src/service/registry.d.ts +8 -2
- package/dist/src/service/registry.js +20 -8
- package/dist/src/service/replies.d.ts +2 -0
- package/dist/src/service/run-handlers.js +54 -30
- package/dist/src/service/service.d.ts +3 -0
- package/dist/src/service/service.js +3 -1
- package/dist/src/service/submission-handler.d.ts +1 -0
- package/dist/src/service/submission-handler.js +92 -13
- package/dist/src/service/worker-totals.d.ts +3 -0
- package/dist/src/service/worker-totals.js +52 -0
- package/dist/src/step-bridge.d.ts +9 -0
- package/dist/src/steps/handoff.d.ts +2 -0
- package/dist/src/steps/handoff.js +13 -0
- package/dist/src/ticket-dependencies.d.ts +1 -0
- package/dist/src/ticket-dependencies.js +15 -0
- package/dist/src/ticket-status.d.ts +8 -0
- package/dist/src/ticket-status.js +48 -0
- package/dist/src/token-prices.d.ts +21 -0
- package/dist/src/token-prices.js +108 -0
- package/dist/src/worker-usage.d.ts +31 -0
- package/dist/src/worker-usage.js +44 -0
- package/dist/src/workflow-admission.d.ts +1 -0
- package/dist/src/workflow-candidate.d.ts +29 -0
- package/dist/src/workflow-candidate.js +60 -0
- package/dist/src/workflow-contracts.d.ts +4 -0
- package/dist/src/workflow-contracts.js +32 -5
- package/dist/src/workflow-declaration.d.ts +12 -1
- package/dist/src/workflow-declaration.js +71 -13
- package/dist/src/workflow-discovery.d.ts +18 -0
- package/dist/src/workflow-discovery.js +33 -0
- package/dist/src/workflow-refusals.d.ts +6 -0
- package/dist/src/workflow-refusals.js +39 -0
- package/dist/src/workflows.d.ts +3 -1
- package/dist/src/workflows.js +2 -0
- package/dist/tools/admit-workflow.d.ts +13 -0
- package/dist/tools/admit-workflow.js +94 -0
- package/dist/tools/self-host-processes.js +7 -2
- package/dist/tools/self-host-project.d.ts +17 -0
- package/dist/tools/self-host-project.js +177 -0
- package/dist/tools/self-host-workflows.d.ts +1 -1
- package/dist/tools/self-host-workflows.js +2 -2
- package/dist/tools/self-host.js +30 -84
- package/dist/tools/self-update-host.d.ts +7 -0
- package/dist/tools/self-update-host.js +48 -1
- package/dist/tools/self-update.d.ts +1 -0
- package/dist/tools/self-update.js +85 -13
- package/dist/tools/workflow-bundle-dependencies.d.ts +5 -0
- package/dist/tools/workflow-bundle-dependencies.js +93 -0
- package/dist/tools/workflow-bundles.d.ts +20 -0
- package/dist/tools/workflow-bundles.js +173 -0
- package/dist/tools/workflow-candidate-counts.d.ts +8 -0
- package/dist/tools/workflow-candidate-counts.js +251 -0
- package/dist/tools/workflow-candidate-program.d.ts +11 -0
- package/dist/tools/workflow-candidate-program.js +78 -0
- package/dist/tools/workflow-candidate-source.d.ts +6 -0
- package/dist/tools/workflow-candidate-source.js +107 -0
- package/dist/tools/workflow-candidate-syntax.d.ts +15 -0
- package/dist/tools/workflow-candidate-syntax.js +219 -0
- package/dist/tools/workflow-folder-capture.d.ts +17 -0
- package/dist/tools/workflow-folder-capture.js +216 -0
- package/dist/tools/workflow-folders.d.ts +33 -0
- package/dist/tools/workflow-folders.js +150 -0
- package/dist/tools/workflow-source-effects.d.ts +10 -0
- package/dist/tools/workflow-source-effects.js +213 -0
- package/dist/workflows/analyze-chats.d.ts +15 -0
- package/dist/workflows/analyze-chats.declaration.json +22 -0
- package/dist/workflows/analyze-chats.js +250 -0
- package/dist/workflows/develop-prd.js +71 -3
- package/dist/workflows/develop-ticket.d.ts +1 -7
- package/dist/workflows/develop-ticket.js +47 -141
- package/dist/workflows/issue-labels.d.ts +3 -1
- package/dist/workflows/issue-labels.js +34 -0
- package/dist/workflows/ticket-prompts.d.ts +35 -0
- package/dist/workflows/ticket-prompts.js +143 -0
- package/package.json +25 -5
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { protectedEffect } from "cloving/workflows/steps/protected-effect";
|
|
2
|
+
import { handoff } from "cloving/workflows/steps/handoff";
|
|
2
3
|
const draft = "cloving-prd-draft.md";
|
|
3
4
|
const noCommit = "Do not commit and do not push. Work only in this work tree.";
|
|
4
5
|
function issueNumber(result) {
|
|
@@ -67,9 +68,76 @@ function requests(input) {
|
|
|
67
68
|
units: 1,
|
|
68
69
|
}));
|
|
69
70
|
}
|
|
71
|
+
function readyIssue(input, issueResult) {
|
|
72
|
+
const { number, result } = issueResult;
|
|
73
|
+
const created = JSON.parse(result ?? "null");
|
|
74
|
+
const url = typeof created === "object" && created !== null && "url" in created
|
|
75
|
+
? created.url
|
|
76
|
+
: undefined;
|
|
77
|
+
const issue = typeof url === "string"
|
|
78
|
+
? /^https?:\/\/[^/\s]+\/([\w.-]+)\/([\w.-]+)\/issues\/([1-9]\d*)$/.exec(url)
|
|
79
|
+
: null;
|
|
80
|
+
if (issue === null || Number(issue[3]) !== number)
|
|
81
|
+
throw new Error("invalid-issue-result");
|
|
82
|
+
return {
|
|
83
|
+
scope: { phase: "prd", operation: "github-ready", round: 1 },
|
|
84
|
+
capability: "github",
|
|
85
|
+
method: "label",
|
|
86
|
+
target: input.cycleId,
|
|
87
|
+
units: 1,
|
|
88
|
+
payload: JSON.stringify({
|
|
89
|
+
owner: issue[1],
|
|
90
|
+
repository: issue[2],
|
|
91
|
+
number,
|
|
92
|
+
add: ["cloving: ready"],
|
|
93
|
+
remove: [],
|
|
94
|
+
}),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
async function handoffIssue(input, created) {
|
|
98
|
+
const { number } = created;
|
|
99
|
+
const outcome = {
|
|
100
|
+
kind: "handoff_requested",
|
|
101
|
+
cycleId: input.cycleId,
|
|
102
|
+
promotionId: `issue-${String(number)}`,
|
|
103
|
+
};
|
|
104
|
+
try {
|
|
105
|
+
await handoff({
|
|
106
|
+
workflowId: "develop-issue",
|
|
107
|
+
input: { ticket: String(number) },
|
|
108
|
+
});
|
|
109
|
+
return outcome;
|
|
110
|
+
}
|
|
111
|
+
catch (error) {
|
|
112
|
+
const reason = handoffReason(error);
|
|
113
|
+
const queued = await protectedEffect(readyIssue(input, created));
|
|
114
|
+
return {
|
|
115
|
+
...outcome,
|
|
116
|
+
reason,
|
|
117
|
+
...(queued.kind === "completed" ? {} : { issueUpdate: "failed" }),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function handoffReason(error) {
|
|
122
|
+
const cause = typeof error === "object" && error !== null && "cause" in error
|
|
123
|
+
? error.cause
|
|
124
|
+
: error;
|
|
125
|
+
if (typeof cause !== "object" ||
|
|
126
|
+
cause === null ||
|
|
127
|
+
!("message" in cause) ||
|
|
128
|
+
typeof cause.message !== "string")
|
|
129
|
+
return "handoff-failed";
|
|
130
|
+
return /^[a-z][a-z0-9-]{0,127}$/.test(cause.message)
|
|
131
|
+
? cause.message
|
|
132
|
+
: "handoff-failed";
|
|
133
|
+
}
|
|
70
134
|
export async function developPrd(input) {
|
|
71
135
|
"use workflow";
|
|
72
|
-
let
|
|
136
|
+
let outcome = {
|
|
137
|
+
kind: "handoff_requested",
|
|
138
|
+
cycleId: input.cycleId,
|
|
139
|
+
promotionId: "",
|
|
140
|
+
};
|
|
73
141
|
for (const request of requests(input)) {
|
|
74
142
|
const result = await protectedEffect(request);
|
|
75
143
|
if (result.kind !== "completed")
|
|
@@ -91,7 +159,7 @@ export async function developPrd(input) {
|
|
|
91
159
|
reason: "invalid-issue-result",
|
|
92
160
|
evidenceId: request.scope.operation,
|
|
93
161
|
};
|
|
94
|
-
|
|
162
|
+
outcome = await handoffIssue(input, { number, result: result.result });
|
|
95
163
|
}
|
|
96
|
-
return
|
|
164
|
+
return outcome;
|
|
97
165
|
}
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import type { CycleOutcome } from "cloving/workflows";
|
|
2
|
-
|
|
3
|
-
readonly cycleId: string;
|
|
4
|
-
readonly ticket: string;
|
|
5
|
-
readonly ticketId?: string;
|
|
6
|
-
readonly repository: string;
|
|
7
|
-
readonly delivery?: string;
|
|
8
|
-
}
|
|
2
|
+
import { type Ticket } from "./ticket-prompts.ts";
|
|
9
3
|
interface Decision {
|
|
10
4
|
readonly gateId: string;
|
|
11
5
|
readonly decision: string;
|
|
@@ -1,77 +1,11 @@
|
|
|
1
1
|
import { decisionGate } from "cloving/workflows/steps/decision-gate";
|
|
2
2
|
import { protectedEffect } from "cloving/workflows/steps/protected-effect";
|
|
3
3
|
import { finishIssue, labelIssue } from "./issue-labels.js";
|
|
4
|
-
|
|
4
|
+
import { fields, part, lastRound, review, prompt, turnPrompt, pullTitle, pullBody, } from "./ticket-prompts.js";
|
|
5
5
|
const lastFix = 3;
|
|
6
|
-
const publicRule = "The branch becomes a public pull request. Do not write local file paths, such as the path of your home folder, in files or in commit messages.";
|
|
7
|
-
function instructions(repository) {
|
|
8
|
-
return [
|
|
9
|
-
"You work on one ticket of this repository. Your current directory is a git work tree on its own branch.",
|
|
10
|
-
`The main repository is at ${repository}. Do not change files there.`,
|
|
11
|
-
`If this work tree has no node_modules folder and the main repository has one, make a copy-on-write clone: cp -c -R ${repository}/node_modules node_modules`,
|
|
12
|
-
"Follow the instructions of the repository (AGENTS.md and CLAUDE.md).",
|
|
13
|
-
"Use test-driven development: write a test that fails, see it fail, then write the code.",
|
|
14
|
-
"Run the checks of the repository before you finish.",
|
|
15
|
-
"Commit your work on the current branch. Do not push. Do not change a different branch.",
|
|
16
|
-
"End with a short report: what you changed, the checks that you ran with their results, and what is not done.",
|
|
17
|
-
].join("\n");
|
|
18
|
-
}
|
|
19
|
-
function named(input) {
|
|
20
|
-
return input.ticketId === undefined
|
|
21
|
-
? "this ticket"
|
|
22
|
-
: `the ticket ${input.ticketId}`;
|
|
23
|
-
}
|
|
24
|
-
function fields(text) {
|
|
25
|
-
const value = JSON.parse(text ?? "{}");
|
|
26
|
-
return typeof value === "object" && value !== null ? { ...value } : {};
|
|
27
|
-
}
|
|
28
|
-
function part(turn, name) {
|
|
29
|
-
const value = turn[name];
|
|
30
|
-
if (Array.isArray(value))
|
|
31
|
-
return value.join("\n");
|
|
32
|
-
if (typeof value === "number")
|
|
33
|
-
return value.toFixed(2);
|
|
34
|
-
return typeof value === "string" ? value : "";
|
|
35
|
-
}
|
|
36
|
-
function denial(round) {
|
|
37
|
-
return round < lastRound
|
|
38
|
-
? "Deny with a feedback text to send the work back to the worker for one more round. Deny with no text to reject the work."
|
|
39
|
-
: "Deny to reject the work. This is the last round.";
|
|
40
|
-
}
|
|
41
|
-
function review(input, turnResult) {
|
|
42
|
-
const turn = fields(turnResult.result);
|
|
43
|
-
return [
|
|
44
|
-
`Review the work of the Claude worker for ${named(input)}.`,
|
|
45
|
-
`Round: ${String(turnResult.round)} of ${String(lastRound)}`,
|
|
46
|
-
`Branch: ${part(turn, "branch")}`,
|
|
47
|
-
`Work tree: ${part(turn, "worktree")}`,
|
|
48
|
-
`Cost (USD): ${part(turn, "costUsd")}`,
|
|
49
|
-
"",
|
|
50
|
-
"Commits:",
|
|
51
|
-
part(turn, "commits"),
|
|
52
|
-
"",
|
|
53
|
-
"Changed files:",
|
|
54
|
-
part(turn, "files"),
|
|
55
|
-
"",
|
|
56
|
-
"Not committed:",
|
|
57
|
-
part(turn, "uncommitted"),
|
|
58
|
-
"",
|
|
59
|
-
"Report of the worker:",
|
|
60
|
-
part(turn, "summary"),
|
|
61
|
-
"",
|
|
62
|
-
"Approve to accept the branch, then merge the branch yourself.",
|
|
63
|
-
denial(turnResult.round),
|
|
64
|
-
].join("\n");
|
|
65
|
-
}
|
|
66
6
|
function blocked(cycleId, cause) {
|
|
67
7
|
return { kind: "blocked", cycleId, ...cause };
|
|
68
8
|
}
|
|
69
|
-
function prompt(input, round) {
|
|
70
|
-
const ticket = `${instructions(input.repository)}\n\nThe text of ${named(input)}:\n\n${input.ticket}`;
|
|
71
|
-
if (round.feedback === null)
|
|
72
|
-
return ticket;
|
|
73
|
-
return `${ticket}\n\nThis is round ${String(round.number)}. The branch has the commits of the earlier rounds. The operator denied the work of round ${String(round.number - 1)} with this feedback:\n\n${round.feedback}`;
|
|
74
|
-
}
|
|
75
9
|
function decided(cycleId, decision) {
|
|
76
10
|
const number = Number(decision.gateId.slice("review-".length));
|
|
77
11
|
if (decision.decision === "approved")
|
|
@@ -92,61 +26,6 @@ function decided(cycleId, decision) {
|
|
|
92
26
|
});
|
|
93
27
|
return { number: number + 1, feedback: decision.answer };
|
|
94
28
|
}
|
|
95
|
-
function pullPrompt(input) {
|
|
96
|
-
return `${instructions(input.repository)}\n${publicRule}\n\nThe text of ${named(input)}:\n\n${input.ticket}`;
|
|
97
|
-
}
|
|
98
|
-
function findingLines(findings) {
|
|
99
|
-
if (!Array.isArray(findings))
|
|
100
|
-
return "";
|
|
101
|
-
return findings
|
|
102
|
-
.map((item) => {
|
|
103
|
-
const finding = fields(JSON.stringify(item));
|
|
104
|
-
const line = finding["line"];
|
|
105
|
-
const place = typeof line === "number" ? `:${String(line)}` : "";
|
|
106
|
-
return `- ${part(finding, "path")}${place}: ${part(finding, "body")}`;
|
|
107
|
-
})
|
|
108
|
-
.join("\n");
|
|
109
|
-
}
|
|
110
|
-
function turnPrompt(input, fix) {
|
|
111
|
-
if (fix === null)
|
|
112
|
-
return pullPrompt(input);
|
|
113
|
-
const { round, pull, review } = fix;
|
|
114
|
-
if (typeof review["reason"] === "string")
|
|
115
|
-
return [
|
|
116
|
-
pullPrompt(input),
|
|
117
|
-
"",
|
|
118
|
-
`This is round ${String(round)}. The merge of the pull request ${pull.url} needs a fix: ${review["reason"]}.`,
|
|
119
|
-
review["reason"] === "merge-conflict"
|
|
120
|
-
? "Merge the default branch of origin into the branch, resolve each conflict, run the tests, and commit."
|
|
121
|
-
: "The check failed on the tree of the merge of the branch with the newest commit of the default branch. Fix the cause and commit the fix.",
|
|
122
|
-
"",
|
|
123
|
-
part(review, "output"),
|
|
124
|
-
].join("\n");
|
|
125
|
-
return [
|
|
126
|
-
pullPrompt(input),
|
|
127
|
-
"",
|
|
128
|
-
`This is round ${String(round)}. The branch has the commits of the earlier rounds. Greptile reviewed the pull request ${pull.url} at the commit ${pull.commit.slice(0, 7)} and gave the confidence score ${String(review["score"])}/5. Fix each problem of the review, then commit the fixes. Cloving merges the pull request when the score is 5/5.`,
|
|
129
|
-
"",
|
|
130
|
-
"Summary of the review:",
|
|
131
|
-
"",
|
|
132
|
-
part(review, "summary"),
|
|
133
|
-
"",
|
|
134
|
-
"Findings on lines:",
|
|
135
|
-
"",
|
|
136
|
-
findingLines(review["findings"]),
|
|
137
|
-
].join("\n");
|
|
138
|
-
}
|
|
139
|
-
function pullTitle(input) {
|
|
140
|
-
const [first = ""] = input.ticket.split("\n", 1);
|
|
141
|
-
return first.startsWith("# ")
|
|
142
|
-
? first.slice(2).trim().slice(0, 200)
|
|
143
|
-
: `Cloving task ${input.cycleId}`;
|
|
144
|
-
}
|
|
145
|
-
function pullBody(input) {
|
|
146
|
-
const issue = /^GitHub issue: ([\w.-]+[/][\w.-]+#\d+)/m.exec(input.ticket);
|
|
147
|
-
const about = `Cloving made this change for ${named(input)}. Greptile reviews the pull request, and Cloving merges it when the confidence score is 5/5.`;
|
|
148
|
-
return issue === null ? about : `Closes ${String(issue[1])}\n\n${about}`;
|
|
149
|
-
}
|
|
150
29
|
async function stepped(input, call) {
|
|
151
30
|
const { phase, operation, round, capability, method, payload } = call;
|
|
152
31
|
const done = await protectedEffect({
|
|
@@ -197,12 +76,40 @@ async function merged(input, done) {
|
|
|
197
76
|
cycleId: input.cycleId,
|
|
198
77
|
promotionId: `pull-request-${String(number)}`,
|
|
199
78
|
};
|
|
79
|
+
if (merge.result["reason"] === "ci-pending")
|
|
80
|
+
return blocked(input.cycleId, {
|
|
81
|
+
reason: `The merge has the result ci-pending: ${part(merge.result, "output")}. The pull request stays open: ${done.pull.url}`,
|
|
82
|
+
evidenceId: "github-merge",
|
|
83
|
+
});
|
|
200
84
|
if (done.round > lastFix)
|
|
201
85
|
return blocked(input.cycleId, {
|
|
202
86
|
reason: `The merge has the result ${merge.result["reason"]} in round ${String(done.round)}, and a run has at most ${String(lastFix)} fix rounds. The pull request stays open: ${done.pull.url}`,
|
|
203
87
|
evidenceId: "github-merge",
|
|
204
88
|
});
|
|
205
|
-
return {
|
|
89
|
+
return {
|
|
90
|
+
round: done.round + 1,
|
|
91
|
+
pull: done.pull,
|
|
92
|
+
review: merge.result,
|
|
93
|
+
report: done.report,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async function reviewedPull(input, round) {
|
|
97
|
+
const opened = await github(input, {
|
|
98
|
+
method: "open-pr",
|
|
99
|
+
round,
|
|
100
|
+
payload: { title: pullTitle(input), body: pullBody(input) },
|
|
101
|
+
});
|
|
102
|
+
if (opened.kind !== "done")
|
|
103
|
+
return opened;
|
|
104
|
+
const pull = pullOf(opened.result);
|
|
105
|
+
const reviewed = await github(input, {
|
|
106
|
+
method: "wait-review",
|
|
107
|
+
round,
|
|
108
|
+
payload: { number: pull.number, commit: pull.commit },
|
|
109
|
+
});
|
|
110
|
+
return reviewed.kind === "done"
|
|
111
|
+
? { kind: "reviewed", pull, review: reviewed.result }
|
|
112
|
+
: reviewed;
|
|
206
113
|
}
|
|
207
114
|
async function pullRequest(input) {
|
|
208
115
|
const prepared = await github(input, {
|
|
@@ -225,26 +132,20 @@ async function pullRequest(input) {
|
|
|
225
132
|
});
|
|
226
133
|
if (turn.kind !== "done")
|
|
227
134
|
return finishIssue(input, { round, outcome: turn });
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
round,
|
|
231
|
-
payload: { title: pullTitle(input), body: pullBody(input) },
|
|
232
|
-
});
|
|
233
|
-
if (opened.kind !== "done")
|
|
234
|
-
return finishIssue(input, { round, outcome: opened });
|
|
235
|
-
const pull = pullOf(opened.result);
|
|
236
|
-
const reviewed = await github(input, {
|
|
237
|
-
method: "wait-review",
|
|
238
|
-
round,
|
|
239
|
-
payload: { number: pull.number, commit: pull.commit },
|
|
240
|
-
});
|
|
241
|
-
if (reviewed.kind !== "done")
|
|
135
|
+
const reviewed = await reviewedPull(input, round);
|
|
136
|
+
if (reviewed.kind !== "reviewed")
|
|
242
137
|
return finishIssue(input, { round, outcome: reviewed });
|
|
243
|
-
const
|
|
138
|
+
const { pull } = reviewed;
|
|
139
|
+
const score = reviewed.review["score"];
|
|
244
140
|
if (score === 5) {
|
|
245
|
-
const result = await merged(input, { round, pull });
|
|
141
|
+
const result = await merged(input, { round, pull, report: turn.result });
|
|
246
142
|
if ("kind" in result)
|
|
247
|
-
return finishIssue(input, {
|
|
143
|
+
return finishIssue(input, {
|
|
144
|
+
round,
|
|
145
|
+
outcome: result,
|
|
146
|
+
summary: part(turn.result, "summary"),
|
|
147
|
+
status: turn.result["ticketStatus"],
|
|
148
|
+
});
|
|
248
149
|
fix = result;
|
|
249
150
|
continue;
|
|
250
151
|
}
|
|
@@ -256,7 +157,12 @@ async function pullRequest(input) {
|
|
|
256
157
|
evidenceId: "github-wait-review",
|
|
257
158
|
}),
|
|
258
159
|
});
|
|
259
|
-
fix = {
|
|
160
|
+
fix = {
|
|
161
|
+
round: round + 1,
|
|
162
|
+
pull,
|
|
163
|
+
review: reviewed.review,
|
|
164
|
+
report: turn.result,
|
|
165
|
+
};
|
|
260
166
|
}
|
|
261
167
|
}
|
|
262
168
|
export async function developTicket(input, decision) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type CycleOutcome } from "cloving/workflows";
|
|
2
2
|
interface IssueTicket {
|
|
3
3
|
readonly cycleId: string;
|
|
4
4
|
readonly ticket: string;
|
|
@@ -10,5 +10,7 @@ export declare function labelIssue(input: IssueTicket, state: {
|
|
|
10
10
|
export declare function finishIssue(input: IssueTicket, ending: {
|
|
11
11
|
readonly round: number;
|
|
12
12
|
readonly outcome: CycleOutcome;
|
|
13
|
+
readonly summary?: string;
|
|
14
|
+
readonly status?: unknown;
|
|
13
15
|
}): Promise<CycleOutcome>;
|
|
14
16
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ticketStatus } from "cloving/workflows";
|
|
1
2
|
import { protectedEffect } from "cloving/workflows/steps/protected-effect";
|
|
2
3
|
export async function labelIssue(input, state) {
|
|
3
4
|
const issue = /^GitHub issue: ([\w.-]+)\/([\w.-]+)#(\d+)/m.exec(input.ticket);
|
|
@@ -28,9 +29,42 @@ export async function labelIssue(input, state) {
|
|
|
28
29
|
});
|
|
29
30
|
}
|
|
30
31
|
export async function finishIssue(input, ending) {
|
|
32
|
+
if (ending.outcome.kind === "handoff_requested")
|
|
33
|
+
return finishMergedIssue(input, ending);
|
|
31
34
|
await labelIssue(input, {
|
|
32
35
|
round: ending.round,
|
|
33
36
|
key: ending.outcome.kind === "blocked" ? "blocked" : "done",
|
|
34
37
|
});
|
|
35
38
|
return ending.outcome;
|
|
36
39
|
}
|
|
40
|
+
async function finishMergedIssue(input, ending) {
|
|
41
|
+
if (ending.outcome.kind !== "handoff_requested")
|
|
42
|
+
return ending.outcome;
|
|
43
|
+
const status = ticketStatus(ending.summary ?? "", ending.status);
|
|
44
|
+
const method = status.kind === "complete" ? "close-issue" : "partial-issue";
|
|
45
|
+
const issue = /^GitHub issue: ([\w.-]+)\/([\w.-]+)#(\d+)/m.exec(input.ticket);
|
|
46
|
+
const outcome = { ...ending.outcome, ticketStatus: status.kind };
|
|
47
|
+
if (issue === null)
|
|
48
|
+
return outcome;
|
|
49
|
+
const update = await protectedEffect({
|
|
50
|
+
scope: {
|
|
51
|
+
phase: "pull-request",
|
|
52
|
+
operation: `github-${method}`,
|
|
53
|
+
round: ending.round,
|
|
54
|
+
},
|
|
55
|
+
capability: "github",
|
|
56
|
+
method,
|
|
57
|
+
target: input.cycleId,
|
|
58
|
+
units: 1,
|
|
59
|
+
payload: JSON.stringify({
|
|
60
|
+
owner: issue[1],
|
|
61
|
+
repository: issue[2],
|
|
62
|
+
number: Number(issue[3]),
|
|
63
|
+
pullRequest: Number(ending.outcome.promotionId.slice("pull-request-".length)),
|
|
64
|
+
...(status.kind === "partial" ? { remaining: status.remaining } : {}),
|
|
65
|
+
}),
|
|
66
|
+
});
|
|
67
|
+
if (update.kind === "completed")
|
|
68
|
+
return outcome;
|
|
69
|
+
return { ...outcome, issueUpdate: "failed" };
|
|
70
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface Ticket {
|
|
2
|
+
readonly cycleId: string;
|
|
3
|
+
readonly ticket: string;
|
|
4
|
+
readonly ticketId?: string;
|
|
5
|
+
readonly repository: string;
|
|
6
|
+
readonly delivery?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface Round {
|
|
9
|
+
readonly number: number;
|
|
10
|
+
readonly feedback: string | null;
|
|
11
|
+
}
|
|
12
|
+
export interface Pull {
|
|
13
|
+
readonly number: number;
|
|
14
|
+
readonly url: string;
|
|
15
|
+
readonly commit: string;
|
|
16
|
+
}
|
|
17
|
+
export interface Fix {
|
|
18
|
+
readonly round: number;
|
|
19
|
+
readonly pull: Pull;
|
|
20
|
+
readonly review: Fields;
|
|
21
|
+
readonly report: Fields;
|
|
22
|
+
}
|
|
23
|
+
export declare const lastRound = 3;
|
|
24
|
+
type Fields = Readonly<Record<string, unknown>>;
|
|
25
|
+
export declare function fields(text: string | null): Readonly<Record<string, unknown>>;
|
|
26
|
+
export declare function part(turn: Readonly<Record<string, unknown>>, name: string): string;
|
|
27
|
+
export declare function review(input: Ticket, turnResult: {
|
|
28
|
+
readonly round: number;
|
|
29
|
+
readonly result: string | null;
|
|
30
|
+
}): string;
|
|
31
|
+
export declare function prompt(input: Ticket, round: Round): string;
|
|
32
|
+
export declare function turnPrompt(input: Ticket, fix: Fix | null): string;
|
|
33
|
+
export declare function pullTitle(input: Ticket): string;
|
|
34
|
+
export declare function pullBody(input: Ticket): string;
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { ticketStatus } from "cloving/workflows";
|
|
2
|
+
export const lastRound = 3;
|
|
3
|
+
const publicRule = "The branch becomes a public pull request. Do not write local file paths, such as the path of your home folder, in files or in commit messages.";
|
|
4
|
+
function instructions(repository) {
|
|
5
|
+
return [
|
|
6
|
+
"You work on one ticket of this repository. Your current directory is a git work tree on its own branch.",
|
|
7
|
+
`The main repository is at ${repository}. Do not change files there.`,
|
|
8
|
+
`If this work tree has no node_modules folder and the main repository has one, make a copy-on-write clone: cp -c -R ${repository}/node_modules node_modules`,
|
|
9
|
+
"Follow the instructions of the repository (AGENTS.md and CLAUDE.md).",
|
|
10
|
+
"Use test-driven development: write a test that fails, see it fail, then write the code.",
|
|
11
|
+
"Run the checks of the repository before you finish. Commit your work before the report. If the repository provides npm run check:clean, run it after committing.",
|
|
12
|
+
"Treat a check time warning as work to do in the same ticket when your change made the check slower.",
|
|
13
|
+
"Commit your work on the current branch. Do not push. Do not change a different branch.",
|
|
14
|
+
"End with a short report: what you changed, the checks that you ran with their results, and what is not done. End the report with exactly one of the lines Ticket status: complete or Ticket status: partial. Before a partial status line, include Remaining: followed by a list with one item on each line, using a dash and a space before each item. Blank lines are allowed around and between list items.",
|
|
15
|
+
].join("\n");
|
|
16
|
+
}
|
|
17
|
+
function named(input) {
|
|
18
|
+
return input.ticketId === undefined
|
|
19
|
+
? "this ticket"
|
|
20
|
+
: `the ticket ${input.ticketId}`;
|
|
21
|
+
}
|
|
22
|
+
export function fields(text) {
|
|
23
|
+
const value = JSON.parse(text ?? "{}");
|
|
24
|
+
return typeof value === "object" && value !== null ? { ...value } : {};
|
|
25
|
+
}
|
|
26
|
+
export function part(turn, name) {
|
|
27
|
+
const value = turn[name];
|
|
28
|
+
if (Array.isArray(value))
|
|
29
|
+
return value.join("\n");
|
|
30
|
+
if (typeof value === "number")
|
|
31
|
+
return value.toFixed(2);
|
|
32
|
+
return typeof value === "string" ? value : "";
|
|
33
|
+
}
|
|
34
|
+
function denial(round) {
|
|
35
|
+
return round < lastRound
|
|
36
|
+
? "Deny with a feedback text to send the work back to the worker for one more round. Deny with no text to reject the work."
|
|
37
|
+
: "Deny to reject the work. This is the last round.";
|
|
38
|
+
}
|
|
39
|
+
export function review(input, turnResult) {
|
|
40
|
+
const turn = fields(turnResult.result);
|
|
41
|
+
return [
|
|
42
|
+
`Review the work of the Claude worker for ${named(input)}.`,
|
|
43
|
+
`Round: ${String(turnResult.round)} of ${String(lastRound)}`,
|
|
44
|
+
`Branch: ${part(turn, "branch")}`,
|
|
45
|
+
`Work tree: ${part(turn, "worktree")}`,
|
|
46
|
+
`Cost (USD): ${part(turn, "costUsd")}`,
|
|
47
|
+
"",
|
|
48
|
+
"Commits:",
|
|
49
|
+
part(turn, "commits"),
|
|
50
|
+
"",
|
|
51
|
+
"Changed files:",
|
|
52
|
+
part(turn, "files"),
|
|
53
|
+
"",
|
|
54
|
+
"Not committed:",
|
|
55
|
+
part(turn, "uncommitted"),
|
|
56
|
+
"",
|
|
57
|
+
"Report of the worker:",
|
|
58
|
+
part(turn, "summary"),
|
|
59
|
+
"",
|
|
60
|
+
"Approve to accept the branch, then merge the branch yourself.",
|
|
61
|
+
denial(turnResult.round),
|
|
62
|
+
].join("\n");
|
|
63
|
+
}
|
|
64
|
+
export function prompt(input, round) {
|
|
65
|
+
const ticket = `${instructions(input.repository)}\n\nThe text of ${named(input)}:\n\n${input.ticket}`;
|
|
66
|
+
if (round.feedback === null)
|
|
67
|
+
return ticket;
|
|
68
|
+
return `${ticket}\n\nThis is round ${String(round.number)}. The branch has the commits of the earlier rounds. The operator denied the work of round ${String(round.number - 1)} with this feedback:\n\n${round.feedback}`;
|
|
69
|
+
}
|
|
70
|
+
function pullPrompt(input) {
|
|
71
|
+
return `${instructions(input.repository)}\n${publicRule}\n\nThe text of ${named(input)}:\n\n${input.ticket}`;
|
|
72
|
+
}
|
|
73
|
+
function findingLines(findings) {
|
|
74
|
+
if (!Array.isArray(findings))
|
|
75
|
+
return "";
|
|
76
|
+
return findings
|
|
77
|
+
.map((item) => {
|
|
78
|
+
const finding = fields(JSON.stringify(item));
|
|
79
|
+
const line = finding["line"];
|
|
80
|
+
const place = typeof line === "number" ? `:${String(line)}` : "";
|
|
81
|
+
return `- ${part(finding, "path")}${place}: ${part(finding, "body")}`;
|
|
82
|
+
})
|
|
83
|
+
.join("\n");
|
|
84
|
+
}
|
|
85
|
+
export function turnPrompt(input, fix) {
|
|
86
|
+
if (fix === null)
|
|
87
|
+
return pullPrompt(input);
|
|
88
|
+
const { round, pull, review } = fix;
|
|
89
|
+
const status = ticketStatus(part(fix.report, "summary"), fix.report["ticketStatus"]);
|
|
90
|
+
const continuation = status.kind === "complete"
|
|
91
|
+
? ""
|
|
92
|
+
: [
|
|
93
|
+
"",
|
|
94
|
+
"Remaining work from the previous worker report:",
|
|
95
|
+
...status.remaining.map((item) => `- ${item}`),
|
|
96
|
+
"Reassess each remaining item before reporting Ticket status: complete. Keep every unfinished item in the next Remaining: list.",
|
|
97
|
+
].join("\n");
|
|
98
|
+
const ticket = pullPrompt(input) + continuation;
|
|
99
|
+
if (review["reason"] === "ci-failed")
|
|
100
|
+
return [
|
|
101
|
+
ticket,
|
|
102
|
+
"",
|
|
103
|
+
`This is round ${String(round)}. The CI checks of the pull request ${pull.url} failed.`,
|
|
104
|
+
"Fix the failed CI checks, including failures that the pull request did not cause, and commit the fix.",
|
|
105
|
+
"",
|
|
106
|
+
part(review, "output"),
|
|
107
|
+
].join("\n");
|
|
108
|
+
if (typeof review["reason"] === "string")
|
|
109
|
+
return [
|
|
110
|
+
ticket,
|
|
111
|
+
"",
|
|
112
|
+
`This is round ${String(round)}. The merge of the pull request ${pull.url} needs a fix: ${review["reason"]}.`,
|
|
113
|
+
review["reason"] === "merge-conflict"
|
|
114
|
+
? "Merge the default branch of origin into the branch, resolve each conflict, run the tests, and commit."
|
|
115
|
+
: "The check failed on the tree of the merge of the branch with the newest commit of the default branch. Fix the cause and commit the fix.",
|
|
116
|
+
"",
|
|
117
|
+
part(review, "output"),
|
|
118
|
+
].join("\n");
|
|
119
|
+
return [
|
|
120
|
+
ticket,
|
|
121
|
+
"",
|
|
122
|
+
`This is round ${String(round)}. The branch has the commits of the earlier rounds. Greptile reviewed the pull request ${pull.url} at the commit ${pull.commit.slice(0, 7)} and gave the confidence score ${String(review["score"])}/5. Fix each problem of the review, then commit the fixes. Cloving merges the pull request when the score is 5/5.`,
|
|
123
|
+
"",
|
|
124
|
+
"Summary of the review:",
|
|
125
|
+
"",
|
|
126
|
+
part(review, "summary"),
|
|
127
|
+
"",
|
|
128
|
+
"Findings on lines:",
|
|
129
|
+
"",
|
|
130
|
+
findingLines(review["findings"]),
|
|
131
|
+
].join("\n");
|
|
132
|
+
}
|
|
133
|
+
export function pullTitle(input) {
|
|
134
|
+
const [first = ""] = input.ticket.split("\n", 1);
|
|
135
|
+
return first.startsWith("# ")
|
|
136
|
+
? first.slice(2).trim().slice(0, 200)
|
|
137
|
+
: `Cloving task ${input.cycleId}`;
|
|
138
|
+
}
|
|
139
|
+
export function pullBody(input) {
|
|
140
|
+
const issue = /^GitHub issue: ([\w.-]+[/][\w.-]+#\d+)/m.exec(input.ticket);
|
|
141
|
+
const about = `Cloving made this change for ${named(input)}. Greptile reviews the pull request, and Cloving merges it when the confidence score is 5/5.`;
|
|
142
|
+
return issue === null ? about : `Refs ${String(issue[1])}\n\n${about}`;
|
|
143
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cloving",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Local durable development workflow service",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -34,28 +34,48 @@
|
|
|
34
34
|
"./workflows/steps/decision-gate": {
|
|
35
35
|
"types": "./dist/src/steps/decision-gate.d.ts",
|
|
36
36
|
"import": "./dist/src/steps/decision-gate.js"
|
|
37
|
+
},
|
|
38
|
+
"./workflows/steps/handoff": {
|
|
39
|
+
"types": "./dist/src/steps/handoff.d.ts",
|
|
40
|
+
"import": "./dist/src/steps/handoff.js"
|
|
37
41
|
}
|
|
38
42
|
},
|
|
39
43
|
"files": [
|
|
40
44
|
"dist/src",
|
|
41
45
|
"dist/tools",
|
|
42
|
-
"dist/workflows"
|
|
46
|
+
"dist/workflows",
|
|
47
|
+
"assets/watch-fonts/fira-code-latin-400-normal.woff2",
|
|
48
|
+
"assets/watch-fonts/fira-code-latin-500-normal.woff2",
|
|
49
|
+
"assets/watch-fonts/fira-code-OFL.md",
|
|
50
|
+
"assets/watch-fonts/heebo-latin-500-normal.woff2",
|
|
51
|
+
"assets/watch-fonts/heebo-latin-700-normal.woff2",
|
|
52
|
+
"assets/watch-fonts/heebo-latin-800-normal.woff2",
|
|
53
|
+
"assets/watch-fonts/heebo-OFL.md",
|
|
54
|
+
"assets/watch-fonts/space-grotesk-latin-400-normal.woff2",
|
|
55
|
+
"assets/watch-fonts/space-grotesk-latin-500-normal.woff2",
|
|
56
|
+
"assets/watch-fonts/space-grotesk-latin-600-normal.woff2",
|
|
57
|
+
"assets/watch-fonts/space-grotesk-latin-700-normal.woff2",
|
|
58
|
+
"assets/watch-fonts/space-grotesk-OFL.md",
|
|
59
|
+
"assets/watch-fonts/manifest.json"
|
|
43
60
|
],
|
|
44
61
|
"engines": {
|
|
45
62
|
"node": ">=26.9.0 <27",
|
|
46
63
|
"npm": ">=11.19.1 <12"
|
|
47
64
|
},
|
|
48
65
|
"os": [
|
|
49
|
-
"darwin"
|
|
66
|
+
"darwin",
|
|
67
|
+
"linux"
|
|
50
68
|
],
|
|
51
69
|
"cpu": [
|
|
52
|
-
"arm64"
|
|
70
|
+
"arm64",
|
|
71
|
+
"x64"
|
|
53
72
|
],
|
|
54
73
|
"scripts": {
|
|
55
74
|
"build": "tsc --project tsconfig.build.json && node tools/copy-workflow-declarations.ts workflows dist/workflows",
|
|
56
75
|
"build:workflows": "node tools/compile-workflows.ts",
|
|
57
76
|
"check:setup": "tsc --project tsconfig.json --noEmit",
|
|
58
77
|
"check:quality": "node tools/check-quality.ts",
|
|
78
|
+
"check:clean": "node tools/check-clean.ts",
|
|
59
79
|
"check:lint": "eslint src tools quality test eslint.config.mjs --max-warnings 0",
|
|
60
80
|
"check:format": "prettier --check src tools quality test eslint.config.mjs package.json tsconfig.json tsconfig.build.json",
|
|
61
81
|
"test:quality": "node --test test/quality/*.test.ts",
|
|
@@ -74,7 +94,6 @@
|
|
|
74
94
|
"istanbul-lib-coverage": "3.2.2",
|
|
75
95
|
"jscpd": "5.4.0",
|
|
76
96
|
"prettier": "3.9.9",
|
|
77
|
-
"typescript": "6.0.3",
|
|
78
97
|
"typescript-eslint": "8.71.1"
|
|
79
98
|
},
|
|
80
99
|
"overrides": {
|
|
@@ -88,6 +107,7 @@
|
|
|
88
107
|
"entities": "8.1.0",
|
|
89
108
|
"preact": "11.0.0",
|
|
90
109
|
"solid-objects": "0.17.8",
|
|
110
|
+
"typescript": "6.0.3",
|
|
91
111
|
"workflow": "5.1.0"
|
|
92
112
|
}
|
|
93
113
|
}
|