chatroom-cli 1.73.0 → 1.74.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/index.js +2612 -61
- package/dist/index.js.map +34 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2167,6 +2167,7 @@ __export(exports_stdin_heredoc, {
|
|
|
2167
2167
|
findReservedDelimiterLines: () => findReservedDelimiterLines,
|
|
2168
2168
|
HANDOFF_STDIN_DELIMITER: () => HANDOFF_STDIN_DELIMITER,
|
|
2169
2169
|
HANDOFF_MESSAGE_MARKER: () => HANDOFF_MESSAGE_MARKER,
|
|
2170
|
+
ENHANCER_STDIN_DELIMITER: () => ENHANCER_STDIN_DELIMITER,
|
|
2170
2171
|
CONTEXT_STDIN_DELIMITER: () => CONTEXT_STDIN_DELIMITER,
|
|
2171
2172
|
BACKLOG_STDIN_DELIMITER: () => BACKLOG_STDIN_DELIMITER,
|
|
2172
2173
|
AGENTIC_QUERY_STDIN_DELIMITER: () => AGENTIC_QUERY_STDIN_DELIMITER
|
|
@@ -2205,13 +2206,14 @@ function findReservedDelimiterLines(content) {
|
|
|
2205
2206
|
}
|
|
2206
2207
|
return hits;
|
|
2207
2208
|
}
|
|
2208
|
-
var HANDOFF_STDIN_DELIMITER = "CHATROOM_HANDOFF_END", CONTEXT_STDIN_DELIMITER = "CHATROOM_CONTEXT_END", BACKLOG_STDIN_DELIMITER = "CHATROOM_BACKLOG_END", AGENTIC_QUERY_STDIN_DELIMITER = "CHATROOM_AGENTIC_QUERY_END", CLASSIFY_STDIN_DELIMITER = "CHATROOM_CLASSIFY_END", HANDOFF_MESSAGE_MARKER = "---MESSAGE---", RESERVED_STDIN_HEREDOC_DELIMITERS, RESERVED_STRUCTURED_PARAM_MARKERS;
|
|
2209
|
+
var HANDOFF_STDIN_DELIMITER = "CHATROOM_HANDOFF_END", CONTEXT_STDIN_DELIMITER = "CHATROOM_CONTEXT_END", BACKLOG_STDIN_DELIMITER = "CHATROOM_BACKLOG_END", AGENTIC_QUERY_STDIN_DELIMITER = "CHATROOM_AGENTIC_QUERY_END", ENHANCER_STDIN_DELIMITER = "CHATROOM_ENHANCER_END", CLASSIFY_STDIN_DELIMITER = "CHATROOM_CLASSIFY_END", HANDOFF_MESSAGE_MARKER = "---MESSAGE---", RESERVED_STDIN_HEREDOC_DELIMITERS, RESERVED_STRUCTURED_PARAM_MARKERS;
|
|
2209
2210
|
var init_stdin_heredoc = __esm(() => {
|
|
2210
2211
|
RESERVED_STDIN_HEREDOC_DELIMITERS = [
|
|
2211
2212
|
HANDOFF_STDIN_DELIMITER,
|
|
2212
2213
|
CONTEXT_STDIN_DELIMITER,
|
|
2213
2214
|
BACKLOG_STDIN_DELIMITER,
|
|
2214
2215
|
AGENTIC_QUERY_STDIN_DELIMITER,
|
|
2216
|
+
ENHANCER_STDIN_DELIMITER,
|
|
2215
2217
|
CLASSIFY_STDIN_DELIMITER
|
|
2216
2218
|
];
|
|
2217
2219
|
RESERVED_STRUCTURED_PARAM_MARKERS = [
|
|
@@ -9914,6 +9916,10 @@ var init_api2 = __esm(() => {
|
|
|
9914
9916
|
});
|
|
9915
9917
|
|
|
9916
9918
|
// src/api.ts
|
|
9919
|
+
var exports_api = {};
|
|
9920
|
+
__export(exports_api, {
|
|
9921
|
+
api: () => api
|
|
9922
|
+
});
|
|
9917
9923
|
var init_api3 = __esm(() => {
|
|
9918
9924
|
init_api2();
|
|
9919
9925
|
});
|
|
@@ -76368,6 +76374,24 @@ var init_register_agent = __esm(() => {
|
|
|
76368
76374
|
init_services();
|
|
76369
76375
|
init_convex_error();
|
|
76370
76376
|
});
|
|
76377
|
+
|
|
76378
|
+
// ../../services/backend/prompts/base/shared/context-rule.ts
|
|
76379
|
+
function getContextRuleBlock(contextNewCmd, contextHint) {
|
|
76380
|
+
return `**Context Rule:** Set a new context for every user message by default — skip ONLY when the message is clearly a follow-up of the current chatroom task. **Before running \`context new\`, run \`context read\` — if the pinned context already uses the same \`--trigger-message-id\` as this task's Origin Message ID, do NOT create another context** (avoids duplicate timeline dividers). Only the entry point role can set contexts:
|
|
76381
|
+
\`\`\`bash
|
|
76382
|
+
${contextNewCmd}
|
|
76383
|
+
\`\`\`
|
|
76384
|
+
${contextHint}`;
|
|
76385
|
+
}
|
|
76386
|
+
|
|
76387
|
+
// ../../services/backend/prompts/base/shared/token-activity-note.ts
|
|
76388
|
+
function getTokenActivityInProgressNote() {
|
|
76389
|
+
return "Begin working from the task content above. The daemon detects harness output (stdout tokens) and marks the task `in_progress` automatically — **do not run `task read`** unless you need backlog items or context details not shown in the delivery.";
|
|
76390
|
+
}
|
|
76391
|
+
function getNativeTokenActivityInProgressNote() {
|
|
76392
|
+
return "Begin working from the task content above. The daemon detects harness output (stdout tokens) and marks the task `in_progress` automatically.";
|
|
76393
|
+
}
|
|
76394
|
+
|
|
76371
76395
|
// ../../services/backend/prompts/cli/context/context-template.ts
|
|
76372
76396
|
function getContextViewTemplate() {
|
|
76373
76397
|
return CONTEXT_VIEW_TEMPLATE;
|
|
@@ -76386,20 +76410,60 @@ var CONTEXT_VIEW_TEMPLATE = `## Goal
|
|
|
76386
76410
|
- _Out-of-scope work or anti-patterns to skip._`;
|
|
76387
76411
|
|
|
76388
76412
|
// ../../services/backend/prompts/cli/context/view-template.ts
|
|
76413
|
+
function contextViewTemplateCommand(params) {
|
|
76414
|
+
const prefix = params.cliEnvPrefix || "";
|
|
76415
|
+
return `${prefix}chatroom context view-template`;
|
|
76416
|
+
}
|
|
76389
76417
|
var init_view_template = () => {};
|
|
76390
76418
|
|
|
76391
76419
|
// ../../services/backend/prompts/cli/context/new.ts
|
|
76420
|
+
function contextNewHint(params) {
|
|
76421
|
+
const viewTemplateCmd = contextViewTemplateCommand({ cliEnvPrefix: params.cliEnvPrefix });
|
|
76422
|
+
return `REQUIRED: All context content MUST conform to the template. Run \`${viewTemplateCmd}\` (no flags). \`--trigger-message-id\` must be the task's \`origin-message-id\` attribute (never \`task-id\`). Use the pre-filled value in the command above when provided.`;
|
|
76423
|
+
}
|
|
76424
|
+
function contextNewCommand(params) {
|
|
76425
|
+
const prefix = params.cliEnvPrefix || "";
|
|
76426
|
+
const chatroomId = params.chatroomId || "CHATROOM_ID";
|
|
76427
|
+
const role = params.role || "ROLE";
|
|
76428
|
+
const triggerMessageId = params.triggerMessageId ?? "ORIGIN_MESSAGE_ID";
|
|
76429
|
+
const commandPrefix = `${prefix}chatroom context new --chatroom-id="${chatroomId}" --role="${role}" --trigger-message-id="${triggerMessageId}"`;
|
|
76430
|
+
return formatStdinHeredocCommand(commandPrefix, CONTEXT_STDIN_DELIMITER, getContextViewTemplate());
|
|
76431
|
+
}
|
|
76392
76432
|
var init_new = __esm(() => {
|
|
76393
76433
|
init_stdin_heredoc();
|
|
76394
76434
|
init_view_template();
|
|
76395
76435
|
});
|
|
76396
76436
|
|
|
76397
76437
|
// ../../services/backend/prompts/cli/task-started/main-prompt.ts
|
|
76438
|
+
function getTaskStartedPrompt(ctx) {
|
|
76439
|
+
const { chatroomId, role, cliEnvPrefix, triggerMessageId } = ctx;
|
|
76440
|
+
const contextNewCmd = contextNewCommand({
|
|
76441
|
+
chatroomId,
|
|
76442
|
+
role,
|
|
76443
|
+
cliEnvPrefix,
|
|
76444
|
+
triggerMessageId
|
|
76445
|
+
});
|
|
76446
|
+
return `### Start working
|
|
76447
|
+
|
|
76448
|
+
${getTokenActivityInProgressNote()}
|
|
76449
|
+
|
|
76450
|
+
${getContextRuleBlock(contextNewCmd, contextNewHint({ cliEnvPrefix }))}`;
|
|
76451
|
+
}
|
|
76452
|
+
function getTaskStartedPromptForHandoffRecipient(_ctx) {
|
|
76453
|
+
return `### Start Working
|
|
76454
|
+
|
|
76455
|
+
The task body contains your work description. ${getTokenActivityInProgressNote()}`;
|
|
76456
|
+
}
|
|
76398
76457
|
var init_main_prompt = __esm(() => {
|
|
76399
76458
|
init_new();
|
|
76400
76459
|
});
|
|
76401
76460
|
|
|
76402
76461
|
// ../../services/backend/prompts/cli/task-started/index.ts
|
|
76462
|
+
var exports_task_started = {};
|
|
76463
|
+
__export(exports_task_started, {
|
|
76464
|
+
getTaskStartedPromptForHandoffRecipient: () => getTaskStartedPromptForHandoffRecipient,
|
|
76465
|
+
getTaskStartedPrompt: () => getTaskStartedPrompt
|
|
76466
|
+
});
|
|
76403
76467
|
var init_task_started = __esm(() => {
|
|
76404
76468
|
init_main_prompt();
|
|
76405
76469
|
});
|
|
@@ -76421,6 +76485,14 @@ Exactly one active waiter should own task delivery at a time. Additional or back
|
|
|
76421
76485
|
|
|
76422
76486
|
After interruption or restart: complete any in-progress work, then restore a single foreground blocking \`get-next-task\` so chatroom tasks can arrive again.`;
|
|
76423
76487
|
}
|
|
76488
|
+
function getCompactionRecoveryNote(params) {
|
|
76489
|
+
const { cliEnvPrefix, chatroomId, role } = params;
|
|
76490
|
+
return `NOTE: If you are an agent that has undergone compaction or summarization, run:
|
|
76491
|
+
${cliEnvPrefix}chatroom get-system-prompt --chatroom-id="${chatroomId}" --role="${role}"
|
|
76492
|
+
to reload your full system and role prompt. Then run:
|
|
76493
|
+
${cliEnvPrefix}chatroom context read --chatroom-id="${chatroomId}" --role="${role}"
|
|
76494
|
+
to see your current chatroom task context.`;
|
|
76495
|
+
}
|
|
76424
76496
|
var init_reminder = () => {};
|
|
76425
76497
|
// ../../services/backend/prompts/utils/index.ts
|
|
76426
76498
|
var init_utils3 = __esm(() => {
|
|
@@ -76428,16 +76500,65 @@ var init_utils3 = __esm(() => {
|
|
|
76428
76500
|
});
|
|
76429
76501
|
|
|
76430
76502
|
// ../../services/backend/prompts/base/shared/getting-started-content.ts
|
|
76503
|
+
function getContextGainingGuidance(params) {
|
|
76504
|
+
const { chatroomId, role, convexUrl, agentType } = params;
|
|
76505
|
+
const cliEnvPrefix = getCliEnvPrefix(convexUrl);
|
|
76506
|
+
const typeValue = agentType && agentType !== "unset" ? agentType : "<remote|custom>";
|
|
76507
|
+
return `## Getting Started
|
|
76508
|
+
|
|
76509
|
+
### Workflow Loop
|
|
76510
|
+
|
|
76511
|
+
\`\`\`mermaid
|
|
76512
|
+
flowchart LR
|
|
76513
|
+
A([Start]) --> B[register-agent]
|
|
76514
|
+
B --> C[get-next-task
|
|
76515
|
+
chatroom task delivery]
|
|
76516
|
+
C --> D[Do Work]
|
|
76517
|
+
D --> E[handoff]
|
|
76518
|
+
E --> C
|
|
76519
|
+
\`\`\`
|
|
76520
|
+
|
|
76521
|
+
### Task delivery and activity
|
|
76522
|
+
|
|
76523
|
+
When \`get-next-task\` delivers a chatroom task, the **full task content is included in the output**. ${getTokenActivityInProgressNote()}
|
|
76524
|
+
|
|
76525
|
+
⚠️ Remember your two-level model: completing a **chatroom task** (Level B) does NOT end your **session** (Level A). After every handoff, you must run \`get-next-task\` again to continue the session.
|
|
76526
|
+
|
|
76527
|
+
### Context Recovery (after compaction/summarization)
|
|
76528
|
+
|
|
76529
|
+
${getCompactionRecoveryNote({ cliEnvPrefix, chatroomId, role })}
|
|
76530
|
+
|
|
76531
|
+
CLI harnesses do not support in-session compaction. After context is lost, the daemon performs a hard restart — you must run \`get-next-task\` again to rejoin the chatroom.
|
|
76532
|
+
|
|
76533
|
+
### Register Agent
|
|
76534
|
+
Register your agent type before starting work.
|
|
76535
|
+
|
|
76536
|
+
\`\`\`bash
|
|
76537
|
+
${cliEnvPrefix}chatroom register-agent --chatroom-id="${chatroomId}" --role="${role}" --type=${typeValue}
|
|
76538
|
+
\`\`\`
|
|
76539
|
+
|
|
76540
|
+
### Get Next Task
|
|
76541
|
+
Listen for incoming tasks assigned to your role. A foreground \`get-next-task\` blocks until the user or team message is ready, then resolves with that message as a chatroom task—infer intent from the message rather than following numbered next-steps blindly.
|
|
76542
|
+
|
|
76543
|
+
\`\`\`bash
|
|
76544
|
+
${cliEnvPrefix}chatroom get-next-task --chatroom-id="${chatroomId}" --role="${role}"
|
|
76545
|
+
\`\`\`
|
|
76546
|
+
|
|
76547
|
+
**This loop never ends.** A session (Level A) processes many chatroom tasks (Level B). Each handoff completes Level B — \`get-next-task\` continues Level A. Do not stop or exit after a handoff.
|
|
76548
|
+
`;
|
|
76549
|
+
}
|
|
76431
76550
|
var init_getting_started_content = __esm(() => {
|
|
76432
76551
|
init_reminder();
|
|
76433
76552
|
init_utils3();
|
|
76434
76553
|
});
|
|
76435
76554
|
|
|
76436
76555
|
// ../../services/backend/prompts/cli/index.ts
|
|
76556
|
+
var getTaskStartedPrompt2, getTaskStartedPromptForHandoffRecipient2;
|
|
76437
76557
|
var init_cli = __esm(() => {
|
|
76438
76558
|
init_task_started();
|
|
76439
76559
|
init_reminder();
|
|
76440
76560
|
init_getting_started_content();
|
|
76561
|
+
({ getTaskStartedPrompt: getTaskStartedPrompt2, getTaskStartedPromptForHandoffRecipient: getTaskStartedPromptForHandoffRecipient2 } = exports_task_started);
|
|
76441
76562
|
});
|
|
76442
76563
|
|
|
76443
76564
|
// src/commands/get-next-task/get-next-task-session-service.ts
|
|
@@ -77735,7 +77856,89 @@ function formatDecodeError(error) {
|
|
|
77735
77856
|
return message;
|
|
77736
77857
|
}
|
|
77737
77858
|
|
|
77859
|
+
// ../../services/backend/config/reliability.ts
|
|
77860
|
+
var HARNESS_SESSION_READY_TIMEOUT_MS = 5000, NATIVE_DELIVERY_RECONCILE_MS = 1e4, DAEMON_HEARTBEAT_INTERVAL_MS, DAEMON_HEARTBEAT_TTL_MS, AGENT_REQUEST_DEADLINE_MS = 120000, OBSERVED_FULL_PUSH_INTERVAL_MS, OBSERVED_SAFETY_POLL_MS = 30000, OBSERVED_SYNC_RECONCILE_MS, WORKSPACE_RECENCY_WINDOW_MS, WORKSPACE_LIST_RECONCILE_MS, CONNECTION_CLOSE_REQUEST_TTL_MS, ENHANCER_ATTEMPT_TIMEOUT_MS = 120000, ENHANCER_TERMINAL_JOB_RETENTION_MS, ENHANCER_CLI_POLL_INTERVAL_MS = 1000;
|
|
77861
|
+
var init_reliability = __esm(() => {
|
|
77862
|
+
DAEMON_HEARTBEAT_INTERVAL_MS = 5 * 60000;
|
|
77863
|
+
DAEMON_HEARTBEAT_TTL_MS = 6 * DAEMON_HEARTBEAT_INTERVAL_MS;
|
|
77864
|
+
OBSERVED_FULL_PUSH_INTERVAL_MS = 5 * 60000;
|
|
77865
|
+
OBSERVED_SYNC_RECONCILE_MS = 15 * 60000;
|
|
77866
|
+
WORKSPACE_RECENCY_WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
|
|
77867
|
+
WORKSPACE_LIST_RECONCILE_MS = 60 * 60 * 1000;
|
|
77868
|
+
CONNECTION_CLOSE_REQUEST_TTL_MS = 10 * 60000;
|
|
77869
|
+
ENHANCER_TERMINAL_JOB_RETENTION_MS = 30 * 24 * 60 * 60 * 1000;
|
|
77870
|
+
});
|
|
77871
|
+
|
|
77872
|
+
// src/commands/enhancer/wait-for-job.ts
|
|
77873
|
+
var exports_wait_for_job = {};
|
|
77874
|
+
__export(exports_wait_for_job, {
|
|
77875
|
+
waitForEnhancerJob: () => waitForEnhancerJob
|
|
77876
|
+
});
|
|
77877
|
+
async function waitForEnhancerJob(chatroomId, jobId, deps) {
|
|
77878
|
+
const sessionId = await deps.getSessionId();
|
|
77879
|
+
if (!sessionId) {
|
|
77880
|
+
throw new Error("Not authenticated");
|
|
77881
|
+
}
|
|
77882
|
+
while (true) {
|
|
77883
|
+
const job = await deps.query(deps.endpoints.getJob, {
|
|
77884
|
+
sessionId,
|
|
77885
|
+
chatroomId,
|
|
77886
|
+
jobId
|
|
77887
|
+
});
|
|
77888
|
+
if (!job) {
|
|
77889
|
+
throw new Error("Enhancer job not found");
|
|
77890
|
+
}
|
|
77891
|
+
if (job.status === "complete") {
|
|
77892
|
+
return "complete";
|
|
77893
|
+
}
|
|
77894
|
+
if (job.status === "cancelled") {
|
|
77895
|
+
return "cancelled";
|
|
77896
|
+
}
|
|
77897
|
+
if (job.status === "failed") {
|
|
77898
|
+
return "failed";
|
|
77899
|
+
}
|
|
77900
|
+
if (job.status === "running" && job.runningSince) {
|
|
77901
|
+
const elapsed3 = Date.now() - job.runningSince;
|
|
77902
|
+
if (elapsed3 > ENHANCER_ATTEMPT_TIMEOUT_MS) {
|
|
77903
|
+
await deps.mutation(deps.endpoints.recordAttemptFailure, {
|
|
77904
|
+
sessionId,
|
|
77905
|
+
chatroomId,
|
|
77906
|
+
jobId,
|
|
77907
|
+
error: "Attempt timed out"
|
|
77908
|
+
});
|
|
77909
|
+
await sleep5(ENHANCER_CLI_POLL_INTERVAL_MS);
|
|
77910
|
+
continue;
|
|
77911
|
+
}
|
|
77912
|
+
}
|
|
77913
|
+
await sleep5(ENHANCER_CLI_POLL_INTERVAL_MS);
|
|
77914
|
+
}
|
|
77915
|
+
}
|
|
77916
|
+
function sleep5(ms) {
|
|
77917
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
77918
|
+
}
|
|
77919
|
+
var init_wait_for_job = __esm(() => {
|
|
77920
|
+
init_reliability();
|
|
77921
|
+
});
|
|
77922
|
+
|
|
77738
77923
|
// ../../services/backend/prompts/native/session-continuity.ts
|
|
77924
|
+
function getSessionContinuityLine(nativeIntegration) {
|
|
77925
|
+
if (nativeIntegration) {
|
|
77926
|
+
return "";
|
|
77927
|
+
}
|
|
77928
|
+
return "Completing a **chatroom task** (Level B) does NOT end your **session** (Level A). After every handoff, run `get-next-task` to continue.";
|
|
77929
|
+
}
|
|
77930
|
+
function getHandoffContinuityRule(nativeIntegration) {
|
|
77931
|
+
if (nativeIntegration) {
|
|
77932
|
+
return "";
|
|
77933
|
+
}
|
|
77934
|
+
return "⚠️ After ANY handoff (including to `user`), you must run `get-next-task` to stay in the session.";
|
|
77935
|
+
}
|
|
77936
|
+
function getOperatingModelLoopFooter(nativeIntegration) {
|
|
77937
|
+
return nativeIntegration ? "Hand off when complete" : "Run get-next-task";
|
|
77938
|
+
}
|
|
77939
|
+
function getNativePlannerDelegationWaitNote() {
|
|
77940
|
+
return `After delegating to the builder, **run handoff as your last action and end your turn** — no further tool calls after handoff. The system delivers their handback when they finish — do not poll \`messages list\`, sleep, or run other tools while waiting.`;
|
|
77941
|
+
}
|
|
77739
77942
|
function getNativeHandoffTurnEndGuidance(nextRole) {
|
|
77740
77943
|
const lines = [
|
|
77741
77944
|
"",
|
|
@@ -77751,10 +77954,103 @@ function getNativeHandoffTurnEndGuidance(nextRole) {
|
|
|
77751
77954
|
}
|
|
77752
77955
|
|
|
77753
77956
|
// ../../services/backend/prompts/cli/handoff/command.ts
|
|
77957
|
+
function handoffCommand(params) {
|
|
77958
|
+
const prefix = params.cliEnvPrefix || "";
|
|
77959
|
+
const chatroomId = params.chatroomId || "<chatroom-id>";
|
|
77960
|
+
const role = params.role || "<role>";
|
|
77961
|
+
const nextRole = params.nextRole || "<target>";
|
|
77962
|
+
const placeholder = params.messagePlaceholder ?? "[Your message here]";
|
|
77963
|
+
const commandPrefix = `${prefix}chatroom handoff --chatroom-id="${chatroomId}" --role="${role}" --next-role="${nextRole}"`;
|
|
77964
|
+
return formatStdinHeredocCommand(commandPrefix, HANDOFF_STDIN_DELIMITER, placeholder, {
|
|
77965
|
+
messageMarker: HANDOFF_MESSAGE_MARKER
|
|
77966
|
+
});
|
|
77967
|
+
}
|
|
77754
77968
|
var init_command2 = __esm(() => {
|
|
77755
77969
|
init_stdin_heredoc();
|
|
77756
77970
|
});
|
|
77971
|
+
|
|
77972
|
+
// ../../services/backend/prompts/types/sections.ts
|
|
77973
|
+
function createSection(id3, type, content) {
|
|
77974
|
+
return { id: id3, type, content };
|
|
77975
|
+
}
|
|
77976
|
+
function composeSections(sections) {
|
|
77977
|
+
return sections.filter((s) => s.content.trim()).map((s) => s.content).join(`
|
|
77978
|
+
|
|
77979
|
+
`).trim();
|
|
77980
|
+
}
|
|
77981
|
+
|
|
77757
77982
|
// ../../services/backend/prompts/sections/commands-reference.ts
|
|
77983
|
+
function getCommandsReferenceSection(params) {
|
|
77984
|
+
const cliEnvPrefix = getCliEnvPrefix(params.convexUrl);
|
|
77985
|
+
const handoffCmd = handoffCommand({
|
|
77986
|
+
chatroomId: params.chatroomId,
|
|
77987
|
+
role: params.role,
|
|
77988
|
+
nextRole: "<target>",
|
|
77989
|
+
cliEnvPrefix
|
|
77990
|
+
});
|
|
77991
|
+
const waitCmd = getNextTaskCommand({
|
|
77992
|
+
chatroomId: params.chatroomId,
|
|
77993
|
+
role: params.role,
|
|
77994
|
+
cliEnvPrefix
|
|
77995
|
+
});
|
|
77996
|
+
const content = `### Commands
|
|
77997
|
+
|
|
77998
|
+
**Complete chatroom task and hand off:**
|
|
77999
|
+
|
|
78000
|
+
\`\`\`bash
|
|
78001
|
+
${handoffCmd}
|
|
78002
|
+
\`\`\`
|
|
78003
|
+
|
|
78004
|
+
${HANDOFF_BODY_GUIDANCE}
|
|
78005
|
+
|
|
78006
|
+
**Continue receiving messages after \`handoff\`:**
|
|
78007
|
+
\`\`\`
|
|
78008
|
+
${waitCmd}
|
|
78009
|
+
\`\`\`
|
|
78010
|
+
|
|
78011
|
+
${getNextTaskReminder()}
|
|
78012
|
+
|
|
78013
|
+
**Reference commands:**
|
|
78014
|
+
- List recent messages: \`${cliEnvPrefix}chatroom messages list --chatroom-id="${params.chatroomId}" --role="${params.role}" --sender-role=user --limit=5 --full\`
|
|
78015
|
+
- Git log: \`git log --oneline -10\`
|
|
78016
|
+
|
|
78017
|
+
**Recovery commands** (only needed after compaction/restart):
|
|
78018
|
+
- Reload system prompt: \`${cliEnvPrefix}chatroom get-system-prompt --chatroom-id="${params.chatroomId}" --role="${params.role}"\`
|
|
78019
|
+
- Reload role guidance: \`${roleGuidanceCommand({ chatroomId: params.chatroomId, role: params.role, cliEnvPrefix })}\`
|
|
78020
|
+
- Read current chatroom task context: \`${cliEnvPrefix}chatroom context read --chatroom-id="${params.chatroomId}" --role="${params.role}"\``;
|
|
78021
|
+
return createSection("commands-reference", "knowledge", content);
|
|
78022
|
+
}
|
|
78023
|
+
function getNativeCommandsReferenceSection(params) {
|
|
78024
|
+
const cliEnvPrefix = getCliEnvPrefix(params.convexUrl);
|
|
78025
|
+
const handoffCmd = handoffCommand({
|
|
78026
|
+
chatroomId: params.chatroomId,
|
|
78027
|
+
role: params.role,
|
|
78028
|
+
nextRole: "<target>",
|
|
78029
|
+
cliEnvPrefix
|
|
78030
|
+
});
|
|
78031
|
+
const content = `### Commands
|
|
78032
|
+
|
|
78033
|
+
**Complete chatroom task and hand off:**
|
|
78034
|
+
|
|
78035
|
+
\`\`\`bash
|
|
78036
|
+
${handoffCmd}
|
|
78037
|
+
\`\`\`
|
|
78038
|
+
|
|
78039
|
+
${HANDOFF_BODY_GUIDANCE}
|
|
78040
|
+
|
|
78041
|
+
**Do not run \`register-agent\`** — your session was registered when the harness started.
|
|
78042
|
+
|
|
78043
|
+
**Reference commands:**
|
|
78044
|
+
- List recent messages: \`${cliEnvPrefix}chatroom messages list --chatroom-id="${params.chatroomId}" --role="${params.role}" --sender-role=user --limit=5 --full\`
|
|
78045
|
+
- Git log: \`git log --oneline -10\`
|
|
78046
|
+
|
|
78047
|
+
**Recovery commands** (only needed after compaction/restart):
|
|
78048
|
+
- Reload system prompt: \`${cliEnvPrefix}chatroom get-system-prompt --chatroom-id="${params.chatroomId}" --role="${params.role}"\`
|
|
78049
|
+
- Reload role guidance: \`${roleGuidanceCommand({ chatroomId: params.chatroomId, role: params.role, cliEnvPrefix })}\`
|
|
78050
|
+
- Read current chatroom task context: \`${cliEnvPrefix}chatroom context read --chatroom-id="${params.chatroomId}" --role="${params.role}"\``;
|
|
78051
|
+
return createSection("commands-reference-native", "knowledge", content);
|
|
78052
|
+
}
|
|
78053
|
+
var HANDOFF_BODY_GUIDANCE = `Fill in the message using the matching template from \`<handoff-templates>\` in your task delivery output. Replace \`[Your message here]\` with that template content. The closing line must be exactly \`CHATROOM_HANDOFF_END\` (not \`EOF\`).`;
|
|
77758
78054
|
var init_commands_reference = __esm(() => {
|
|
77759
78055
|
init_command();
|
|
77760
78056
|
init_reminder();
|
|
@@ -77763,25 +78059,650 @@ var init_commands_reference = __esm(() => {
|
|
|
77763
78059
|
});
|
|
77764
78060
|
|
|
77765
78061
|
// ../../services/backend/prompts/cli/backlog/command.ts
|
|
78062
|
+
function backlogAddCommand(params) {
|
|
78063
|
+
const prefix = params.cliEnvPrefix || "";
|
|
78064
|
+
const chatroomId = params.chatroomId || "<id>";
|
|
78065
|
+
const role = params.role || "<role>";
|
|
78066
|
+
const placeholder = params.contentPlaceholder ?? "Your backlog item content here";
|
|
78067
|
+
const commandPrefix = `${prefix}chatroom backlog add --chatroom-id=${chatroomId} --role=${role}`;
|
|
78068
|
+
return formatStdinHeredocCommand(commandPrefix, BACKLOG_STDIN_DELIMITER, placeholder);
|
|
78069
|
+
}
|
|
78070
|
+
function backlogUpdateCommand(params) {
|
|
78071
|
+
const prefix = params.cliEnvPrefix || "";
|
|
78072
|
+
const chatroomId = params.chatroomId || "<id>";
|
|
78073
|
+
const role = params.role || "<role>";
|
|
78074
|
+
const backlogItemId = params.backlogItemId || "<id>";
|
|
78075
|
+
const placeholder = params.contentPlaceholder ?? "New content here";
|
|
78076
|
+
const commandPrefix = `${prefix}chatroom backlog update --chatroom-id=${chatroomId} --role=${role} --backlog-item-id=${backlogItemId}`;
|
|
78077
|
+
return formatStdinHeredocCommand(commandPrefix, BACKLOG_STDIN_DELIMITER, placeholder);
|
|
78078
|
+
}
|
|
77766
78079
|
var init_command3 = __esm(() => {
|
|
77767
78080
|
init_stdin_heredoc();
|
|
77768
78081
|
});
|
|
77769
78082
|
|
|
77770
78083
|
// ../../services/backend/src/domain/usecase/skills/modules/backlog/index.ts
|
|
78084
|
+
var backlogSkill;
|
|
77771
78085
|
var init_backlog = __esm(() => {
|
|
77772
78086
|
init_command3();
|
|
78087
|
+
backlogSkill = {
|
|
78088
|
+
skillId: "backlog",
|
|
78089
|
+
name: "Backlog Reference",
|
|
78090
|
+
description: "Full backlog command reference: list/add/update, scoring, completion, close, export/import, and workflow guides.",
|
|
78091
|
+
getPrompt: (cliEnvPrefix) => `You have been activated with the "backlog" skill.
|
|
78092
|
+
|
|
78093
|
+
## Command Reference
|
|
78094
|
+
|
|
78095
|
+
### List
|
|
78096
|
+
\`\`\`
|
|
78097
|
+
${cliEnvPrefix}chatroom backlog list --chatroom-id=<id> --role=<role>
|
|
78098
|
+
\`\`\`
|
|
78099
|
+
Options: \`--limit=<n>\`, \`--sort=date:desc|priority:desc\`, \`--filter=unscored\` (only items without a priority score)
|
|
78100
|
+
|
|
78101
|
+
The list output shows scoring info (complexity, value, priority) for each item if it has been scored.
|
|
78102
|
+
|
|
78103
|
+
### History
|
|
78104
|
+
\`\`\`
|
|
78105
|
+
${cliEnvPrefix}chatroom backlog history --chatroom-id=<id> --role=<role>
|
|
78106
|
+
\`\`\`
|
|
78107
|
+
Options: \`--from=YYYY-MM-DD\`, \`--to=YYYY-MM-DD\`, \`--limit=<n>\`
|
|
78108
|
+
|
|
78109
|
+
Defaults: last 30 days through today; shows completed and closed tasks in range.
|
|
78110
|
+
|
|
78111
|
+
Use \`history\` for finished work; use \`list\` for active backlog items.
|
|
78112
|
+
|
|
78113
|
+
### Add
|
|
78114
|
+
Content via **stdin / heredoc** or \`--content-file\`:
|
|
78115
|
+
|
|
78116
|
+
\`\`\`
|
|
78117
|
+
${backlogAddCommand({ cliEnvPrefix })}
|
|
78118
|
+
\`\`\`
|
|
78119
|
+
|
|
78120
|
+
\`\`\`
|
|
78121
|
+
${cliEnvPrefix}chatroom backlog add --chatroom-id=<id> --role=<role> --content-file=./task.md
|
|
78122
|
+
\`\`\`
|
|
78123
|
+
|
|
78124
|
+
### Update
|
|
78125
|
+
Replace the **text content** of an existing item. Allowed only while the item is in \`backlog\` status. Same input pattern as **add** (stdin/heredoc or \`--content-file\`).
|
|
78126
|
+
|
|
78127
|
+
\`\`\`
|
|
78128
|
+
${backlogUpdateCommand({ cliEnvPrefix })}
|
|
78129
|
+
\`\`\`
|
|
78130
|
+
|
|
78131
|
+
\`\`\`
|
|
78132
|
+
${cliEnvPrefix}chatroom backlog update --chatroom-id=<id> --role=<role> --backlog-item-id=<id> --content-file=./revised.md
|
|
78133
|
+
\`\`\`
|
|
78134
|
+
|
|
78135
|
+
Use **update** to revise a description in place instead of adding a superseding item.
|
|
78136
|
+
|
|
78137
|
+
### Score
|
|
78138
|
+
**Requires at least one** of \`--complexity\`, \`--value\`, or \`--priority\` (you can combine multiple).
|
|
78139
|
+
|
|
78140
|
+
\`\`\`
|
|
78141
|
+
${cliEnvPrefix}chatroom backlog score --chatroom-id=<id> --role=<role> --backlog-item-id=<id> \\
|
|
78142
|
+
[--complexity=<low|medium|high>] \\
|
|
78143
|
+
[--value=<low|medium|high>] \\
|
|
78144
|
+
[--priority=<n>]
|
|
78145
|
+
\`\`\`
|
|
78146
|
+
|
|
78147
|
+
\`--priority\` must be an integer (higher = more important). There is no enforced max in the CLI.
|
|
78148
|
+
|
|
78149
|
+
**Important**: Only score items that do not already have all three fields set (complexity, value, priority).
|
|
78150
|
+
Check the list output — items showing "Score: ..." are already scored. Skip them to avoid overwriting.
|
|
78151
|
+
|
|
78152
|
+
### Complete
|
|
78153
|
+
\`\`\`
|
|
78154
|
+
${cliEnvPrefix}chatroom backlog complete --chatroom-id=<id> --role=<role> --backlog-item-id=<id> [-f|--force]
|
|
78155
|
+
\`\`\`
|
|
78156
|
+
|
|
78157
|
+
Optional \`-f\` / \`--force\` is a registered flag (see \`chatroom backlog complete --help\`). It is **not** forwarded to the Convex mutation yet, so it does not change server behavior today; omit it unless your runbook says otherwise.
|
|
78158
|
+
|
|
78159
|
+
### Reopen
|
|
78160
|
+
\`\`\`
|
|
78161
|
+
${cliEnvPrefix}chatroom backlog reopen --chatroom-id=<id> --role=<role> --backlog-item-id=<id>
|
|
78162
|
+
\`\`\`
|
|
78163
|
+
|
|
78164
|
+
### Mark for Review
|
|
78165
|
+
\`\`\`
|
|
78166
|
+
${cliEnvPrefix}chatroom backlog mark-for-review --chatroom-id=<id> --role=<role> --backlog-item-id=<id>
|
|
78167
|
+
\`\`\`
|
|
78168
|
+
|
|
78169
|
+
### Export
|
|
78170
|
+
\`\`\`
|
|
78171
|
+
${cliEnvPrefix}chatroom backlog export --chatroom-id=<id> --role=<role> [--path=<directory>]
|
|
78172
|
+
\`\`\`
|
|
78173
|
+
Exports all backlog items (status=\`backlog\`) to a \`backlog-export.json\` file in the specified directory.
|
|
78174
|
+
Creates the directory if it doesn't exist.
|
|
78175
|
+
Default path (if \`--path\` is omitted): \`<cwd>/.chatroom/exports/\`
|
|
78176
|
+
|
|
78177
|
+
### Import
|
|
78178
|
+
\`\`\`
|
|
78179
|
+
${cliEnvPrefix}chatroom backlog import --chatroom-id=<id> --role=<role> [--path=<directory>]
|
|
78180
|
+
\`\`\`
|
|
78181
|
+
Imports backlog items from a \`backlog-export.json\` file in the specified directory.
|
|
78182
|
+
- **Idempotent**: skips items whose content already exists (matched by SHA-256 content hash)
|
|
78183
|
+
- **Staleness warning**: warns if the export is older than 7 days
|
|
78184
|
+
Default path (if \`--path\` is omitted): \`<cwd>/.chatroom/exports/\`
|
|
78185
|
+
|
|
78186
|
+
### Close
|
|
78187
|
+
Retires an item as stale, superseded, or duplicate. **\`--reason\` is required** (audit trail).
|
|
78188
|
+
|
|
78189
|
+
\`\`\`
|
|
78190
|
+
${cliEnvPrefix}chatroom backlog close --chatroom-id=<id> --role=<role> --backlog-item-id=<id> --reason="duplicate of XYZ"
|
|
78191
|
+
\`\`\`
|
|
78192
|
+
|
|
78193
|
+
⚠️ **RESTRICTED: Only use when the user explicitly asks you to close an item.**
|
|
78194
|
+
Agents must NEVER close backlog items autonomously. If an item looks stale or already implemented, prefer \`mark-for-review\` so the user decides.
|
|
78195
|
+
|
|
78196
|
+
Give a concise, factual reason (e.g. \`User confirmed: shipped in PR #119\`).
|
|
78197
|
+
|
|
78198
|
+
---
|
|
78199
|
+
|
|
78200
|
+
## Lifecycle
|
|
78201
|
+
|
|
78202
|
+
Backlog items move through explicit statuses. **When you raise a PR for user review, use \`mark-for-review\` — not \`complete\`.** Only mark \`complete\` after the PR is merged and verified (or the user confirms).
|
|
78203
|
+
|
|
78204
|
+
\`\`\`mermaid
|
|
78205
|
+
stateDiagram-v2
|
|
78206
|
+
[*] --> backlog: user creates
|
|
78207
|
+
backlog --> pending_user_review: agent raises PR (mark-for-review)
|
|
78208
|
+
pending_user_review --> closed: user confirms / PR merged (complete)
|
|
78209
|
+
backlog --> closed: stale/superseded (close)
|
|
78210
|
+
closed --> backlog: reopen
|
|
78211
|
+
\`\`\`
|
|
78212
|
+
|
|
78213
|
+
### Command decision table
|
|
78214
|
+
|
|
78215
|
+
| Situation | Command |
|
|
78216
|
+
|-----------|---------|
|
|
78217
|
+
| Fix PR opened, awaiting user review/merge | \`mark-for-review\` |
|
|
78218
|
+
| PR merged and verified | \`complete\` |
|
|
78219
|
+
| Stale/duplicate/won't fix | \`close --reason=...\` |
|
|
78220
|
+
| Mistakenly completed early | \`reopen\` then \`mark-for-review\` |
|
|
78221
|
+
|
|
78222
|
+
Reference: \`docs/plans/backlog-item-lifecycle-and-attachments.md\`
|
|
78223
|
+
|
|
78224
|
+
---
|
|
78225
|
+
|
|
78226
|
+
## Workflows
|
|
78227
|
+
|
|
78228
|
+
### 1. Score Unscored Items
|
|
78229
|
+
|
|
78230
|
+
\`\`\`mermaid
|
|
78231
|
+
flowchart TD
|
|
78232
|
+
A([Start]) --> B[List backlog items]
|
|
78233
|
+
B --> C{Any unscored?}
|
|
78234
|
+
C -->|No| D([Done])
|
|
78235
|
+
C -->|Yes| E["Check item: does it already have complexity + value + priority set?"]
|
|
78236
|
+
E -->|Already scored| F[Skip — do not overwrite existing score]
|
|
78237
|
+
F --> C
|
|
78238
|
+
E -->|Not scored| G[Score item: complexity, value, priority]
|
|
78239
|
+
G --> C
|
|
78240
|
+
\`\`\`
|
|
78241
|
+
|
|
78242
|
+
An item is "already scored" if the list output shows "Score: complexity=... | value=... | priority=...".
|
|
78243
|
+
|
|
78244
|
+
### 2. After Completing a Backlog Task (PR raised)
|
|
78245
|
+
|
|
78246
|
+
\`\`\`mermaid
|
|
78247
|
+
flowchart TD
|
|
78248
|
+
A([Implementation complete]) --> B[Open PR for user review]
|
|
78249
|
+
B --> C["mark-for-review (NOT complete)"]
|
|
78250
|
+
C --> D[Hand off to user with PR link + summary]
|
|
78251
|
+
D --> E([User reviews in Pending Review section])
|
|
78252
|
+
\`\`\`
|
|
78253
|
+
|
|
78254
|
+
Moves item to \`pending_user_review\`. User confirms completion (\`complete\`) or sends back for rework (\`reopen\`).
|
|
78255
|
+
|
|
78256
|
+
### 3. Continuous Backlog Execution
|
|
78257
|
+
|
|
78258
|
+
Only activate when the user explicitly instructs autonomous execution
|
|
78259
|
+
(e.g. "work through the backlog", "autonomously implement backlog items").
|
|
78260
|
+
|
|
78261
|
+
\`\`\`mermaid
|
|
78262
|
+
flowchart TD
|
|
78263
|
+
A([Start]) --> B[List all backlog items]
|
|
78264
|
+
B --> C{Any unscored?}
|
|
78265
|
+
C -->|Yes| D["Score only items missing complexity/value/priority\\n(skip already-scored items)"] --> E[Re-list]
|
|
78266
|
+
C -->|No| E
|
|
78267
|
+
E --> F["Select items: complexity=low AND value=high"]
|
|
78268
|
+
F --> G{Qualifying items?}
|
|
78269
|
+
G -->|No| H([Hand off — no high-ROI items found])
|
|
78270
|
+
G -->|Yes| I[Take next item]
|
|
78271
|
+
I --> J{Already implemented?\\nCheck codebase / recent commits}
|
|
78272
|
+
J -->|Yes — stale| K["Mark for review\\n(note: already implemented)"]
|
|
78273
|
+
J -->|No| L[Implement: code changes + PR]
|
|
78274
|
+
L --> K
|
|
78275
|
+
K --> M[Mark item for review]
|
|
78276
|
+
M --> N{More items?}
|
|
78277
|
+
N -->|Yes| I
|
|
78278
|
+
N -->|No| O[Hand off to user with full summary]
|
|
78279
|
+
O --> P([Done])
|
|
78280
|
+
\`\`\`
|
|
78281
|
+
|
|
78282
|
+
Stale item = backlog task already present in the codebase. Mark immediately; skip implementation.
|
|
78283
|
+
ROI = low complexity × high value.
|
|
78284
|
+
|
|
78285
|
+
### 4. Backlog Cleanup
|
|
78286
|
+
|
|
78287
|
+
Follow these steps to clean up the backlog by identifying and closing stale items.
|
|
78288
|
+
|
|
78289
|
+
1. List all backlog items:
|
|
78290
|
+
\`\`\`
|
|
78291
|
+
${cliEnvPrefix}chatroom backlog list --chatroom-id=<id> --role=<role>
|
|
78292
|
+
\`\`\`
|
|
78293
|
+
|
|
78294
|
+
2. For each item, assess staleness:
|
|
78295
|
+
- Read the content carefully
|
|
78296
|
+
- If the item is still valid but the **wording is wrong**, use \`backlog update\` to fix the description in place (do not add a duplicate item)
|
|
78297
|
+
- Check if already implemented (look at recent commits, PRs, or existing code)
|
|
78298
|
+
- Check if superseded by a newer backlog item
|
|
78299
|
+
|
|
78300
|
+
3. For stale items, mark for review:
|
|
78301
|
+
\`\`\`
|
|
78302
|
+
${cliEnvPrefix}chatroom backlog mark-for-review --chatroom-id=<id> --role=<role> --backlog-item-id=<item-id>
|
|
78303
|
+
\`\`\`
|
|
78304
|
+
**Important:** Always mark for review — do NOT close directly. Let the user confirm.
|
|
78305
|
+
|
|
78306
|
+
4. If you are the coordinator, delegate assessment to workers:
|
|
78307
|
+
- Builder checks codebase to determine if items are stale
|
|
78308
|
+
- Builder marks stale items for review and reports back
|
|
78309
|
+
|
|
78310
|
+
5. Report summary: items reviewed, marked for review, kept, needs clarification
|
|
78311
|
+
|
|
78312
|
+
### 5. Export / Import Backlog
|
|
78313
|
+
|
|
78314
|
+
Use export/import to transfer backlog items between workspaces or for backup.
|
|
78315
|
+
Default path: \`<cwd>/.chatroom/exports/\` — omit \`--path\` to use this.
|
|
78316
|
+
|
|
78317
|
+
**Export workflow:**
|
|
78318
|
+
\`\`\`mermaid
|
|
78319
|
+
flowchart TD
|
|
78320
|
+
A([Start]) --> B["Export backlog"]
|
|
78321
|
+
B --> C["chatroom backlog export\\n(writes to <cwd>/.chatroom/exports/ by default)"]
|
|
78322
|
+
C --> D["File written: backlog-export.json"]
|
|
78323
|
+
D --> E([Done — report file path to user])
|
|
78324
|
+
\`\`\`
|
|
78325
|
+
|
|
78326
|
+
**Import workflow:**
|
|
78327
|
+
\`\`\`mermaid
|
|
78328
|
+
flowchart TD
|
|
78329
|
+
A([Start]) --> B["Import backlog"]
|
|
78330
|
+
B --> C["chatroom backlog import\\n(reads from <cwd>/.chatroom/exports/ by default)"]
|
|
78331
|
+
C --> D{Staleness warning?}
|
|
78332
|
+
D -->|Yes — export > 7 days old| E["Warn user: export may be stale"]
|
|
78333
|
+
D -->|No| F["Import items (skip duplicates)"]
|
|
78334
|
+
E --> F
|
|
78335
|
+
F --> G["Report: total / imported / skipped"]
|
|
78336
|
+
G --> H([Done])
|
|
78337
|
+
\`\`\`
|
|
78338
|
+
|
|
78339
|
+
**Key points:**
|
|
78340
|
+
- Default path is \`<cwd>/.chatroom/exports/\` — no \`--path\` needed for standard usage
|
|
78341
|
+
- Use \`--path=<dir>\` to override with a custom directory
|
|
78342
|
+
- Imports are idempotent — running import twice with the same file won't create duplicates
|
|
78343
|
+
- Each item is identified by a SHA-256 hash of its content`
|
|
78344
|
+
};
|
|
77773
78345
|
});
|
|
77774
78346
|
|
|
77775
78347
|
// ../../services/backend/src/domain/usecase/skills/modules/code-review/index.ts
|
|
77776
|
-
var
|
|
78348
|
+
var codeReviewSkill;
|
|
78349
|
+
var init_code_review = __esm(() => {
|
|
78350
|
+
codeReviewSkill = {
|
|
78351
|
+
skillId: "code-review",
|
|
78352
|
+
name: "Code Review",
|
|
78353
|
+
description: "Use this skill when reviewing, auditing, or giving feedback on code. Covers ten pillars: simplification, type drift, duplication, design patterns, security, test quality, ownership/observability, dead code elimination, incomplete implementations, and hallucinated content.",
|
|
78354
|
+
getPrompt: (_cliEnvPrefix) => `You have been activated with the "code-review" skill.
|
|
78355
|
+
|
|
78356
|
+
# AI Code Review — Tech Debt Prevention
|
|
78357
|
+
|
|
78358
|
+
You are reviewing code that was fully or partially generated by an AI tool. Your job is not
|
|
78359
|
+
just to check if it works — working code is the floor, not the ceiling. Your job is to assess
|
|
78360
|
+
whether it is maintainable, secure, and coherent with the broader codebase.
|
|
78361
|
+
|
|
78362
|
+
AI code is highly functional but architecturally blind. It implements the prompt without
|
|
78363
|
+
considering existing patterns, refactoring opportunities, or long-term cost. Research from
|
|
78364
|
+
2025–2026 shows AI code carries 1.75x more logic errors, 1.64x more maintainability issues,
|
|
78365
|
+
and 1.57x more security findings than human-written code (CodeRabbit, 2025). 66% of developers
|
|
78366
|
+
report spending more time fixing AI output than it saved (Stack Overflow, 2026).
|
|
78367
|
+
|
|
78368
|
+
Apply the ten pillars below in priority order.
|
|
78369
|
+
|
|
78370
|
+
---
|
|
78371
|
+
|
|
78372
|
+
## How to run a review
|
|
78373
|
+
|
|
78374
|
+
1. Read the code in full before making any comments — do not flag issues as you scan
|
|
78375
|
+
2. Apply each pillar in order; stop and note findings as you go
|
|
78376
|
+
3. Classify each finding as BLOCK (must fix before merge) or FLAG (must be addressed by author)
|
|
78377
|
+
4. Summarise findings at the end using the output template below
|
|
78378
|
+
5. If the PR is over ~300 lines of net-new AI code, recommend decomposition before review
|
|
78379
|
+
|
|
78380
|
+
---
|
|
78381
|
+
|
|
78382
|
+
## Pillar 1 — Simplification (Highest Priority)
|
|
78383
|
+
|
|
78384
|
+
AI generates more code than needed. The average developer checked in 75% more code in 2025
|
|
78385
|
+
than in 2022 — volume that the team now has to maintain. AI agents never suggest refactoring,
|
|
78386
|
+
so complexity accumulates silently.
|
|
78387
|
+
|
|
78388
|
+
Look for:
|
|
78389
|
+
- Functions over ~40 lines or classes over ~200 lines with no clear single responsibility
|
|
78390
|
+
- Monolithic architecture: 40–50% of AI code defaults to tightly-coupled structures that
|
|
78391
|
+
reverse a decade of modular progress (OX Security, 2025)
|
|
78392
|
+
- Phantom Bugs: logic handling highly improbable edge cases, adding complexity with no benefit
|
|
78393
|
+
(found in 20–30% of AI code)
|
|
78394
|
+
- Dead code, unused imports, or leftover scaffolding from generation
|
|
78395
|
+
- PRs that touch services, libraries, infrastructure, and tests in a single change
|
|
78396
|
+
|
|
78397
|
+
Ask: Is there a simpler path to the same outcome? Would a new team member understand this
|
|
78398
|
+
without help? Can this function be split without losing meaning?
|
|
78399
|
+
|
|
78400
|
+
Action: Flag any function over ~40 lines. Require decomposition or written justification
|
|
78401
|
+
before merge.
|
|
78402
|
+
|
|
78403
|
+
---
|
|
78404
|
+
|
|
78405
|
+
## Pillar 2 — Type Drift (High Priority)
|
|
78406
|
+
|
|
78407
|
+
AI generates code in isolation from the broader type system. Type inconsistencies introduced
|
|
78408
|
+
here surface later as null pointer exceptions, silent failures, and cross-service contract
|
|
78409
|
+
mismatches. A University of Naples study of 500k+ samples (Aug 2025) confirmed these are the
|
|
78410
|
+
most reliably catchable issues via static analysis — meaning they should never reach review.
|
|
78411
|
+
|
|
78412
|
+
Look for:
|
|
78413
|
+
- \`any\` usage: defeats TypeScript entirely; AI reaches for it when uncertain
|
|
78414
|
+
- Unsafe \`as\` assertions: suppresses the compiler rather than satisfying it
|
|
78415
|
+
- Missing \`strictNullChecks\` compliance — null/undefined slipping through unchecked
|
|
78416
|
+
- Boundary drift: API endpoints returning different shapes across execution paths
|
|
78417
|
+
- Configuration drift: divergent \`tsconfig\` settings or ESLint rules added incrementally
|
|
78418
|
+
- Leaked internals: AI exposing implementation details that should be encapsulated
|
|
78419
|
+
|
|
78420
|
+
Ask: Are all return types and parameters explicitly typed? Are API contract types shared and
|
|
78421
|
+
stable? Does this match existing type conventions, or introduce a new pattern?
|
|
78422
|
+
|
|
78423
|
+
Action: \`strict: true\` in \`tsconfig.json\` is a hard gate. Any PR disabling strict settings
|
|
78424
|
+
requires explicit team sign-off.
|
|
78425
|
+
|
|
78426
|
+
---
|
|
78427
|
+
|
|
78428
|
+
## Pillar 3 — Duplication (High Priority)
|
|
78429
|
+
|
|
78430
|
+
GitClear's 2025 analysis of 211 million changed lines found duplicated code blocks grew 8x
|
|
78431
|
+
in one year, and copy/pasted code surpassed refactored code for the first time in history.
|
|
78432
|
+
OX Security found "Bugs Déjà-Vu" in 70–80% of AI codebases: identical bugs recurring in
|
|
78433
|
+
multiple locations because logic was never abstracted.
|
|
78434
|
+
|
|
78435
|
+
Look for:
|
|
78436
|
+
- Duplicate utility logic across files — each instance works, but no shared abstraction exists
|
|
78437
|
+
- "Vanilla Style" rebuilds: AI reconstructing functionality from scratch instead of using
|
|
78438
|
+
existing libraries, SDKs, or internal utilities (40–50% of AI code, OX Security)
|
|
78439
|
+
- Duplicated validation, auth checks, and input sanitization
|
|
78440
|
+
- Copy-pasted try/catch blocks instead of centralised error handling
|
|
78441
|
+
- New dependencies that the existing codebase already covers
|
|
78442
|
+
|
|
78443
|
+
Ask: Does an equivalent utility already exist? Is this logic duplicated anywhere else?
|
|
78444
|
+
Use AST-level search, not just grep.
|
|
78445
|
+
|
|
78446
|
+
Action: Require a codebase search before approving any new utility function. Run SonarQube,
|
|
78447
|
+
CodeClimate, or Codacy as a PR gate for duplication thresholds.
|
|
78448
|
+
|
|
78449
|
+
---
|
|
78450
|
+
|
|
78451
|
+
## Pillar 4 — Design Pattern Compliance (Standard Priority)
|
|
78452
|
+
|
|
78453
|
+
AI implements the prompt. It does not check the ADR log, existing service patterns, or
|
|
78454
|
+
architectural conventions. OX Security identified "By-The-Book Fixation" in 80–90% of AI
|
|
78455
|
+
code: rigid application of generic best practices, missing the better solution for this
|
|
78456
|
+
specific context.
|
|
78457
|
+
|
|
78458
|
+
Look for:
|
|
78459
|
+
- Pattern violations: raw \`fetch\` where an API service layer exists; new state patterns where
|
|
78460
|
+
a store convention is already established
|
|
78461
|
+
- SOLID violations:
|
|
78462
|
+
- Single Responsibility: see Pillar 1
|
|
78463
|
+
- Open/Closed: code requiring modification rather than extension to add new behaviour
|
|
78464
|
+
- Dependency Inversion: hard-coded dependencies instead of injection
|
|
78465
|
+
- No refactoring suggestions — AI never proposes that a feature should trigger a refactor
|
|
78466
|
+
- Context blindness: ignoring ADRs, versioning strategy, or team-level conventions
|
|
78467
|
+
|
|
78468
|
+
Ask: Does this follow the patterns in this area of the codebase? Can this be extended without
|
|
78469
|
+
modification? Are dependencies injected?
|
|
78470
|
+
|
|
78471
|
+
Action: Maintain a living \`ARCHITECTURE.md\` or ADR log. Pass it as context to AI tools before
|
|
78472
|
+
generation, not after.
|
|
78473
|
+
|
|
78474
|
+
---
|
|
78475
|
+
|
|
78476
|
+
## Pillar 5 — Security (Standard Priority)
|
|
78477
|
+
|
|
78478
|
+
45% of AI-generated code samples introduced OWASP Top 10 vulnerabilities in Veracode's 2025
|
|
78479
|
+
test of 100+ LLMs. CodeRabbit found AI code is 2.74x more likely to introduce XSS, 1.88x more
|
|
78480
|
+
likely to mishandle passwords, 1.82x more likely to implement insecure deserialization.
|
|
78481
|
+
OX Security calls this "insecure by dumbness" — not malicious, but structurally blind to
|
|
78482
|
+
security requirements that were not in the prompt.
|
|
78483
|
+
|
|
78484
|
+
Look for:
|
|
78485
|
+
- OWASP Top 10: injection (SQL, XSS, command), broken auth, insecure deserialization
|
|
78486
|
+
- "Worked on My Machine" syndrome (60–70% of AI code): missing environment awareness,
|
|
78487
|
+
hard-coded localhost references, assumed-present secrets
|
|
78488
|
+
- Missing auth/ownership checks — AI assumes the happy path; role gates rarely appear unprompted
|
|
78489
|
+
- Secrets, tokens, or credentials in source code
|
|
78490
|
+
- Deprecated API patterns from the model's training data
|
|
78491
|
+
- Excessive I/O (~8x human rate) and concurrency misuse (~2x human rate)
|
|
78492
|
+
|
|
78493
|
+
Ask: Are all inputs validated before use? Are auth checks present at every trust boundary?
|
|
78494
|
+
Does this code behave differently across environments?
|
|
78495
|
+
|
|
78496
|
+
Action: Run SAST tooling (Snyk, Semgrep, SonarQube) on every AI-generated PR as a CI gate.
|
|
78497
|
+
Manual review alone cannot keep pace with AI generation velocity.
|
|
78498
|
+
|
|
78499
|
+
---
|
|
78500
|
+
|
|
78501
|
+
## Pillar 6 — Test Quality (Standard Priority)
|
|
78502
|
+
|
|
78503
|
+
AI generates tests that look comprehensive but frequently are not. OX Security found "Fake
|
|
78504
|
+
Test Coverage" in 40–50% of AI codebases: inflated metrics, low signal. The failure mode is
|
|
78505
|
+
precise: AI tests its own assumptions, not the developer's intent. University of Naples (2025)
|
|
78506
|
+
confirmed that even code passing all functional benchmarks averaged 1.45–1.77 static issues
|
|
78507
|
+
per task.
|
|
78508
|
+
|
|
78509
|
+
Look for:
|
|
78510
|
+
- Tests that verify AI output is stable, not that it is correct by domain rules
|
|
78511
|
+
- Missing edge cases: empty inputs, boundary values, null handling, race conditions,
|
|
78512
|
+
business-rule violations
|
|
78513
|
+
- Coverage theater: tests that assert no exception was thrown and nothing more
|
|
78514
|
+
- No integration or contract tests — AI generates unit tests almost exclusively
|
|
78515
|
+
- Tests coupled to implementation: must be updated every time the code changes
|
|
78516
|
+
|
|
78517
|
+
Ask: Do these tests verify the domain intent? Would they catch a logic regression in the
|
|
78518
|
+
next PR? Are cross-service interactions tested?
|
|
78519
|
+
|
|
78520
|
+
Action: Test review is a separate pass from code review. Use mutation testing (Stryker,
|
|
78521
|
+
PITest) to validate whether tests catch real defects — coverage percentage is not sufficient.
|
|
78522
|
+
|
|
78523
|
+
---
|
|
78524
|
+
|
|
78525
|
+
## Pillar 7 — Ownership, Observability, Deployment (Standard Priority)
|
|
78526
|
+
|
|
78527
|
+
The most consistently missed category. ISACA's 2026 incident review found that the biggest
|
|
78528
|
+
AI failures of 2025 were organisational, not technical: weak controls and unclear ownership.
|
|
78529
|
+
Bright Security (2026) identified unclear ownership as one of the most dangerous patterns:
|
|
78530
|
+
code that works well enough that no one feels responsible for it. IBM's 2025 breach data found
|
|
78531
|
+
shadow AI added $670,000 average to breach costs.
|
|
78532
|
+
|
|
78533
|
+
Look for:
|
|
78534
|
+
- No named human owner — every AI-generated module needs someone who can explain it in a
|
|
78535
|
+
postmortem without reading it fresh
|
|
78536
|
+
- Missing structured logs, metrics emission, or tracing hooks
|
|
78537
|
+
- Swallowed exceptions: retry logic with no alerting; fallback paths invisible to operators
|
|
78538
|
+
- No environment-specific configuration, secrets management, or health check endpoints
|
|
78539
|
+
- Model versioning chaos: inconsistencies from team members using different AI tool versions
|
|
78540
|
+
- Shadow AI: code with no record of which tool or prompt produced it
|
|
78541
|
+
|
|
78542
|
+
Ask: Who owns this? Will production failures surface to operators? Does this behave
|
|
78543
|
+
differently across environments?
|
|
78544
|
+
|
|
78545
|
+
Action: Require every AI-generated module to have a named owner in CODEOWNERS. Add logging
|
|
78546
|
+
requirements to the PR template. Establish a team AI governance policy that tracks tools
|
|
78547
|
+
and model versions — treat this like any other dependency.
|
|
78548
|
+
|
|
78549
|
+
---
|
|
78550
|
+
|
|
78551
|
+
## Pillar 8 — Dead Code Elimination (Standard Priority)
|
|
78552
|
+
|
|
78553
|
+
AI generates code speculatively. It adds helper functions "just in case", creates abstractions
|
|
78554
|
+
for paths that never materialise, and leaves behind scaffolding from earlier generation
|
|
78555
|
+
attempts. GitClear's 2025 data showed a 75% increase in total code volume, much of it never
|
|
78556
|
+
executed. Dead code is not harmless — it misleads future readers, inflates bundle sizes, creates
|
|
78557
|
+
false positive search results, and adds surface area for bugs and security vulnerabilities
|
|
78558
|
+
in code that serves no purpose.
|
|
78559
|
+
|
|
78560
|
+
Look for:
|
|
78561
|
+
- Unreachable code: functions, methods, or branches that no call site ever invokes
|
|
78562
|
+
- Unused imports: modules imported but never referenced — common in AI-generated files
|
|
78563
|
+
- Commented-out code: old implementations left inline instead of being removed; version
|
|
78564
|
+
control already preserves history
|
|
78565
|
+
- Feature flags that are permanently off: conditional paths that were never enabled or have
|
|
78566
|
+
been superseded but not cleaned up
|
|
78567
|
+
- Orphaned configuration: environment variables, constants, or config entries with no consumer
|
|
78568
|
+
- Stale types and interfaces: type definitions for data shapes that no longer exist in the
|
|
78569
|
+
system
|
|
78570
|
+
- Unused dependencies: packages listed in \`package.json\` (or equivalent) that no source file
|
|
78571
|
+
imports
|
|
78572
|
+
- Vestigial error handling: catch blocks or fallback paths for conditions that can no longer
|
|
78573
|
+
occur due to upstream changes
|
|
78574
|
+
- Test helpers and fixtures for tests that have been deleted
|
|
78575
|
+
|
|
78576
|
+
Ask: Is every function called? Is every import used? Is every dependency exercised?
|
|
78577
|
+
Would removing this code change any observable behaviour?
|
|
78578
|
+
|
|
78579
|
+
Action: Run tree-shaking analysis and dead code detection tools (e.g., \`ts-prune\`,
|
|
78580
|
+
\`knip\`, \`depcheck\`, IDE unused-symbol highlighting) as part of CI. Treat dead code
|
|
78581
|
+
the same as duplication — it compounds over time and must be actively managed.
|
|
78582
|
+
|
|
78583
|
+
---
|
|
78584
|
+
|
|
78585
|
+
## Pillar 9 — Incomplete Implementations (Standard Priority)
|
|
78586
|
+
|
|
78587
|
+
AI tools often leave TODOs, stubs, "throw new Error('not implemented')", or placeholder
|
|
78588
|
+
returns when they hit uncertainty. The default assumption MUST be that these are bugs to fix,
|
|
78589
|
+
not features — unless the human explicitly requested a stub (e.g., scaffolding a future module).
|
|
78590
|
+
|
|
78591
|
+
Look for:
|
|
78592
|
+
- \`TODO\`, \`FIXME\`, \`XXX\`, \`HACK\` comments — especially without an assignee or ticket reference
|
|
78593
|
+
- Functions that throw "not implemented" / "unimplemented" errors
|
|
78594
|
+
- Empty function bodies or bodies that only return null/undefined/empty object as a placeholder
|
|
78595
|
+
- Switch/case branches with \`// handle later\` style comments
|
|
78596
|
+
- Conditional branches that silently fall through without handling a real case
|
|
78597
|
+
- Type definitions with fields marked \`any\` or \`unknown\` "to be refined later"
|
|
78598
|
+
- Tests with \`it.skip\`, \`xit\`, \`it.todo\` left in committed code without justification
|
|
78599
|
+
|
|
78600
|
+
Ask: Is every code path fully implemented? If a TODO exists, is there a tracked ticket and
|
|
78601
|
+
explicit reason it wasn't done now?
|
|
78602
|
+
|
|
78603
|
+
Action: Treat any TODO or stub as BLOCK unless the PR description or commit message explicitly
|
|
78604
|
+
justifies it (e.g., "scaffolding for follow-up PR #N"). Generated code with unprompted TODOs
|
|
78605
|
+
should be completed before merge, not after.
|
|
78606
|
+
|
|
78607
|
+
---
|
|
78608
|
+
|
|
78609
|
+
## Pillar 10 — Hallucinated Content & Magic Strings (Standard Priority)
|
|
78610
|
+
|
|
78611
|
+
AI generation frequently invents plausible-looking but incorrect values — API endpoints,
|
|
78612
|
+
env var names, library functions, config keys — and scatters magic strings/numbers across
|
|
78613
|
+
the codebase instead of consolidating them as named constants. Both fail at runtime or rot
|
|
78614
|
+
the codebase over time.
|
|
78615
|
+
|
|
78616
|
+
Look for:
|
|
78617
|
+
- Fabricated API endpoints, library functions, or package names that don't exist (verify against
|
|
78618
|
+
actual SDK docs / \`package.json\`)
|
|
78619
|
+
- Magic strings: status codes, role names, event types, feature flag keys appearing as inline
|
|
78620
|
+
literals across multiple files
|
|
78621
|
+
- Magic numbers: timeouts, limits, retry counts, port numbers without named constants
|
|
78622
|
+
- Placeholder content left in production paths: "lorem ipsum", "foo/bar", "example.com",
|
|
78623
|
+
"test@test.com"
|
|
78624
|
+
- Hardcoded URLs, file paths, or table/collection names that should come from config
|
|
78625
|
+
- Duplicated string literals that should be a single enum / const object
|
|
78626
|
+
- Configuration keys invented by the AI that don't match the project's actual config schema
|
|
78627
|
+
|
|
78628
|
+
Ask: Does every literal that carries domain meaning have a named home? Is every external
|
|
78629
|
+
reference (API, package, env var) verified to exist? Where SHOULD this constant live (entity
|
|
78630
|
+
enum, config module, shared constants file)?
|
|
78631
|
+
|
|
78632
|
+
Action: Consolidate magic literals into the canonical location for the codebase (typically
|
|
78633
|
+
enums alongside the relevant entity, or a dedicated constants module). For hallucinated
|
|
78634
|
+
references, treat as BLOCK — code that compiles against fictional APIs will fail in production.
|
|
78635
|
+
|
|
78636
|
+
---
|
|
78637
|
+
|
|
78638
|
+
## Output template
|
|
78639
|
+
|
|
78640
|
+
Use this format for every review. Do not skip sections.
|
|
78641
|
+
|
|
78642
|
+
\`\`\`
|
|
78643
|
+
## AI Code Review — [filename or PR title]
|
|
78644
|
+
|
|
78645
|
+
### Summary
|
|
78646
|
+
[2–3 sentences: overall quality signal, highest-risk area, recommended action]
|
|
78647
|
+
|
|
78648
|
+
### BLOCK — must fix before merge
|
|
78649
|
+
[List findings. Format: PILLAR | finding | why it matters | suggested fix]
|
|
78650
|
+
|
|
78651
|
+
### FLAG — author must respond
|
|
78652
|
+
[List findings. Same format.]
|
|
78653
|
+
|
|
78654
|
+
### Passed
|
|
78655
|
+
[Pillars or areas with no significant findings]
|
|
78656
|
+
|
|
78657
|
+
### Recommendation
|
|
78658
|
+
[ ] Approve [ ] Approve with flags addressed [ ] Decompose PR first [ ] Reject — rework required
|
|
78659
|
+
\`\`\``
|
|
78660
|
+
};
|
|
78661
|
+
});
|
|
77777
78662
|
|
|
77778
78663
|
// ../../services/backend/src/domain/usecase/skills/registry.ts
|
|
78664
|
+
var SKILLS_REGISTRY;
|
|
77779
78665
|
var init_registry3 = __esm(() => {
|
|
77780
78666
|
init_backlog();
|
|
77781
78667
|
init_code_review();
|
|
78668
|
+
SKILLS_REGISTRY = [backlogSkill, codeReviewSkill];
|
|
77782
78669
|
});
|
|
77783
78670
|
|
|
77784
78671
|
// ../../services/backend/prompts/sections/glossary.ts
|
|
78672
|
+
function formatGlossaryEntry(entry) {
|
|
78673
|
+
const skillNote = entry.linkedSkillId ? " (1 skill available)" : "";
|
|
78674
|
+
return [`- \`${entry.term}\`${skillNote}`, ` - ${entry.definition}`, ""];
|
|
78675
|
+
}
|
|
78676
|
+
function buildSkillsSection(cliEnvPrefix) {
|
|
78677
|
+
const lines = ["# Skills", ""];
|
|
78678
|
+
lines.push(`Run \`${cliEnvPrefix}chatroom skill list --chatroom-id=<id> --role=<role>\` to list all available skills.`);
|
|
78679
|
+
lines.push("");
|
|
78680
|
+
lines.push("## When to Activate Skills");
|
|
78681
|
+
lines.push("");
|
|
78682
|
+
lines.push("**Proactively activate skills** when your task matches their purpose:");
|
|
78683
|
+
for (const skill of SKILLS_REGISTRY) {
|
|
78684
|
+
lines.push(`- **${skill.skillId}**: ${skill.description}`);
|
|
78685
|
+
}
|
|
78686
|
+
lines.push("");
|
|
78687
|
+
lines.push("Don't wait for the user to ask — proactively activate the skill that matches the task.");
|
|
78688
|
+
return lines;
|
|
78689
|
+
}
|
|
78690
|
+
function getGlossarySection(params) {
|
|
78691
|
+
const cliEnvPrefix = getCliEnvPrefix(params.convexUrl);
|
|
78692
|
+
const lines = ["# Glossary", ""];
|
|
78693
|
+
const terms = params.nativeIntegration ? NATIVE_GLOSSARY_TERMS : GLOSSARY_TERMS;
|
|
78694
|
+
for (const entry of terms) {
|
|
78695
|
+
lines.push(...formatGlossaryEntry(entry));
|
|
78696
|
+
}
|
|
78697
|
+
if (params.compactSkills) {
|
|
78698
|
+
lines.push("# Skills", "");
|
|
78699
|
+
lines.push(`Run \`${cliEnvPrefix}chatroom skill list --chatroom-id=<id> --role=<role>\` to list available skills. Activate skills proactively when your task matches their purpose.`);
|
|
78700
|
+
} else {
|
|
78701
|
+
lines.push(...buildSkillsSection(cliEnvPrefix));
|
|
78702
|
+
}
|
|
78703
|
+
return createSection("glossary", "knowledge", lines.join(`
|
|
78704
|
+
`));
|
|
78705
|
+
}
|
|
77785
78706
|
var GLOSSARY_TERMS, NATIVE_GLOSSARY_TERMS;
|
|
77786
78707
|
var init_glossary = __esm(() => {
|
|
77787
78708
|
init_registry3();
|
|
@@ -77832,10 +78753,249 @@ var init_glossary = __esm(() => {
|
|
|
77832
78753
|
});
|
|
77833
78754
|
|
|
77834
78755
|
// ../../services/backend/prompts/cli/roles/builder.ts
|
|
78756
|
+
function getBuilderFlowMermaid(nativeIntegration, codeChangesTarget, questionTarget) {
|
|
78757
|
+
const handoffNodes = ` D --> E[Commit work]
|
|
78758
|
+
E --> F{Code changes?}
|
|
78759
|
+
F -->|yes| G[Hand off to **${codeChangesTarget}**]
|
|
78760
|
+
F -->|no| H[Hand off to **${questionTarget}**]`;
|
|
78761
|
+
if (nativeIntegration) {
|
|
78762
|
+
return `flowchart TD
|
|
78763
|
+
A([Start]) --> B[Receive task]
|
|
78764
|
+
B --> D[Implement changes]
|
|
78765
|
+
${handoffNodes}`;
|
|
78766
|
+
}
|
|
78767
|
+
return `flowchart TD
|
|
78768
|
+
A([Start]) --> B[Receive chatroom task]
|
|
78769
|
+
B --> D[Implement changes]
|
|
78770
|
+
${handoffNodes}`;
|
|
78771
|
+
}
|
|
78772
|
+
function getBuilderGuidance(params) {
|
|
78773
|
+
const {
|
|
78774
|
+
questionTarget: questionTargetParam,
|
|
78775
|
+
codeChangesTarget: codeChangesTargetParam,
|
|
78776
|
+
nativeIntegration
|
|
78777
|
+
} = params;
|
|
78778
|
+
const questionTarget = questionTargetParam ?? "user";
|
|
78779
|
+
const codeChangesTarget = codeChangesTargetParam ?? "planner";
|
|
78780
|
+
return `
|
|
78781
|
+
## Builder Operating Model
|
|
78782
|
+
|
|
78783
|
+
${getSessionContinuityLine(nativeIntegration)}
|
|
78784
|
+
|
|
78785
|
+
You are responsible for implementing code changes based on requirements.
|
|
78786
|
+
|
|
78787
|
+
**Typical Flow:**
|
|
78788
|
+
|
|
78789
|
+
\`\`\`mermaid
|
|
78790
|
+
${getBuilderFlowMermaid(nativeIntegration, codeChangesTarget, questionTarget)}
|
|
78791
|
+
\`\`\`
|
|
78792
|
+
|
|
78793
|
+
**Handoff Rules:**
|
|
78794
|
+
- **After code changes** → Hand off to \`${codeChangesTarget}\`
|
|
78795
|
+
- **For simple questions** → Can hand off directly to \`${questionTarget}\`
|
|
78796
|
+
⚠️ If \`${questionTarget}\` is the user: the user can ONLY see the handoff-to-user message — progress reports and all other messages are invisible to them. Write the handoff as a complete, self-contained document: include all relevant context, results, and next steps without assuming the user read any prior conversation.
|
|
78797
|
+
|
|
78798
|
+
**Implementation Guidelines:**
|
|
78799
|
+
- Write clean, maintainable, well-documented code
|
|
78800
|
+
- Follow established patterns and best practices from the codebase
|
|
78801
|
+
- Handle edge cases and error scenarios
|
|
78802
|
+
- Commit work with descriptive, atomic commit messages
|
|
78803
|
+
`;
|
|
78804
|
+
}
|
|
77835
78805
|
var init_builder = () => {};
|
|
78806
|
+
|
|
78807
|
+
// ../../services/backend/prompts/cli/sections/core-responsibilities.ts
|
|
78808
|
+
function getCoreResponsibilitiesSection(config3) {
|
|
78809
|
+
const qualityLine = config3.hasBuilder ? "If the user's requirements are not met, hand work back to the builder for rework." : "If the work doesn't meet requirements, revise it yourself before delivering.";
|
|
78810
|
+
return `**Core Responsibilities:**
|
|
78811
|
+
- **User Communication**: You are the ONLY role that communicates with the user. All responses to the user come through you.
|
|
78812
|
+
- **Handoff completeness**: The user can ONLY see the final handoff-to-\`user\` message. Write it as a complete, standalone document — do not reference prior messages or assume the user has context from earlier session text.
|
|
78813
|
+
- **Quality Accountability**: You are ultimately accountable for all work. ${qualityLine}`;
|
|
78814
|
+
}
|
|
78815
|
+
|
|
78816
|
+
// ../../services/backend/prompts/cli/sections/delegation-and-decomposition.ts
|
|
78817
|
+
function getDelegationAndDecompositionSection(config3) {
|
|
78818
|
+
if (!config3.hasBuilder) {
|
|
78819
|
+
return "";
|
|
78820
|
+
}
|
|
78821
|
+
return `**Delegation & Decomposition:**
|
|
78822
|
+
|
|
78823
|
+
Any task that requires code changes must be delegated to the builder — break it into small, focused slices and delegate them one at a time using a **Delegation Brief** (see **Delegation Guidelines** below).`;
|
|
78824
|
+
}
|
|
78825
|
+
|
|
78826
|
+
// ../../services/backend/prompts/cli/sections/delegation-guidelines.ts
|
|
78827
|
+
function buildCmdHelper(cliEnvPrefix, chatroomIdArg, roleArg) {
|
|
78828
|
+
return (subcommand) => `\`${cliEnvPrefix}chatroom ${subcommand} --chatroom-id=${chatroomIdArg} --role=${roleArg}\``;
|
|
78829
|
+
}
|
|
78830
|
+
function getDelegationBriefReference() {
|
|
78831
|
+
return "Use the **Handoff to `builder`** template in the task delivery `<handoff-templates>` section — follow that structure in your handoff message.";
|
|
78832
|
+
}
|
|
78833
|
+
function getSoloImplementationGuidelines(cmd, feedingNote) {
|
|
78834
|
+
return `**Implementation Guidelines:**
|
|
78835
|
+
|
|
78836
|
+
Break complex features into small, focused slices. For code review guidance, activate the \`code-review\` skill: ${cmd("skill activate code-review")}.
|
|
78837
|
+
|
|
78838
|
+
- Implement one slice at a time; each slice ≈ one focused review surface.
|
|
78839
|
+
- Review your own work before moving on; re-validate after rework.
|
|
78840
|
+
- ${feedingNote}.`;
|
|
78841
|
+
}
|
|
78842
|
+
function getBuilderDelegationGuidelines(cmd, feedingNote, delegationBriefRef) {
|
|
78843
|
+
return `**Delegation Guidelines:**
|
|
78844
|
+
|
|
78845
|
+
Break features into small, focused slices, then delegate them to the builder one at a time. For code review guidance, activate the \`code-review\` skill: ${cmd("skill activate code-review")}.
|
|
78846
|
+
|
|
78847
|
+
**Delegation rule:** If the task requires **any code changes** (new files, edits, deletions), you **must delegate to the builder** — regardless of how small the change is.
|
|
78848
|
+
|
|
78849
|
+
**Decision flow:**
|
|
78850
|
+
\`\`\`mermaid
|
|
78851
|
+
flowchart TD
|
|
78852
|
+
A[Receive task] --> B{Code changes needed?}
|
|
78853
|
+
B -->|Yes — any size| D[Write a Delegation Brief]
|
|
78854
|
+
D --> E[Hand off ONE slice to builder]
|
|
78855
|
+
E --> F[Review output]
|
|
78856
|
+
F -->|Not acceptable| G[Hand back with feedback]
|
|
78857
|
+
G --> E
|
|
78858
|
+
F -->|Acceptable| H{More slices?}
|
|
78859
|
+
H -->|Yes| E
|
|
78860
|
+
H -->|No| I[Deliver to user]
|
|
78861
|
+
B -->|No: question or clarification only| C[Answer directly → deliver to user]
|
|
78862
|
+
\`\`\`
|
|
78863
|
+
|
|
78864
|
+
**Default: delegate with a Delegation Brief.** ${delegationBriefRef}
|
|
78865
|
+
|
|
78866
|
+
**How to slice the work** — think about the phases a human engineer would actually go through to ship the work, then make each phase a slice. Some heuristics:
|
|
78867
|
+
|
|
78868
|
+
- **Each slice should name a concrete artifact** ("the X schema", "the Y entity", "the Z endpoint") — not a vague layer ("backend work", "implementation"). Weak builders fail when scope is unbounded.
|
|
78869
|
+
- **File-level detail, zero ambiguity.** List every file (full paths) and paste snippets until the builder cannot guess wrong — not vague layers ("backend work", "the component").
|
|
78870
|
+
- **You own technical design; the builder executes.** Per-file target code plus shared contracts in the brief — do not leave API shape for the builder to invent.
|
|
78871
|
+
- **Spell out what to avoid** — anti-patterns and recurring mistakes you have seen from builders on similar work (scope creep, wrong abstractions, forbidden refactors).
|
|
78872
|
+
- **One slice ≈ one focused review surface.** If you can't imagine reviewing it in one sitting, split it.
|
|
78873
|
+
- **Order by dependency**, not by team convention. A slice should be runnable/testable when its dependencies are done.
|
|
78874
|
+
- **Skip phases that don't apply** (e.g., no frontend for a backend-only change, no schema for a pure refactor).
|
|
78875
|
+
|
|
78876
|
+
**Code review:** For code-producing work, review before delivering. Activate the review framework with: ${cmd("skill activate code-review")}.
|
|
78877
|
+
|
|
78878
|
+
**Backlog items:** When the task originates from a backlog item, activate the backlog skill: ${cmd("skill activate backlog")}.
|
|
78879
|
+
|
|
78880
|
+
**If stuck:** After 2 failed rework attempts → step back, replan the slice, or deliver partial results with a clear explanation.
|
|
78881
|
+
|
|
78882
|
+
**Review loop:**
|
|
78883
|
+
- Review completed work before moving to the next slice.
|
|
78884
|
+
- Send back with specific feedback if requirements aren't met.
|
|
78885
|
+
- ${feedingNote}.`;
|
|
78886
|
+
}
|
|
78887
|
+
function getDelegationGuidelinesSection(config3, options) {
|
|
78888
|
+
const feedingNote = config3.hasBuilder ? "Feed slices to the builder incrementally — one at a time, not all at once" : "When implementing yourself, tackle one layer at a time — avoid large monolithic changes";
|
|
78889
|
+
const cliEnvPrefix = options?.cliEnvPrefix ?? "";
|
|
78890
|
+
const chatroomIdArg = options?.chatroomId ? `"${options.chatroomId}"` : "<id>";
|
|
78891
|
+
const roleArg = options?.role ? `"${options.role}"` : "<role>";
|
|
78892
|
+
const cmd = buildCmdHelper(cliEnvPrefix, chatroomIdArg, roleArg);
|
|
78893
|
+
if (!config3.hasBuilder) {
|
|
78894
|
+
return getSoloImplementationGuidelines(cmd, feedingNote);
|
|
78895
|
+
}
|
|
78896
|
+
return getBuilderDelegationGuidelines(cmd, feedingNote, getDelegationBriefReference());
|
|
78897
|
+
}
|
|
78898
|
+
|
|
77836
78899
|
// ../../services/backend/prompts/cli/sections/handoff-rules.ts
|
|
78900
|
+
function buildHandoffRuleLines(config3) {
|
|
78901
|
+
return [
|
|
78902
|
+
config3.hasBuilder ? "- **To delegate implementation** → Hand off to `builder` with clear requirements" : "- **To implement** → Work on the chatroom task directly (you are acting as implementer)",
|
|
78903
|
+
"- **To deliver to user** → Hand off to `user` with a complete, standalone summary\n ⚠️ The user can ONLY see the handoff-to-user message — progress reports and all other messages are invisible to them. Write the handoff as a self-contained document: include all relevant context, results, and next steps without assuming the user read any prior conversation.",
|
|
78904
|
+
config3.hasBuilder ? "- **For rework** → Hand off back to `builder` with specific feedback on what needs to change" : "- **For rework** → Revise your implementation directly and re-validate"
|
|
78905
|
+
].join(`
|
|
78906
|
+
`);
|
|
78907
|
+
}
|
|
78908
|
+
function getHandoffRulesSection(config3, nativeIntegration) {
|
|
78909
|
+
const continuityRule = getHandoffContinuityRule(nativeIntegration);
|
|
78910
|
+
const continuityBlock = continuityRule ? `${continuityRule}
|
|
78911
|
+
|
|
78912
|
+
` : "";
|
|
78913
|
+
return `**Handoff Rules:**
|
|
78914
|
+
|
|
78915
|
+
${continuityBlock}${buildHandoffRuleLines(config3)}`;
|
|
78916
|
+
}
|
|
77837
78917
|
var init_handoff_rules = () => {};
|
|
78918
|
+
|
|
78919
|
+
// ../../services/backend/prompts/cli/sections/when-work-comes-back.ts
|
|
78920
|
+
function getWhenWorkComesBackSection(config3) {
|
|
78921
|
+
const reworkLine = config3.hasBuilder ? "3. If requirements are NOT met → hand back to `builder` for rework" : "3. If requirements are NOT met → revise your own implementation and re-validate";
|
|
78922
|
+
return `**When you receive work back from team members:**
|
|
78923
|
+
1. Review the completed work against the original user request
|
|
78924
|
+
2. If requirements are met → deliver to \`user\`
|
|
78925
|
+
${reworkLine}
|
|
78926
|
+
4. **No ceremonial handoffs** — never hand back just to acknowledge, thank, or echo receipt. A handback to the sender is only valid when it carries concrete rework feedback (step 3). Handoffs to \`user\` are reserved for the final deliverable from the entry-point role.`;
|
|
78927
|
+
}
|
|
78928
|
+
|
|
78929
|
+
// ../../services/backend/prompts/cli/sections/team-composition.ts
|
|
78930
|
+
function getTeamCompositionSection(teamMembers) {
|
|
78931
|
+
const isSoloRole = teamMembers.length === 1 && teamMembers[0]?.toLowerCase() === "solo";
|
|
78932
|
+
const nonPlannerMembers = teamMembers.filter((r) => r.toLowerCase() !== "planner");
|
|
78933
|
+
if (isSoloRole || nonPlannerMembers.length === 0) {
|
|
78934
|
+
return `**Team composition:** Solo team — you handle planning and implementation yourself.`;
|
|
78935
|
+
}
|
|
78936
|
+
const roleList = nonPlannerMembers.map((r) => `\`${r}\``).join(", ");
|
|
78937
|
+
return `**Team composition:** Duo team — you coordinate with ${roleList} for implementation.
|
|
78938
|
+
|
|
78939
|
+
**Agent presence:** This prompt does **not** tell you who is online. Other agents may be offline. Delegate code-changing work by handing off when appropriate; do not infer availability from team configuration or prior chat history.`;
|
|
78940
|
+
}
|
|
78941
|
+
|
|
77838
78942
|
// ../../services/backend/prompts/cli/sections/operating-model.ts
|
|
78943
|
+
function getTaskIntakeNodes(nativeIntegration) {
|
|
78944
|
+
if (nativeIntegration) {
|
|
78945
|
+
return ` A([Start]) --> B[Receive user message]
|
|
78946
|
+
B --> E[Decompose into phases]`;
|
|
78947
|
+
}
|
|
78948
|
+
return ` A([Start]) --> B[Receive chatroom task from get-next-task]
|
|
78949
|
+
B --> E[Decompose into phases]`;
|
|
78950
|
+
}
|
|
78951
|
+
function getOperatingModelSection(config3, nativeIntegration) {
|
|
78952
|
+
if (config3.hasBuilder) {
|
|
78953
|
+
return getPlannerPlusBuilderOperatingModel(nativeIntegration);
|
|
78954
|
+
}
|
|
78955
|
+
return getPlannerSoloOperatingModel(nativeIntegration);
|
|
78956
|
+
}
|
|
78957
|
+
function getPlannerPlusBuilderOperatingModel(nativeIntegration) {
|
|
78958
|
+
const footer = getOperatingModelLoopFooter(nativeIntegration);
|
|
78959
|
+
const delegationNote = nativeIntegration ? getNativePlannerDelegationWaitNote() : "After delegating to the builder, hand off and wait for work to return.";
|
|
78960
|
+
return `**Operating model: Planner + Builder**
|
|
78961
|
+
|
|
78962
|
+
${delegationNote}
|
|
78963
|
+
|
|
78964
|
+
\`\`\`mermaid
|
|
78965
|
+
flowchart TD
|
|
78966
|
+
${getTaskIntakeNodes(nativeIntegration)}
|
|
78967
|
+
E --> F[Delegate ONE phase to builder]
|
|
78968
|
+
F --> G[Builder completes phase]
|
|
78969
|
+
G --> H[Builder hands off to planner]
|
|
78970
|
+
H --> I[Review builder output]
|
|
78971
|
+
I --> J{phase acceptable?}
|
|
78972
|
+
J -->|no| K[Hand back to builder with feedback]
|
|
78973
|
+
K --> F
|
|
78974
|
+
J -->|yes| L{more phases?}
|
|
78975
|
+
L -->|yes| F
|
|
78976
|
+
L -->|no| O[Deliver final result to user]
|
|
78977
|
+
O --> P[${footer}] --> B
|
|
78978
|
+
\`\`\``;
|
|
78979
|
+
}
|
|
78980
|
+
function getPlannerSoloOperatingModel(nativeIntegration) {
|
|
78981
|
+
const continueStep = nativeIntegration ? "Hand off when complete" : "Run `get-next-task` to continue the session (Level A continues after Level B completes)";
|
|
78982
|
+
const intakeSteps = nativeIntegration ? `1. Receive user message
|
|
78983
|
+
2. Plan and implement` : `1. Receive chatroom task from get-next-task
|
|
78984
|
+
2. Plan and implement`;
|
|
78985
|
+
if (nativeIntegration) {
|
|
78986
|
+
return `**Operating model: Planner Solo**
|
|
78987
|
+
|
|
78988
|
+
${intakeSteps}
|
|
78989
|
+
3. Deliver to **user**
|
|
78990
|
+
4. ${continueStep}`;
|
|
78991
|
+
}
|
|
78992
|
+
return `**Operating model: Planner Solo**
|
|
78993
|
+
|
|
78994
|
+
${intakeSteps}
|
|
78995
|
+
3. Review your own work for quality
|
|
78996
|
+
4. Deliver to **user**
|
|
78997
|
+
5. ${continueStep}`;
|
|
78998
|
+
}
|
|
77839
78999
|
var init_operating_model = () => {};
|
|
77840
79000
|
|
|
77841
79001
|
// ../../services/backend/prompts/cli/sections/index.ts
|
|
@@ -77845,17 +79005,126 @@ var init_sections = __esm(() => {
|
|
|
77845
79005
|
});
|
|
77846
79006
|
|
|
77847
79007
|
// ../../services/backend/prompts/cli/roles/planner.ts
|
|
79008
|
+
function getPlannerGuidance(params) {
|
|
79009
|
+
const { convexUrl, teamRoles, chatroomId, role, nativeIntegration } = params;
|
|
79010
|
+
const cliEnvPrefix = getCliEnvPrefix(convexUrl);
|
|
79011
|
+
const members = teamRoles;
|
|
79012
|
+
const hasBuilder = members.some((r) => r.toLowerCase() === "builder");
|
|
79013
|
+
const teamConfig = { hasBuilder };
|
|
79014
|
+
return `## Planner Operating Model
|
|
79015
|
+
|
|
79016
|
+
${getSessionContinuityLine(nativeIntegration)}
|
|
79017
|
+
|
|
79018
|
+
You are the team coordinator and the **single point of contact** for the user.
|
|
79019
|
+
|
|
79020
|
+
${getTeamCompositionSection(members)}
|
|
79021
|
+
|
|
79022
|
+
${getOperatingModelSection(teamConfig, nativeIntegration)}
|
|
79023
|
+
|
|
79024
|
+
${getCoreResponsibilitiesSection(teamConfig)}
|
|
79025
|
+
|
|
79026
|
+
${getDelegationAndDecompositionSection(teamConfig)}
|
|
79027
|
+
|
|
79028
|
+
${getDelegationGuidelinesSection(teamConfig, { cliEnvPrefix, chatroomId, role })}
|
|
79029
|
+
|
|
79030
|
+
${getHandoffRulesSection(teamConfig, nativeIntegration)}
|
|
79031
|
+
|
|
79032
|
+
${getWhenWorkComesBackSection(teamConfig)}`;
|
|
79033
|
+
}
|
|
77848
79034
|
var init_planner = __esm(() => {
|
|
77849
79035
|
init_env();
|
|
77850
79036
|
init_sections();
|
|
77851
79037
|
});
|
|
77852
79038
|
|
|
77853
79039
|
// ../../services/backend/prompts/teams/solo/prompts/solo.ts
|
|
79040
|
+
function getSoloGuidance(ctx) {
|
|
79041
|
+
const { teamRoles, nativeIntegration } = ctx;
|
|
79042
|
+
return `## Solo Operating Model
|
|
79043
|
+
|
|
79044
|
+
${getSessionContinuityLine(nativeIntegration)}
|
|
79045
|
+
|
|
79046
|
+
You are an autonomous agent responsible for BOTH planning and implementing chatroom tasks independently.
|
|
79047
|
+
|
|
79048
|
+
**Solo Team Context:**
|
|
79049
|
+
- You are the ONLY team member — you plan, implement, and deliver
|
|
79050
|
+
- You communicate directly with the user (single point of contact)
|
|
79051
|
+
- There is no separate builder or planner — you fill all roles
|
|
79052
|
+
- You hand off directly to the user when work is complete
|
|
79053
|
+
|
|
79054
|
+
${getTeamCompositionSection(teamRoles)}
|
|
79055
|
+
|
|
79056
|
+
${getPlannerSoloOperatingModel(nativeIntegration)}
|
|
79057
|
+
|
|
79058
|
+
${getCoreResponsibilitiesSection(SOLO_TEAM_CONFIG)}
|
|
79059
|
+
|
|
79060
|
+
**Implementation Guidelines:**
|
|
79061
|
+
- Write clean, maintainable, well-documented code
|
|
79062
|
+
- Follow established patterns and best practices from the codebase
|
|
79063
|
+
- Handle edge cases and error scenarios
|
|
79064
|
+
- Commit work with descriptive, atomic commit messages
|
|
79065
|
+
|
|
79066
|
+
${getHandoffRulesSection(SOLO_TEAM_CONFIG, nativeIntegration)}
|
|
79067
|
+
|
|
79068
|
+
${getWhenWorkComesBackSection(SOLO_TEAM_CONFIG)}`;
|
|
79069
|
+
}
|
|
79070
|
+
var SOLO_TEAM_CONFIG;
|
|
77854
79071
|
var init_solo = __esm(() => {
|
|
77855
79072
|
init_sections();
|
|
79073
|
+
SOLO_TEAM_CONFIG = { hasBuilder: false };
|
|
77856
79074
|
});
|
|
77857
79075
|
|
|
77858
79076
|
// ../../services/backend/prompts/cli/roles/fromContext.ts
|
|
79077
|
+
function toBuilderParams(ctx) {
|
|
79078
|
+
return {
|
|
79079
|
+
role: ctx.role,
|
|
79080
|
+
teamRoles: ctx.teamRoles,
|
|
79081
|
+
isEntryPoint: ctx.isEntryPoint,
|
|
79082
|
+
convexUrl: ctx.convexUrl,
|
|
79083
|
+
nativeIntegration: ctx.nativeIntegration
|
|
79084
|
+
};
|
|
79085
|
+
}
|
|
79086
|
+
function toPlannerParams(ctx) {
|
|
79087
|
+
return {
|
|
79088
|
+
role: ctx.role,
|
|
79089
|
+
teamRoles: ctx.teamRoles,
|
|
79090
|
+
isEntryPoint: ctx.isEntryPoint,
|
|
79091
|
+
convexUrl: ctx.convexUrl,
|
|
79092
|
+
chatroomId: ctx.chatroomId,
|
|
79093
|
+
nativeIntegration: ctx.nativeIntegration
|
|
79094
|
+
};
|
|
79095
|
+
}
|
|
79096
|
+
function getBaseBuilderGuidanceFromContext(ctx) {
|
|
79097
|
+
return getBuilderGuidance(toBuilderParams(ctx));
|
|
79098
|
+
}
|
|
79099
|
+
function toSoloParams(ctx) {
|
|
79100
|
+
return {
|
|
79101
|
+
role: ctx.role,
|
|
79102
|
+
teamRoles: ctx.teamRoles,
|
|
79103
|
+
isEntryPoint: ctx.isEntryPoint,
|
|
79104
|
+
convexUrl: ctx.convexUrl,
|
|
79105
|
+
chatroomId: ctx.chatroomId,
|
|
79106
|
+
nativeIntegration: ctx.nativeIntegration
|
|
79107
|
+
};
|
|
79108
|
+
}
|
|
79109
|
+
function getSoloGuidanceFromContext(ctx) {
|
|
79110
|
+
return getSoloGuidance(toSoloParams(ctx));
|
|
79111
|
+
}
|
|
79112
|
+
function getBasePlannerGuidanceFromContext(ctx) {
|
|
79113
|
+
return getPlannerGuidance(toPlannerParams(ctx));
|
|
79114
|
+
}
|
|
79115
|
+
function getBaseRoleGuidanceFromContext(ctx) {
|
|
79116
|
+
const normalizedRole = ctx.role.toLowerCase();
|
|
79117
|
+
if (normalizedRole === "planner") {
|
|
79118
|
+
return getBasePlannerGuidanceFromContext(ctx);
|
|
79119
|
+
}
|
|
79120
|
+
if (normalizedRole === "builder") {
|
|
79121
|
+
return getBaseBuilderGuidanceFromContext(ctx);
|
|
79122
|
+
}
|
|
79123
|
+
if (normalizedRole === "solo") {
|
|
79124
|
+
return getSoloGuidanceFromContext(ctx);
|
|
79125
|
+
}
|
|
79126
|
+
return "";
|
|
79127
|
+
}
|
|
77859
79128
|
var init_fromContext = __esm(() => {
|
|
77860
79129
|
init_builder();
|
|
77861
79130
|
init_planner();
|
|
@@ -77863,32 +79132,229 @@ var init_fromContext = __esm(() => {
|
|
|
77863
79132
|
});
|
|
77864
79133
|
|
|
77865
79134
|
// ../../services/backend/prompts/teams/duo/prompts/builder.ts
|
|
79135
|
+
function getBuilderGuidance2(ctx) {
|
|
79136
|
+
return `
|
|
79137
|
+
**Duo Team Context:**
|
|
79138
|
+
- You work with a planner who coordinates work and communicates with the user
|
|
79139
|
+
- You do NOT communicate directly with the user — hand off to the planner instead
|
|
79140
|
+
- Focus on implementation; the planner handles user communication and delivery
|
|
79141
|
+
- After completing work, hand off back to planner
|
|
79142
|
+
- **NEVER hand off directly to \`user\`** — always go through the planner
|
|
79143
|
+
|
|
79144
|
+
${getBuilderGuidance({ ...ctx, questionTarget: "planner", codeChangesTarget: "planner" })}
|
|
79145
|
+
`;
|
|
79146
|
+
}
|
|
77866
79147
|
var init_builder2 = __esm(() => {
|
|
77867
79148
|
init_builder();
|
|
77868
79149
|
});
|
|
77869
79150
|
|
|
77870
79151
|
// ../../services/backend/prompts/cli/roles/planner-guidance-context.ts
|
|
79152
|
+
function getPlannerGuidanceContext(ctx) {
|
|
79153
|
+
const { convexUrl, teamRoles, chatroomId, role } = ctx;
|
|
79154
|
+
const cliEnvPrefix = getCliEnvPrefix(convexUrl);
|
|
79155
|
+
const members = teamRoles;
|
|
79156
|
+
return {
|
|
79157
|
+
...ctx,
|
|
79158
|
+
cliEnvPrefix,
|
|
79159
|
+
members,
|
|
79160
|
+
chatroomId,
|
|
79161
|
+
role
|
|
79162
|
+
};
|
|
79163
|
+
}
|
|
77871
79164
|
var init_planner_guidance_context = __esm(() => {
|
|
77872
79165
|
init_env();
|
|
77873
79166
|
});
|
|
77874
79167
|
|
|
77875
79168
|
// ../../services/backend/prompts/teams/duo/prompts/planner.ts
|
|
79169
|
+
function getPlannerGuidance2(ctx) {
|
|
79170
|
+
const { nativeIntegration, members, cliEnvPrefix, chatroomId, role } = getPlannerGuidanceContext(ctx);
|
|
79171
|
+
const operatingModelGuidance = getPlannerPlusBuilderOperatingModel(nativeIntegration);
|
|
79172
|
+
return `## Planner Operating Model
|
|
79173
|
+
|
|
79174
|
+
${getSessionContinuityLine(nativeIntegration)}
|
|
79175
|
+
|
|
79176
|
+
You are the team coordinator and the **single point of contact** for the user.
|
|
79177
|
+
|
|
79178
|
+
**Duo Team Context:**
|
|
79179
|
+
- You are the entry point — you communicate directly with the user
|
|
79180
|
+
- You coordinate with the builder for implementation tasks
|
|
79181
|
+
- You are ultimately accountable for all work quality
|
|
79182
|
+
- After reviewing builder output, deliver results to the user
|
|
79183
|
+
- **Only you can hand off to \`user\`**
|
|
79184
|
+
|
|
79185
|
+
${getTeamCompositionSection(members)}
|
|
79186
|
+
|
|
79187
|
+
${operatingModelGuidance}
|
|
79188
|
+
|
|
79189
|
+
${getCoreResponsibilitiesSection(DUO_TEAM_CONFIG)}
|
|
79190
|
+
|
|
79191
|
+
${getDelegationAndDecompositionSection(DUO_TEAM_CONFIG)}
|
|
79192
|
+
|
|
79193
|
+
${getDelegationGuidelinesSection(DUO_TEAM_CONFIG, {
|
|
79194
|
+
cliEnvPrefix,
|
|
79195
|
+
chatroomId,
|
|
79196
|
+
role
|
|
79197
|
+
})}
|
|
79198
|
+
|
|
79199
|
+
${getHandoffRulesSection(DUO_TEAM_CONFIG, nativeIntegration)}
|
|
79200
|
+
|
|
79201
|
+
${getWhenWorkComesBackSection(DUO_TEAM_CONFIG)}`;
|
|
79202
|
+
}
|
|
79203
|
+
var DUO_TEAM_CONFIG;
|
|
77876
79204
|
var init_planner2 = __esm(() => {
|
|
77877
79205
|
init_planner_guidance_context();
|
|
77878
79206
|
init_sections();
|
|
79207
|
+
DUO_TEAM_CONFIG = { hasBuilder: true };
|
|
77879
79208
|
});
|
|
77880
79209
|
|
|
77881
79210
|
// ../../services/backend/prompts/teams/duo/prompts/fromContext.ts
|
|
79211
|
+
function toDuoBuilderParams(ctx) {
|
|
79212
|
+
return {
|
|
79213
|
+
role: ctx.role,
|
|
79214
|
+
teamRoles: ctx.teamRoles,
|
|
79215
|
+
isEntryPoint: ctx.isEntryPoint,
|
|
79216
|
+
convexUrl: ctx.convexUrl,
|
|
79217
|
+
nativeIntegration: ctx.nativeIntegration
|
|
79218
|
+
};
|
|
79219
|
+
}
|
|
79220
|
+
function toDuoPlannerParams(ctx) {
|
|
79221
|
+
return {
|
|
79222
|
+
role: ctx.role,
|
|
79223
|
+
teamRoles: ctx.teamRoles,
|
|
79224
|
+
isEntryPoint: ctx.isEntryPoint,
|
|
79225
|
+
convexUrl: ctx.convexUrl,
|
|
79226
|
+
chatroomId: ctx.chatroomId,
|
|
79227
|
+
nativeIntegration: ctx.nativeIntegration
|
|
79228
|
+
};
|
|
79229
|
+
}
|
|
79230
|
+
function getDuoBuilderGuidanceFromContext(ctx) {
|
|
79231
|
+
return getBuilderGuidance2(toDuoBuilderParams(ctx));
|
|
79232
|
+
}
|
|
79233
|
+
function getDuoPlannerGuidanceFromContext(ctx) {
|
|
79234
|
+
return getPlannerGuidance2(toDuoPlannerParams(ctx));
|
|
79235
|
+
}
|
|
79236
|
+
function getDuoRoleGuidanceFromContext(ctx) {
|
|
79237
|
+
const normalizedRole = ctx.role.toLowerCase();
|
|
79238
|
+
if (normalizedRole === "planner") {
|
|
79239
|
+
return getDuoPlannerGuidanceFromContext(ctx);
|
|
79240
|
+
}
|
|
79241
|
+
if (normalizedRole === "builder") {
|
|
79242
|
+
return getDuoBuilderGuidanceFromContext(ctx);
|
|
79243
|
+
}
|
|
79244
|
+
return null;
|
|
79245
|
+
}
|
|
77882
79246
|
var init_fromContext2 = __esm(() => {
|
|
77883
79247
|
init_builder2();
|
|
77884
79248
|
init_planner2();
|
|
77885
79249
|
});
|
|
77886
79250
|
|
|
77887
79251
|
// ../../services/backend/prompts/teams/solo/prompts/fromContext.ts
|
|
79252
|
+
function toSoloParams2(ctx) {
|
|
79253
|
+
return {
|
|
79254
|
+
role: ctx.role,
|
|
79255
|
+
teamRoles: ctx.teamRoles,
|
|
79256
|
+
isEntryPoint: ctx.isEntryPoint,
|
|
79257
|
+
convexUrl: ctx.convexUrl,
|
|
79258
|
+
chatroomId: ctx.chatroomId,
|
|
79259
|
+
nativeIntegration: ctx.nativeIntegration
|
|
79260
|
+
};
|
|
79261
|
+
}
|
|
79262
|
+
function getSoloGuidanceFromContext2(ctx) {
|
|
79263
|
+
return getSoloGuidance(toSoloParams2(ctx));
|
|
79264
|
+
}
|
|
79265
|
+
function getSoloRoleGuidanceFromContext(ctx) {
|
|
79266
|
+
const normalizedRole = ctx.role.toLowerCase();
|
|
79267
|
+
if (normalizedRole === "solo") {
|
|
79268
|
+
return getSoloGuidanceFromContext2(ctx);
|
|
79269
|
+
}
|
|
79270
|
+
return null;
|
|
79271
|
+
}
|
|
77888
79272
|
var init_fromContext3 = __esm(() => {
|
|
77889
79273
|
init_solo();
|
|
77890
79274
|
});
|
|
79275
|
+
|
|
79276
|
+
// ../../services/backend/src/domain/entities/team.ts
|
|
79277
|
+
function toTeam(chatroom) {
|
|
79278
|
+
if (!chatroom.teamId || !chatroom.teamRoles || chatroom.teamRoles.length === 0) {
|
|
79279
|
+
return null;
|
|
79280
|
+
}
|
|
79281
|
+
const entryPoint = chatroom.teamEntryPoint ?? chatroom.teamRoles[0];
|
|
79282
|
+
if (!entryPoint)
|
|
79283
|
+
return null;
|
|
79284
|
+
return {
|
|
79285
|
+
id: chatroom.teamId,
|
|
79286
|
+
name: chatroom.teamName ?? chatroom.teamId,
|
|
79287
|
+
roles: chatroom.teamRoles,
|
|
79288
|
+
entryPoint
|
|
79289
|
+
};
|
|
79290
|
+
}
|
|
79291
|
+
function getTeamEntryPoint(team) {
|
|
79292
|
+
return team.teamEntryPoint ?? team.teamRoles?.[0] ?? null;
|
|
79293
|
+
}
|
|
79294
|
+
|
|
77891
79295
|
// ../../services/backend/prompts/selector-context.ts
|
|
79296
|
+
function detectTeamTypeByName(teamName) {
|
|
79297
|
+
const normalizedName = (teamName || "").toLowerCase();
|
|
79298
|
+
if (normalizedName.includes("solo"))
|
|
79299
|
+
return "solo";
|
|
79300
|
+
if (normalizedName.includes("duo"))
|
|
79301
|
+
return "duo";
|
|
79302
|
+
return null;
|
|
79303
|
+
}
|
|
79304
|
+
function isSoloTeamByRoles(teamRoles) {
|
|
79305
|
+
return teamRoles.some((r) => r.toLowerCase() === "solo") && teamRoles.length === 1;
|
|
79306
|
+
}
|
|
79307
|
+
function isDuoTeamByRoles(teamRoles) {
|
|
79308
|
+
const hasPlanner = teamRoles.some((r) => r.toLowerCase() === "planner");
|
|
79309
|
+
const hasBuilder = teamRoles.some((r) => r.toLowerCase() === "builder");
|
|
79310
|
+
return hasPlanner && hasBuilder && teamRoles.length === 2;
|
|
79311
|
+
}
|
|
79312
|
+
function detectTeamType(teamRoles, teamName) {
|
|
79313
|
+
const byName = detectTeamTypeByName(teamName);
|
|
79314
|
+
if (byName)
|
|
79315
|
+
return byName;
|
|
79316
|
+
if (isSoloTeamByRoles(teamRoles))
|
|
79317
|
+
return "solo";
|
|
79318
|
+
if (isDuoTeamByRoles(teamRoles))
|
|
79319
|
+
return "duo";
|
|
79320
|
+
return "unknown";
|
|
79321
|
+
}
|
|
79322
|
+
function buildSelectorContext(params) {
|
|
79323
|
+
const entryPoint = getTeamEntryPoint({ teamEntryPoint: params.teamEntryPoint, teamRoles: params.teamRoles }) ?? "builder";
|
|
79324
|
+
const teamConfig = toTeam({
|
|
79325
|
+
teamId: params.teamId,
|
|
79326
|
+
teamName: params.teamName,
|
|
79327
|
+
teamRoles: params.teamRoles,
|
|
79328
|
+
teamEntryPoint: params.teamEntryPoint
|
|
79329
|
+
}) ?? undefined;
|
|
79330
|
+
return {
|
|
79331
|
+
role: params.role,
|
|
79332
|
+
team: detectTeamType(params.teamRoles, params.teamName),
|
|
79333
|
+
teamConfig,
|
|
79334
|
+
workflow: params.workflow,
|
|
79335
|
+
teamRoles: params.teamRoles,
|
|
79336
|
+
isEntryPoint: params.role.toLowerCase() === entryPoint.toLowerCase(),
|
|
79337
|
+
convexUrl: params.convexUrl,
|
|
79338
|
+
chatroomId: params.chatroomId,
|
|
79339
|
+
agentType: params.agentType ?? "unset",
|
|
79340
|
+
nativeIntegration: params.nativeIntegration
|
|
79341
|
+
};
|
|
79342
|
+
}
|
|
79343
|
+
function getRoleGuidanceFromContext(ctx) {
|
|
79344
|
+
try {
|
|
79345
|
+
if (ctx.team === "solo") {
|
|
79346
|
+
const result = getSoloRoleGuidanceFromContext(ctx);
|
|
79347
|
+
if (result !== null)
|
|
79348
|
+
return result;
|
|
79349
|
+
}
|
|
79350
|
+
if (ctx.team === "duo") {
|
|
79351
|
+
const result = getDuoRoleGuidanceFromContext(ctx);
|
|
79352
|
+
if (result !== null)
|
|
79353
|
+
return result;
|
|
79354
|
+
}
|
|
79355
|
+
} catch {}
|
|
79356
|
+
return getBaseRoleGuidanceFromContext(ctx);
|
|
79357
|
+
}
|
|
77892
79358
|
var init_selector_context = __esm(() => {
|
|
77893
79359
|
init_fromContext();
|
|
77894
79360
|
init_fromContext2();
|
|
@@ -77896,19 +79362,151 @@ var init_selector_context = __esm(() => {
|
|
|
77896
79362
|
});
|
|
77897
79363
|
|
|
77898
79364
|
// ../../services/backend/prompts/sections/role-guidance.ts
|
|
79365
|
+
function getRoleGuidanceSection(ctx) {
|
|
79366
|
+
const content = getRoleGuidanceFromContext(ctx);
|
|
79367
|
+
return createSection("role-guidance", "knowledge", content);
|
|
79368
|
+
}
|
|
77899
79369
|
var init_role_guidance = __esm(() => {
|
|
77900
79370
|
init_selector_context();
|
|
77901
79371
|
});
|
|
77902
79372
|
|
|
77903
79373
|
// ../../services/backend/prompts/templates.ts
|
|
77904
|
-
|
|
79374
|
+
function getRoleTemplate(role) {
|
|
79375
|
+
const normalizedRole = role.toLowerCase();
|
|
79376
|
+
const template = ROLE_TEMPLATES[normalizedRole];
|
|
79377
|
+
if (template) {
|
|
79378
|
+
return template;
|
|
79379
|
+
}
|
|
79380
|
+
return {
|
|
79381
|
+
role,
|
|
79382
|
+
title: role.charAt(0).toUpperCase() + role.slice(1),
|
|
79383
|
+
description: `You are participating as the ${role} in this collaborative workflow.`,
|
|
79384
|
+
responsibilities: [
|
|
79385
|
+
"Complete tasks assigned to your role",
|
|
79386
|
+
"Communicate clearly with other participants",
|
|
79387
|
+
"Hand off to the next appropriate role when done"
|
|
79388
|
+
],
|
|
79389
|
+
defaultHandoffTarget: "user"
|
|
79390
|
+
};
|
|
79391
|
+
}
|
|
79392
|
+
var ROLE_TEMPLATES;
|
|
79393
|
+
var init_templates = __esm(() => {
|
|
79394
|
+
ROLE_TEMPLATES = {
|
|
79395
|
+
builder: {
|
|
79396
|
+
role: "builder",
|
|
79397
|
+
title: "Builder",
|
|
79398
|
+
description: "You are the implementer responsible for writing code and building solutions.",
|
|
79399
|
+
responsibilities: [
|
|
79400
|
+
"Implement solutions based on requirements",
|
|
79401
|
+
"Write clean, maintainable, well-documented code",
|
|
79402
|
+
"Follow established patterns and best practices",
|
|
79403
|
+
"Handle edge cases and error scenarios",
|
|
79404
|
+
"Provide clear summaries of what was built"
|
|
79405
|
+
],
|
|
79406
|
+
defaultHandoffTarget: "planner"
|
|
79407
|
+
},
|
|
79408
|
+
planner: {
|
|
79409
|
+
role: "planner",
|
|
79410
|
+
title: "Planner",
|
|
79411
|
+
description: "You are the team coordinator responsible for user communication, task decomposition, and team management.",
|
|
79412
|
+
responsibilities: [
|
|
79413
|
+
"Communicate with the user as the single point of contact",
|
|
79414
|
+
"Decompose complex tasks into actionable work items",
|
|
79415
|
+
"Delegate work to available team members",
|
|
79416
|
+
"Review completed work against user requirements",
|
|
79417
|
+
"Manage the backlog and prioritize tasks",
|
|
79418
|
+
"Hand back work for rework if requirements are not met"
|
|
79419
|
+
],
|
|
79420
|
+
defaultHandoffTarget: "builder"
|
|
79421
|
+
},
|
|
79422
|
+
architect: {
|
|
79423
|
+
role: "architect",
|
|
79424
|
+
title: "Architect",
|
|
79425
|
+
description: "You are the system designer responsible for planning and high-level architecture.",
|
|
79426
|
+
responsibilities: [
|
|
79427
|
+
"Analyze requirements and break down complex tasks",
|
|
79428
|
+
"Design system architecture and component structure",
|
|
79429
|
+
"Make technology and pattern decisions",
|
|
79430
|
+
"Create clear specifications for the builder",
|
|
79431
|
+
"Consider scalability, maintainability, and best practices"
|
|
79432
|
+
],
|
|
79433
|
+
defaultHandoffTarget: "builder"
|
|
79434
|
+
},
|
|
79435
|
+
tester: {
|
|
79436
|
+
role: "tester",
|
|
79437
|
+
title: "Tester",
|
|
79438
|
+
description: "You are the QA specialist responsible for testing and validation.",
|
|
79439
|
+
responsibilities: [
|
|
79440
|
+
"Write and execute test cases",
|
|
79441
|
+
"Verify functionality works as expected",
|
|
79442
|
+
"Test edge cases and error handling",
|
|
79443
|
+
"Report bugs and issues clearly",
|
|
79444
|
+
"Confirm quality standards are met"
|
|
79445
|
+
],
|
|
79446
|
+
defaultHandoffTarget: "user"
|
|
79447
|
+
},
|
|
79448
|
+
solo: {
|
|
79449
|
+
role: "solo",
|
|
79450
|
+
title: "Solo",
|
|
79451
|
+
description: "You are the autonomous agent responsible for both planning and executing tasks independently.",
|
|
79452
|
+
responsibilities: [
|
|
79453
|
+
"Communicate directly with the user as the single point of contact",
|
|
79454
|
+
"Decompose complex tasks into actionable work items",
|
|
79455
|
+
"Implement solutions: write clean, maintainable code",
|
|
79456
|
+
"Follow established patterns and best practices",
|
|
79457
|
+
"Handle edge cases and error scenarios",
|
|
79458
|
+
"Review and validate your own work for quality",
|
|
79459
|
+
"Deliver completed results to the user"
|
|
79460
|
+
],
|
|
79461
|
+
defaultHandoffTarget: "user"
|
|
79462
|
+
}
|
|
79463
|
+
};
|
|
79464
|
+
});
|
|
77905
79465
|
|
|
77906
79466
|
// ../../services/backend/prompts/sections/role-identity.ts
|
|
79467
|
+
function getTeamHeaderSection(teamName) {
|
|
79468
|
+
return createSection("team-header", "knowledge", `# ${teamName}`);
|
|
79469
|
+
}
|
|
79470
|
+
function getRoleTitleSection(ctx) {
|
|
79471
|
+
const template = getRoleTemplate(ctx.role);
|
|
79472
|
+
return createSection("role-title", "knowledge", `## Your Role: ${template.title.toUpperCase()}`);
|
|
79473
|
+
}
|
|
79474
|
+
function getRoleDescriptionSection(ctx) {
|
|
79475
|
+
const template = getRoleTemplate(ctx.role);
|
|
79476
|
+
return createSection("role-description", "knowledge", template.description);
|
|
79477
|
+
}
|
|
77907
79478
|
var init_role_identity = __esm(() => {
|
|
77908
79479
|
init_templates();
|
|
77909
79480
|
});
|
|
77910
79481
|
|
|
77911
79482
|
// ../../services/backend/prompts/native/system-prompt.ts
|
|
79483
|
+
function composeNativeSystemPrompt(input) {
|
|
79484
|
+
const { chatroomId, role, teamId, teamName, teamRoles, teamEntryPoint, convexUrl } = input;
|
|
79485
|
+
const selectorCtx = buildSelectorContext({
|
|
79486
|
+
role,
|
|
79487
|
+
teamRoles,
|
|
79488
|
+
teamId,
|
|
79489
|
+
teamName,
|
|
79490
|
+
teamEntryPoint,
|
|
79491
|
+
convexUrl,
|
|
79492
|
+
chatroomId,
|
|
79493
|
+
agentType: input.agentType,
|
|
79494
|
+
nativeIntegration: true
|
|
79495
|
+
});
|
|
79496
|
+
const sections = [
|
|
79497
|
+
getRoleTitleSection(selectorCtx),
|
|
79498
|
+
getGlossarySection({
|
|
79499
|
+
convexUrl,
|
|
79500
|
+
chatroomId,
|
|
79501
|
+
role,
|
|
79502
|
+
nativeIntegration: true,
|
|
79503
|
+
compactSkills: true
|
|
79504
|
+
}),
|
|
79505
|
+
getRoleGuidanceSection(selectorCtx),
|
|
79506
|
+
getNativeCommandsReferenceSection({ chatroomId, role, convexUrl })
|
|
79507
|
+
];
|
|
79508
|
+
return composeSections(sections);
|
|
79509
|
+
}
|
|
77912
79510
|
var init_system_prompt = __esm(() => {
|
|
77913
79511
|
init_commands_reference();
|
|
77914
79512
|
init_glossary();
|
|
@@ -77918,11 +79516,46 @@ var init_system_prompt = __esm(() => {
|
|
|
77918
79516
|
});
|
|
77919
79517
|
|
|
77920
79518
|
// ../../services/backend/prompts/native/task-started-content.ts
|
|
79519
|
+
function getNativeTaskStartedPrompt(ctx) {
|
|
79520
|
+
const contextNewCmd = contextNewCommand({
|
|
79521
|
+
chatroomId: ctx.chatroomId,
|
|
79522
|
+
role: ctx.role,
|
|
79523
|
+
cliEnvPrefix: ctx.cliEnvPrefix,
|
|
79524
|
+
triggerMessageId: ctx.triggerMessageId
|
|
79525
|
+
});
|
|
79526
|
+
return `### Start working
|
|
79527
|
+
|
|
79528
|
+
Entry-point roles receive user messages directly. ${getNativeTokenActivityInProgressNote()}
|
|
79529
|
+
|
|
79530
|
+
${getContextRuleBlock(contextNewCmd, contextNewHint({ cliEnvPrefix: ctx.cliEnvPrefix }))}`;
|
|
79531
|
+
}
|
|
79532
|
+
function getNativeTaskStartedPromptForHandoffRecipient() {
|
|
79533
|
+
return `### Start Working
|
|
79534
|
+
|
|
79535
|
+
The task body contains your work description. Begin immediately.`;
|
|
79536
|
+
}
|
|
77921
79537
|
var init_task_started_content = __esm(() => {
|
|
77922
79538
|
init_new();
|
|
77923
79539
|
});
|
|
77924
79540
|
|
|
77925
79541
|
// ../../services/backend/prompts/sections/classification-guide.ts
|
|
79542
|
+
function getTaskIntakeContent(ctx) {
|
|
79543
|
+
const cliEnvPrefix = getCliEnvPrefix(ctx.convexUrl);
|
|
79544
|
+
const chatroomId = ctx.chatroomId ?? "";
|
|
79545
|
+
if (ctx.isEntryPoint) {
|
|
79546
|
+
return ctx.nativeIntegration ? getNativeTaskStartedPrompt({ chatroomId, role: ctx.role, cliEnvPrefix }) : getTaskStartedPrompt2({ chatroomId, role: ctx.role, cliEnvPrefix });
|
|
79547
|
+
}
|
|
79548
|
+
return ctx.nativeIntegration ? getNativeTaskStartedPromptForHandoffRecipient() : getTaskStartedPromptForHandoffRecipient2({
|
|
79549
|
+
chatroomId,
|
|
79550
|
+
role: ctx.role,
|
|
79551
|
+
cliEnvPrefix
|
|
79552
|
+
});
|
|
79553
|
+
}
|
|
79554
|
+
function getClassificationGuideSection(ctx) {
|
|
79555
|
+
const content = getTaskIntakeContent(ctx);
|
|
79556
|
+
const sectionId = ctx.isEntryPoint ? "task-intake-guide" : "handoff-recipient-guide";
|
|
79557
|
+
return createSection(sectionId, "knowledge", content);
|
|
79558
|
+
}
|
|
77926
79559
|
var init_classification_guide = __esm(() => {
|
|
77927
79560
|
init_cli();
|
|
77928
79561
|
init_task_started_content();
|
|
@@ -77930,23 +79563,118 @@ var init_classification_guide = __esm(() => {
|
|
|
77930
79563
|
});
|
|
77931
79564
|
|
|
77932
79565
|
// ../../services/backend/prompts/sections/current-classification.ts
|
|
79566
|
+
function getCurrentClassificationSection(classification) {
|
|
79567
|
+
const info = {
|
|
79568
|
+
question: {
|
|
79569
|
+
label: "QUESTION",
|
|
79570
|
+
description: "User is asking a question. Can respond directly after answering."
|
|
79571
|
+
},
|
|
79572
|
+
new_feature: {
|
|
79573
|
+
label: "NEW FEATURE",
|
|
79574
|
+
description: "New functionality request."
|
|
79575
|
+
},
|
|
79576
|
+
follow_up: {
|
|
79577
|
+
label: "FOLLOW-UP",
|
|
79578
|
+
description: "Follow-up to previous task. Same rules as the original apply."
|
|
79579
|
+
}
|
|
79580
|
+
};
|
|
79581
|
+
const { label, description } = info[classification];
|
|
79582
|
+
const content = `### Current Task: ${label}
|
|
79583
|
+
${description}`;
|
|
79584
|
+
return createSection("current-classification", "guidance", content);
|
|
79585
|
+
}
|
|
77933
79586
|
var init_current_classification = () => {};
|
|
77934
79587
|
|
|
77935
79588
|
// ../../services/backend/prompts/sections/getting-started.ts
|
|
79589
|
+
function getGettingStartedSection(ctx) {
|
|
79590
|
+
const content = getContextGainingGuidance({
|
|
79591
|
+
chatroomId: ctx.chatroomId ?? "",
|
|
79592
|
+
role: ctx.role,
|
|
79593
|
+
convexUrl: ctx.convexUrl,
|
|
79594
|
+
agentType: ctx.agentType
|
|
79595
|
+
});
|
|
79596
|
+
return createSection("getting-started", "knowledge", content);
|
|
79597
|
+
}
|
|
77936
79598
|
var init_getting_started = __esm(() => {
|
|
77937
79599
|
init_getting_started_content();
|
|
77938
79600
|
});
|
|
77939
79601
|
|
|
77940
79602
|
// ../../services/backend/prompts/sections/handoff-options.ts
|
|
79603
|
+
function getHandoffOptionsSection(params) {
|
|
79604
|
+
const roles = params.availableHandoffRoles.join(", ");
|
|
79605
|
+
const content = `### Handoff Options
|
|
79606
|
+
Available targets: ${roles}`;
|
|
79607
|
+
return createSection("handoff-options", "guidance", content);
|
|
79608
|
+
}
|
|
77941
79609
|
var init_handoff_options = () => {};
|
|
77942
79610
|
|
|
77943
79611
|
// ../../services/backend/prompts/sections/next-step.ts
|
|
79612
|
+
function getNextStepSection(params) {
|
|
79613
|
+
const cliEnvPrefix = getCliEnvPrefix(params.convexUrl);
|
|
79614
|
+
const waitCmd = getNextTaskCommand({
|
|
79615
|
+
chatroomId: params.chatroomId,
|
|
79616
|
+
role: params.role,
|
|
79617
|
+
cliEnvPrefix
|
|
79618
|
+
});
|
|
79619
|
+
const content = `### Next
|
|
79620
|
+
|
|
79621
|
+
Run:
|
|
79622
|
+
|
|
79623
|
+
\`\`\`bash
|
|
79624
|
+
${waitCmd}
|
|
79625
|
+
\`\`\``;
|
|
79626
|
+
return createSection("next-step", "guidance", content);
|
|
79627
|
+
}
|
|
77944
79628
|
var init_next_step = __esm(() => {
|
|
77945
79629
|
init_command();
|
|
77946
79630
|
init_utils3();
|
|
77947
79631
|
});
|
|
77948
79632
|
|
|
77949
79633
|
// ../../services/backend/prompts/sections/session-vs-chatroom-task.ts
|
|
79634
|
+
function getTwoLevelsTableSection() {
|
|
79635
|
+
return `## Two-Level Model: Session vs Chatroom Task
|
|
79636
|
+
|
|
79637
|
+
| Level | Name | Scope | Ends when |
|
|
79638
|
+
|-------|------|-------|-----------|
|
|
79639
|
+
| **A** | **Session** (harness turn) | The entire agent invocation — from startup to shutdown | You deliberately shut down or the harness exits |
|
|
79640
|
+
| **B** | **Chatroom task** | One discrete unit of work delivered by \`get-next-task\` | You run \`handoff\` to pass work to the next role |
|
|
79641
|
+
|
|
79642
|
+
**Completing Level B does NOT end Level A.**
|
|
79643
|
+
After every \`handoff\`, you must run \`get-next-task\` again to stay in the session and receive the next chatroom task.`;
|
|
79644
|
+
}
|
|
79645
|
+
function getSessionLifecycleSection() {
|
|
79646
|
+
return `### Session Lifecycle
|
|
79647
|
+
|
|
79648
|
+
A session starts when your harness launches you and ends only when the harness shuts down (or you explicitly stop).
|
|
79649
|
+
Within a session, you process many chatroom tasks sequentially:
|
|
79650
|
+
|
|
79651
|
+
\`get-next-task\` → do work → \`handoff\` → \`get-next-task\` → do work → \`handoff\` → …
|
|
79652
|
+
|
|
79653
|
+
Never exit or stop after a handoff — that closes the session (Level A) before the user is done with you.`;
|
|
79654
|
+
}
|
|
79655
|
+
function getSessionAntiPatternsSection() {
|
|
79656
|
+
return `### Common Mistakes
|
|
79657
|
+
|
|
79658
|
+
❌ **Wrong:** Run \`handoff\`, then stop or wait for the user to re-invoke you.
|
|
79659
|
+
✅ **Right:** Run \`handoff\`, then immediately run \`get-next-task\` in the foreground.
|
|
79660
|
+
|
|
79661
|
+
❌ **Wrong:** Think "I finished the task, I'm done."
|
|
79662
|
+
✅ **Right:** Think "I finished this chatroom task (Level B). The session (Level A) continues — run \`get-next-task\`."
|
|
79663
|
+
|
|
79664
|
+
❌ **Wrong:** Run \`get-next-task\` in the background or skip it.
|
|
79665
|
+
✅ **Right:** \`get-next-task\` must run in the **foreground** so the harness can deliver the next chatroom task.`;
|
|
79666
|
+
}
|
|
79667
|
+
function getSessionVsChatroomTaskSection() {
|
|
79668
|
+
const content = [
|
|
79669
|
+
getTwoLevelsTableSection(),
|
|
79670
|
+
"",
|
|
79671
|
+
getSessionLifecycleSection(),
|
|
79672
|
+
"",
|
|
79673
|
+
getSessionAntiPatternsSection()
|
|
79674
|
+
].join(`
|
|
79675
|
+
`);
|
|
79676
|
+
return createSection("session-vs-chatroom-task", "guidance", content);
|
|
79677
|
+
}
|
|
77950
79678
|
var init_session_vs_chatroom_task = () => {};
|
|
77951
79679
|
|
|
77952
79680
|
// ../../services/backend/src/domain/entities/harness/claude-sdk.config.ts
|
|
@@ -78151,9 +79879,571 @@ var init_types = __esm(() => {
|
|
|
78151
79879
|
"pi-sdk": piSdkCapabilities
|
|
78152
79880
|
};
|
|
78153
79881
|
});
|
|
79882
|
+
|
|
79883
|
+
// ../../services/backend/prompts/review-guidelines/review.ts
|
|
79884
|
+
function getReviewGuidelines() {
|
|
79885
|
+
return [REVIEW_PRINCIPLES, REVIEW_PROCESS, GUIDELINE_FILE_LOCATIONS, REJECTION_GUIDANCE].join(`
|
|
79886
|
+
|
|
79887
|
+
`);
|
|
79888
|
+
}
|
|
79889
|
+
var REVIEW_PRINCIPLES = `
|
|
79890
|
+
## Review Principles
|
|
79891
|
+
|
|
79892
|
+
When reviewing completed work, you serve as the quality guardian between implementation and delivery.
|
|
79893
|
+
|
|
79894
|
+
### Primary Goal: Maintainability & Extensibility
|
|
79895
|
+
|
|
79896
|
+
**The ultimate purpose of code review is to ensure the changes make it possible to continue building on the application.**
|
|
79897
|
+
|
|
79898
|
+
Every piece of code must be:
|
|
79899
|
+
- Easy to understand and modify later
|
|
79900
|
+
- Following patterns that scale
|
|
79901
|
+
- Not creating technical debt that slows future development
|
|
79902
|
+
|
|
79903
|
+
If code is hard to extend, hard to understand, or creates mess - it should be rejected or refactored, regardless of whether it "works."
|
|
79904
|
+
|
|
79905
|
+
### Core Values
|
|
79906
|
+
|
|
79907
|
+
1. **User Goal Alignment**
|
|
79908
|
+
The implementation must accomplish what the user originally requested.
|
|
79909
|
+
Compare the work against the ORIGINAL user request, not just the handoff summary.
|
|
79910
|
+
|
|
79911
|
+
2. **Code Quality Over Speed**
|
|
79912
|
+
Maintain code quality: Use \`handoff\` to reject messy code that creates technical debt and slows future development.
|
|
79913
|
+
|
|
79914
|
+
3. **Codebase Consistency**
|
|
79915
|
+
New code should follow existing patterns and conventions.
|
|
79916
|
+
Check guideline files for project-specific rules.
|
|
79917
|
+
Inconsistent code creates confusion and bugs.
|
|
79918
|
+
|
|
79919
|
+
4. **Verification Over Trust**
|
|
79920
|
+
Check the actual changes, not just the summary.
|
|
79921
|
+
If something seems off, investigate. Trust but verify.
|
|
79922
|
+
|
|
79923
|
+
5. **Be Direct and Specific**
|
|
79924
|
+
Be specific and clear in your \`handoff\` message: Vague feedback leads to confusion and rework. If something is wrong, say exactly what and why.
|
|
79925
|
+
If a refactor is needed, propose the exact approach.
|
|
79926
|
+
`, REVIEW_PROCESS = `
|
|
79927
|
+
## Review Process
|
|
79928
|
+
|
|
79929
|
+
### Phase 1: Context Review
|
|
79930
|
+
|
|
79931
|
+
Before looking at code, understand what was requested:
|
|
79932
|
+
|
|
79933
|
+
1. Read the **original user request** in the context window
|
|
79934
|
+
2. Note all requirements, constraints, and acceptance criteria
|
|
79935
|
+
3. If a feature has metadata (title, description, tech-specs), review each point
|
|
79936
|
+
4. If there are attached tasks, read their content
|
|
79937
|
+
|
|
79938
|
+
### Phase 2: Change Inspection
|
|
79939
|
+
|
|
79940
|
+
Run these commands to inspect the implementation:
|
|
79941
|
+
|
|
79942
|
+
\`\`\`bash
|
|
79943
|
+
# Check for linting issues
|
|
79944
|
+
pnpm lint:fix
|
|
79945
|
+
|
|
79946
|
+
# View uncommitted changes
|
|
79947
|
+
git status
|
|
79948
|
+
git diff
|
|
79949
|
+
|
|
79950
|
+
# View recent commits
|
|
79951
|
+
git log --oneline -5
|
|
79952
|
+
git show HEAD
|
|
79953
|
+
\`\`\`
|
|
79954
|
+
|
|
79955
|
+
### Phase 3: Code Review Checklist
|
|
79956
|
+
|
|
79957
|
+
**Functional Requirements:**
|
|
79958
|
+
- [ ] All requirements from original request are addressed
|
|
79959
|
+
- [ ] Edge cases are handled
|
|
79960
|
+
- [ ] Error handling is appropriate
|
|
79961
|
+
|
|
79962
|
+
**Code Quality:**
|
|
79963
|
+
- [ ] No \`any\` types - proper TypeScript typing required
|
|
79964
|
+
- [ ] No type assertions (\`as\`) hiding real type issues
|
|
79965
|
+
- [ ] React hooks used correctly (deps arrays, memoization)
|
|
79966
|
+
- [ ] No inline workarounds or hacks
|
|
79967
|
+
|
|
79968
|
+
**Codebase Consistency:**
|
|
79969
|
+
- [ ] Follows existing patterns in the codebase
|
|
79970
|
+
- [ ] Uses existing components/utilities where applicable
|
|
79971
|
+
- [ ] Styling follows design system (semantic tokens, not hardcoded colors)
|
|
79972
|
+
|
|
79973
|
+
**Guidelines Compliance:**
|
|
79974
|
+
- [ ] Check relevant guideline files were followed (see list below)
|
|
79975
|
+
|
|
79976
|
+
### Phase 4: Decision
|
|
79977
|
+
|
|
79978
|
+
**Your feedback must be SPECIFIC and ACTIONABLE. Include clear guidance in your \`handoff\` message to help the builder make the right changes.**
|
|
79979
|
+
|
|
79980
|
+
**If changes are needed:**
|
|
79981
|
+
- State EXACTLY what is wrong (file, line, code snippet)
|
|
79982
|
+
- Explain WHY it's a problem (not just that it's wrong)
|
|
79983
|
+
- Provide the EXACT fix or approach you want to see
|
|
79984
|
+
- If multiple issues, number them clearly
|
|
79985
|
+
|
|
79986
|
+
Example of BAD feedback:
|
|
79987
|
+
> "The code could be cleaner"
|
|
79988
|
+
|
|
79989
|
+
Example of GOOD feedback:
|
|
79990
|
+
> "In \`TaskQueue.tsx\` line 45, you're using \`any\` type for the task parameter.
|
|
79991
|
+
> This hides type errors. Change to: \`task: Task\` using the imported Task type."
|
|
79992
|
+
|
|
79993
|
+
**If the code is a mess - REJECT IT:**
|
|
79994
|
+
- Use \`handoff\` to reject messy code that "works"
|
|
79995
|
+
- Propose the refactor approach explicitly in your \`handoff\` message
|
|
79996
|
+
- Large refactors are acceptable if they improve maintainability
|
|
79997
|
+
- The goal is code that can be built upon, not just code that runs
|
|
79998
|
+
|
|
79999
|
+
**If approved:**
|
|
80000
|
+
- Confirm ALL requirements from original request are met
|
|
80001
|
+
- Briefly summarize what was verified
|
|
80002
|
+
- Hand off to user
|
|
80003
|
+
`, GUIDELINE_FILE_LOCATIONS = `
|
|
80004
|
+
## Guideline Files to Check
|
|
80005
|
+
|
|
80006
|
+
Different AI tools use different guideline file locations. Check any that exist:
|
|
80007
|
+
|
|
80008
|
+
### Cursor IDE
|
|
80009
|
+
- \`.cursor/rules/*.md\` - Cursor rules files
|
|
80010
|
+
- \`.cursorrules\` - Root cursor rules
|
|
80011
|
+
|
|
80012
|
+
### GitHub Copilot
|
|
80013
|
+
- \`.github/copilot-instructions.md\` - Copilot instructions
|
|
80014
|
+
- \`.github/copilot/*.md\` - Additional Copilot files
|
|
80015
|
+
|
|
80016
|
+
### Claude / Anthropic
|
|
80017
|
+
- \`CLAUDE.md\` - Claude-specific instructions
|
|
80018
|
+
- \`.claude/*.md\` - Claude rules directory
|
|
80019
|
+
|
|
80020
|
+
### OpenAI / Codex
|
|
80021
|
+
- \`.openai/guidelines.md\` - OpenAI guidelines
|
|
80022
|
+
- \`CODEX.md\` - Codex instructions
|
|
80023
|
+
|
|
80024
|
+
### Generic Agent Files
|
|
80025
|
+
- \`AGENTS.md\` - Generic agent guidelines
|
|
80026
|
+
- \`.ai/*.md\` - AI-related instructions
|
|
80027
|
+
- \`DEVELOPMENT.md\` - Development guidelines
|
|
80028
|
+
- \`CONTRIBUTING.md\` - Contribution guidelines
|
|
80029
|
+
|
|
80030
|
+
### Project-Specific
|
|
80031
|
+
- \`docs/design/*.md\` - Design guidelines
|
|
80032
|
+
- \`docs/style-guide.md\` - Style guides
|
|
80033
|
+
- \`guides/*.md\` - Project guides
|
|
80034
|
+
|
|
80035
|
+
**Important:** Adapt to what exists in THIS codebase. Not all projects have all files.
|
|
80036
|
+
`, REJECTION_GUIDANCE = `
|
|
80037
|
+
## When to Reject or Request Refactors
|
|
80038
|
+
|
|
80039
|
+
**Use \`handoff\` to maintain code quality:** The goal is a maintainable codebase.
|
|
80040
|
+
|
|
80041
|
+
### Reject When:
|
|
80042
|
+
|
|
80043
|
+
1. **Requirements Not Met**
|
|
80044
|
+
- The original user request is not fully addressed
|
|
80045
|
+
- Key features are missing or only partially implemented
|
|
80046
|
+
|
|
80047
|
+
2. **Significant Technical Debt**
|
|
80048
|
+
- Hacks or workarounds that will cause problems later
|
|
80049
|
+
- Code that is hard to understand or modify
|
|
80050
|
+
- Patterns that don't scale or won't work with future features
|
|
80051
|
+
|
|
80052
|
+
3. **Type Safety Violations**
|
|
80053
|
+
- Widespread use of \`any\` or type assertions
|
|
80054
|
+
- Missing proper error types or return types
|
|
80055
|
+
- Type errors being suppressed rather than fixed
|
|
80056
|
+
|
|
80057
|
+
4. **Architectural Issues**
|
|
80058
|
+
- Code in wrong location (logic in UI, UI in logic)
|
|
80059
|
+
- Duplication of existing functionality
|
|
80060
|
+
- Tight coupling that prevents testing/reuse
|
|
80061
|
+
|
|
80062
|
+
### Propose Refactors When:
|
|
80063
|
+
|
|
80064
|
+
1. **The fix is bigger than the feature**
|
|
80065
|
+
If cleaning up the code would take more effort than the original change,
|
|
80066
|
+
but the mess will compound over time - propose the refactor.
|
|
80067
|
+
|
|
80068
|
+
2. **Patterns are inconsistent**
|
|
80069
|
+
If new code follows different patterns than existing code,
|
|
80070
|
+
propose alignment to the established pattern.
|
|
80071
|
+
|
|
80072
|
+
3. **Abstractions are wrong**
|
|
80073
|
+
If the code is solving the problem at the wrong level of abstraction,
|
|
80074
|
+
propose the right approach even if it means starting over.
|
|
80075
|
+
|
|
80076
|
+
### How to Propose Refactors:
|
|
80077
|
+
|
|
80078
|
+
1. Explain the problem clearly
|
|
80079
|
+
2. Describe the desired end state
|
|
80080
|
+
3. Suggest whether to:
|
|
80081
|
+
- Fix now before merging
|
|
80082
|
+
- Create a follow-up task for later
|
|
80083
|
+
- Block on the refactor
|
|
80084
|
+
|
|
80085
|
+
**Remember:** Approving bad code costs more than rejecting it.
|
|
80086
|
+
`;
|
|
80087
|
+
|
|
78154
80088
|
// ../../services/backend/prompts/review-guidelines/index.ts
|
|
78155
80089
|
var init_review_guidelines = () => {};
|
|
80090
|
+
|
|
80091
|
+
// ../../services/backend/prompts/policies/security.ts
|
|
80092
|
+
function getSecurityPolicy() {
|
|
80093
|
+
return SECURITY_POLICY;
|
|
80094
|
+
}
|
|
80095
|
+
var SECURITY_POLICY = `
|
|
80096
|
+
## Security Review Policy
|
|
80097
|
+
|
|
80098
|
+
These are general security principles. Adapt to your codebase's specific security requirements.
|
|
80099
|
+
|
|
80100
|
+
### Authentication & Authorization
|
|
80101
|
+
|
|
80102
|
+
- [ ] Authentication checks are in place where required
|
|
80103
|
+
- [ ] Authorization verifies user has permission for the action
|
|
80104
|
+
- [ ] Session handling follows established patterns
|
|
80105
|
+
- [ ] No hardcoded credentials or secrets
|
|
80106
|
+
|
|
80107
|
+
### Input Validation
|
|
80108
|
+
|
|
80109
|
+
- [ ] User input is validated before use
|
|
80110
|
+
- [ ] Input sanitization for database queries (SQL injection prevention)
|
|
80111
|
+
- [ ] Path traversal protection for file operations
|
|
80112
|
+
- [ ] Proper escaping for output contexts (XSS prevention)
|
|
80113
|
+
|
|
80114
|
+
### Data Handling
|
|
80115
|
+
|
|
80116
|
+
- [ ] Sensitive data is not logged
|
|
80117
|
+
- [ ] PII is handled according to privacy requirements
|
|
80118
|
+
- [ ] Secrets use environment variables, not hardcoded values
|
|
80119
|
+
- [ ] .env files are not committed
|
|
80120
|
+
|
|
80121
|
+
### API Security
|
|
80122
|
+
|
|
80123
|
+
- [ ] Rate limiting considerations for public endpoints
|
|
80124
|
+
- [ ] CORS configuration is appropriate
|
|
80125
|
+
- [ ] API responses don't leak sensitive information
|
|
80126
|
+
- [ ] Error messages don't expose internal details
|
|
80127
|
+
|
|
80128
|
+
### Common Vulnerabilities to Check
|
|
80129
|
+
|
|
80130
|
+
1. **Injection Attacks**
|
|
80131
|
+
- SQL/NoSQL injection
|
|
80132
|
+
- Command injection
|
|
80133
|
+
- Template injection
|
|
80134
|
+
|
|
80135
|
+
2. **Broken Access Control**
|
|
80136
|
+
- Missing authorization checks
|
|
80137
|
+
- IDOR (Insecure Direct Object Reference)
|
|
80138
|
+
- Privilege escalation
|
|
80139
|
+
|
|
80140
|
+
3. **Security Misconfiguration**
|
|
80141
|
+
- Debug mode in production
|
|
80142
|
+
- Exposed admin interfaces
|
|
80143
|
+
- Default credentials
|
|
80144
|
+
|
|
80145
|
+
4. **Cryptographic Issues**
|
|
80146
|
+
- Weak hashing algorithms
|
|
80147
|
+
- Insecure random number generation
|
|
80148
|
+
- Improper key management
|
|
80149
|
+
|
|
80150
|
+
### Codebase-Specific Security
|
|
80151
|
+
|
|
80152
|
+
Check these locations for security-related guidelines:
|
|
80153
|
+
- Security documentation in \`docs/security*.md\`
|
|
80154
|
+
- Authentication patterns in existing auth code
|
|
80155
|
+
- Existing security middleware/helpers
|
|
80156
|
+
- Security comments in sensitive code areas
|
|
80157
|
+
|
|
80158
|
+
**Important:** These are general guidelines. Always verify against your project's specific security requirements and compliance needs.
|
|
80159
|
+
`;
|
|
80160
|
+
|
|
80161
|
+
// ../../services/backend/prompts/policies/design.ts
|
|
80162
|
+
function getDesignPolicy() {
|
|
80163
|
+
return DESIGN_POLICY;
|
|
80164
|
+
}
|
|
80165
|
+
var DESIGN_POLICY = `
|
|
80166
|
+
## Design Review Policy
|
|
80167
|
+
|
|
80168
|
+
These are general design principles. Adapt to your codebase's specific design system.
|
|
80169
|
+
|
|
80170
|
+
### Design System Compliance
|
|
80171
|
+
|
|
80172
|
+
- [ ] Uses existing design tokens (colors, spacing, typography)
|
|
80173
|
+
- [ ] Follows established component patterns
|
|
80174
|
+
- [ ] Reuses existing components instead of creating duplicates
|
|
80175
|
+
- [ ] Styling uses semantic values, not hardcoded ones
|
|
80176
|
+
|
|
80177
|
+
### Color Usage
|
|
80178
|
+
|
|
80179
|
+
**Semantic colors should be preferred:**
|
|
80180
|
+
- Use \`text-foreground\` not \`text-black\`
|
|
80181
|
+
- Use \`bg-card\` not \`bg-white\`
|
|
80182
|
+
- Use \`border-border\` not \`border-gray-200\`
|
|
80183
|
+
|
|
80184
|
+
**Dark mode support:**
|
|
80185
|
+
- All UI should work in both light and dark mode
|
|
80186
|
+
- Brand/status colors need dark variants (e.g., \`bg-red-50 dark:bg-red-950/20\`)
|
|
80187
|
+
|
|
80188
|
+
### Component Patterns
|
|
80189
|
+
|
|
80190
|
+
- [ ] Components follow existing file structure conventions
|
|
80191
|
+
- [ ] Props are typed properly
|
|
80192
|
+
- [ ] Components are accessible (keyboard navigation, ARIA)
|
|
80193
|
+
- [ ] Responsive design is considered
|
|
80194
|
+
|
|
80195
|
+
### Typography
|
|
80196
|
+
|
|
80197
|
+
- [ ] Uses established font sizes from the design system
|
|
80198
|
+
- [ ] Heading hierarchy is semantic (h1, h2, etc.)
|
|
80199
|
+
- [ ] Text is readable at all sizes
|
|
80200
|
+
- [ ] Font weights follow conventions
|
|
80201
|
+
|
|
80202
|
+
### Spacing & Layout
|
|
80203
|
+
|
|
80204
|
+
- [ ] Uses design system spacing tokens
|
|
80205
|
+
- [ ] Layout is responsive
|
|
80206
|
+
- [ ] Alignment is consistent
|
|
80207
|
+
- [ ] Proper use of flexbox/grid patterns
|
|
80208
|
+
|
|
80209
|
+
### UX Considerations
|
|
80210
|
+
|
|
80211
|
+
- [ ] Loading states are handled
|
|
80212
|
+
- [ ] Error states have clear messaging
|
|
80213
|
+
- [ ] Empty states are designed
|
|
80214
|
+
- [ ] Interactive elements have hover/focus states
|
|
80215
|
+
|
|
80216
|
+
### Common Design Issues to Catch
|
|
80217
|
+
|
|
80218
|
+
1. **Inconsistent Styling**
|
|
80219
|
+
- Different button styles for similar actions
|
|
80220
|
+
- Inconsistent spacing between elements
|
|
80221
|
+
- Mixed font sizes within components
|
|
80222
|
+
|
|
80223
|
+
2. **Accessibility Gaps**
|
|
80224
|
+
- Missing keyboard navigation
|
|
80225
|
+
- Low color contrast
|
|
80226
|
+
- Missing ARIA labels
|
|
80227
|
+
- Focus states not visible
|
|
80228
|
+
|
|
80229
|
+
3. **Hardcoded Values**
|
|
80230
|
+
- Magic numbers for spacing (use tokens)
|
|
80231
|
+
- Hardcoded colors (use semantic colors)
|
|
80232
|
+
- Fixed widths that break responsive
|
|
80233
|
+
|
|
80234
|
+
4. **Component Duplication**
|
|
80235
|
+
- Recreating existing components
|
|
80236
|
+
- Copy-paste instead of abstraction
|
|
80237
|
+
- Similar patterns implemented differently
|
|
80238
|
+
|
|
80239
|
+
### Codebase-Specific Design
|
|
80240
|
+
|
|
80241
|
+
Check these locations for design guidelines:
|
|
80242
|
+
- \`docs/design/*.md\` - Design documentation
|
|
80243
|
+
- \`components/ui/\` - Existing UI component library
|
|
80244
|
+
- \`tailwind.config.*\` - Theme configuration
|
|
80245
|
+
- \`globals.css\` or theme files - CSS custom properties
|
|
80246
|
+
- \`AGENTS.md\` or \`CLAUDE.md\` - May contain UI guidelines
|
|
80247
|
+
|
|
80248
|
+
**Important:** These are general guidelines. Always verify against your project's specific design system.
|
|
80249
|
+
`;
|
|
80250
|
+
|
|
80251
|
+
// ../../services/backend/prompts/policies/performance.ts
|
|
80252
|
+
function getPerformancePolicy() {
|
|
80253
|
+
return PERFORMANCE_POLICY;
|
|
80254
|
+
}
|
|
80255
|
+
var PERFORMANCE_POLICY = `
|
|
80256
|
+
## Performance Review Policy
|
|
80257
|
+
|
|
80258
|
+
These are general performance principles. Adapt to your codebase's specific requirements.
|
|
80259
|
+
|
|
80260
|
+
### Frontend Performance
|
|
80261
|
+
|
|
80262
|
+
**React/Component Performance:**
|
|
80263
|
+
- [ ] \`useMemo\` used for expensive computations
|
|
80264
|
+
- [ ] \`useCallback\` used for callback props passed to child components
|
|
80265
|
+
- [ ] \`React.memo\` considered for components receiving stable props
|
|
80266
|
+
- [ ] No unnecessary re-renders (check dependency arrays)
|
|
80267
|
+
- [ ] Large lists use virtualization where appropriate
|
|
80268
|
+
|
|
80269
|
+
**Bundle Size:**
|
|
80270
|
+
- [ ] No large dependencies added for simple functionality
|
|
80271
|
+
- [ ] Dynamic imports (\`lazy\`) used for route-level code splitting
|
|
80272
|
+
- [ ] Tree-shaking friendly imports (avoid \`import * as\`)
|
|
80273
|
+
- [ ] Images/assets are appropriately sized and optimized
|
|
80274
|
+
|
|
80275
|
+
**Rendering:**
|
|
80276
|
+
- [ ] No layout thrashing (reading and writing DOM in loops)
|
|
80277
|
+
- [ ] CSS animations use \`transform\` and \`opacity\` where possible
|
|
80278
|
+
- [ ] Avoid inline styles that change frequently
|
|
80279
|
+
- [ ] Consider \`will-change\` for animated elements
|
|
80280
|
+
|
|
80281
|
+
### Backend Performance
|
|
80282
|
+
|
|
80283
|
+
**Database Queries:**
|
|
80284
|
+
- [ ] Queries use appropriate indexes
|
|
80285
|
+
- [ ] N+1 query patterns are avoided or justified
|
|
80286
|
+
- [ ] Pagination used for large result sets
|
|
80287
|
+
- [ ] Expensive queries are cached where appropriate
|
|
80288
|
+
|
|
80289
|
+
**API Design:**
|
|
80290
|
+
- [ ] Responses don't include unnecessary data
|
|
80291
|
+
- [ ] Batch endpoints available for bulk operations
|
|
80292
|
+
- [ ] Expensive operations are async/background where possible
|
|
80293
|
+
- [ ] Rate limiting considered for resource-intensive endpoints
|
|
80294
|
+
|
|
80295
|
+
**Memory & Resources:**
|
|
80296
|
+
- [ ] No memory leaks (event listeners cleaned up, subscriptions closed)
|
|
80297
|
+
- [ ] Large data structures are streamed, not loaded entirely
|
|
80298
|
+
- [ ] Connection pooling used for database/external services
|
|
80299
|
+
- [ ] Temporary files/resources are cleaned up
|
|
80300
|
+
|
|
80301
|
+
### Common Performance Issues to Catch
|
|
80302
|
+
|
|
80303
|
+
1. **Unnecessary Computation**
|
|
80304
|
+
- Computing values on every render
|
|
80305
|
+
- Recalculating derived data without memoization
|
|
80306
|
+
- Expensive operations in hot paths
|
|
80307
|
+
|
|
80308
|
+
2. **Over-fetching**
|
|
80309
|
+
- Requesting more data than needed
|
|
80310
|
+
- Missing pagination on large datasets
|
|
80311
|
+
- Not using projection/select for specific fields
|
|
80312
|
+
|
|
80313
|
+
3. **Under-caching**
|
|
80314
|
+
- Repeated identical API calls
|
|
80315
|
+
- Not caching expensive computations
|
|
80316
|
+
- Missing server-side caching for static data
|
|
80317
|
+
|
|
80318
|
+
4. **Blocking Operations**
|
|
80319
|
+
- Synchronous operations blocking the event loop
|
|
80320
|
+
- Not using async patterns for I/O
|
|
80321
|
+
- Long-running operations without progress feedback
|
|
80322
|
+
|
|
80323
|
+
5. **React-Specific Issues**
|
|
80324
|
+
- Missing dependency arrays causing infinite loops
|
|
80325
|
+
- Creating new objects/functions in render
|
|
80326
|
+
- Not using \`key\` prop properly in lists
|
|
80327
|
+
- State updates in useEffect without proper deps
|
|
80328
|
+
|
|
80329
|
+
### Platform-Specific Considerations
|
|
80330
|
+
|
|
80331
|
+
**Next.js:**
|
|
80332
|
+
- Server Components for static content
|
|
80333
|
+
- Client Components for interactive elements
|
|
80334
|
+
- Image optimization with next/image
|
|
80335
|
+
- Route segment config for caching
|
|
80336
|
+
|
|
80337
|
+
**Convex:**
|
|
80338
|
+
- Query indexing for filtered/sorted data
|
|
80339
|
+
- Pagination for large result sets
|
|
80340
|
+
- Optimistic updates for better UX
|
|
80341
|
+
- Reactive queries vs. one-time fetches
|
|
80342
|
+
|
|
80343
|
+
**General Web:**
|
|
80344
|
+
- Core Web Vitals (LCP, FID, CLS)
|
|
80345
|
+
- Time to Interactive (TTI)
|
|
80346
|
+
- First Contentful Paint (FCP)
|
|
80347
|
+
|
|
80348
|
+
### Questions to Ask
|
|
80349
|
+
|
|
80350
|
+
1. "Will this scale with 10x/100x more data?"
|
|
80351
|
+
2. "What happens with slow network conditions?"
|
|
80352
|
+
3. "Are there any O(n²) or worse algorithms?"
|
|
80353
|
+
4. "Could this operation be batched or debounced?"
|
|
80354
|
+
5. "Is this computation necessary on every render?"
|
|
80355
|
+
|
|
80356
|
+
**Important:** These are general guidelines. Performance requirements vary by application.
|
|
80357
|
+
Focus on user-facing performance impact rather than micro-optimizations.
|
|
80358
|
+
`;
|
|
80359
|
+
|
|
78156
80360
|
// ../../services/backend/prompts/generator.ts
|
|
80361
|
+
var exports_generator = {};
|
|
80362
|
+
__export(exports_generator, {
|
|
80363
|
+
getSecurityPolicy: () => getSecurityPolicy,
|
|
80364
|
+
getReviewGuidelines: () => getReviewGuidelines,
|
|
80365
|
+
getPerformancePolicy: () => getPerformancePolicy,
|
|
80366
|
+
getDesignPolicy: () => getDesignPolicy,
|
|
80367
|
+
generateRolePrompt: () => generateRolePrompt,
|
|
80368
|
+
generateHandoffOutput: () => generateHandoffOutput,
|
|
80369
|
+
generateGeneralInstructions: () => generateGeneralInstructions,
|
|
80370
|
+
composeSystemPrompt: () => composeSystemPrompt2,
|
|
80371
|
+
composeInitPrompt: () => composeInitPrompt,
|
|
80372
|
+
composeInitMessage: () => composeInitMessage
|
|
80373
|
+
});
|
|
80374
|
+
function generateGeneralInstructions(_input) {
|
|
80375
|
+
const sections = [];
|
|
80376
|
+
sections.push(getNextTaskGuidance());
|
|
80377
|
+
return sections.join(`
|
|
80378
|
+
|
|
80379
|
+
`);
|
|
80380
|
+
}
|
|
80381
|
+
function generateRolePrompt(ctx) {
|
|
80382
|
+
const selectorCtx = buildSelectorContext({
|
|
80383
|
+
role: ctx.role,
|
|
80384
|
+
teamRoles: ctx.teamRoles,
|
|
80385
|
+
teamId: ctx.teamId,
|
|
80386
|
+
teamName: ctx.teamName,
|
|
80387
|
+
teamEntryPoint: ctx.teamEntryPoint,
|
|
80388
|
+
convexUrl: ctx.convexUrl,
|
|
80389
|
+
chatroomId: ctx.chatroomId,
|
|
80390
|
+
workflow: ctx.currentClassification
|
|
80391
|
+
});
|
|
80392
|
+
const sections = [];
|
|
80393
|
+
sections.push(getRoleTitleSection(selectorCtx));
|
|
80394
|
+
sections.push(getRoleDescriptionSection(selectorCtx));
|
|
80395
|
+
sections.push(getGlossarySection({ convexUrl: ctx.convexUrl ?? "", chatroomId: ctx.chatroomId }));
|
|
80396
|
+
sections.push(getRoleGuidanceSection(selectorCtx));
|
|
80397
|
+
if (ctx.currentClassification) {
|
|
80398
|
+
sections.push(getCurrentClassificationSection(ctx.currentClassification));
|
|
80399
|
+
}
|
|
80400
|
+
sections.push(getHandoffOptionsSection({
|
|
80401
|
+
availableHandoffRoles: ctx.availableHandoffRoles
|
|
80402
|
+
}));
|
|
80403
|
+
sections.push(getCommandsReferenceSection({
|
|
80404
|
+
chatroomId: ctx.chatroomId,
|
|
80405
|
+
role: ctx.role,
|
|
80406
|
+
convexUrl: ctx.convexUrl
|
|
80407
|
+
}));
|
|
80408
|
+
return composeSections(sections);
|
|
80409
|
+
}
|
|
80410
|
+
function buildInitPromptSections(input, selectorCtx) {
|
|
80411
|
+
const { chatroomId, role, teamRoles, convexUrl } = input;
|
|
80412
|
+
const otherRoles = teamRoles.filter((r) => r.toLowerCase() !== role.toLowerCase());
|
|
80413
|
+
const handoffTargets = [...new Set([...otherRoles, "user"])];
|
|
80414
|
+
const sections = [
|
|
80415
|
+
getTeamHeaderSection(input.teamName),
|
|
80416
|
+
getRoleTitleSection(selectorCtx),
|
|
80417
|
+
getRoleDescriptionSection(selectorCtx),
|
|
80418
|
+
getGlossarySection({ convexUrl: convexUrl ?? "", chatroomId }),
|
|
80419
|
+
getSessionVsChatroomTaskSection(),
|
|
80420
|
+
getGettingStartedSection(selectorCtx),
|
|
80421
|
+
getClassificationGuideSection(selectorCtx),
|
|
80422
|
+
getRoleGuidanceSection(selectorCtx),
|
|
80423
|
+
getHandoffOptionsSection({ availableHandoffRoles: handoffTargets }),
|
|
80424
|
+
getCommandsReferenceSection({ chatroomId, role, convexUrl }),
|
|
80425
|
+
getNextStepSection({ chatroomId, role, convexUrl })
|
|
80426
|
+
];
|
|
80427
|
+
return sections;
|
|
80428
|
+
}
|
|
80429
|
+
function composeSystemPrompt2(input) {
|
|
80430
|
+
if (isNativeHarness(input.agentHarness)) {
|
|
80431
|
+
return composeNativeSystemPrompt(input);
|
|
80432
|
+
}
|
|
80433
|
+
const { chatroomId, role, teamId, teamName, teamRoles, teamEntryPoint, convexUrl } = input;
|
|
80434
|
+
const selectorCtx = buildSelectorContext({
|
|
80435
|
+
role,
|
|
80436
|
+
teamRoles,
|
|
80437
|
+
teamId,
|
|
80438
|
+
teamName,
|
|
80439
|
+
teamEntryPoint,
|
|
80440
|
+
convexUrl,
|
|
80441
|
+
chatroomId,
|
|
80442
|
+
agentType: input.agentType,
|
|
80443
|
+
nativeIntegration: false
|
|
80444
|
+
});
|
|
80445
|
+
return composeSections(buildInitPromptSections(input, selectorCtx));
|
|
80446
|
+
}
|
|
78157
80447
|
function generateHandoffOutput(params) {
|
|
78158
80448
|
const { role, nextRole, chatroomId, convexUrl, supportsNativeIntegration } = params;
|
|
78159
80449
|
const cliEnvPrefix = getCliEnvPrefix(convexUrl);
|
|
@@ -78171,6 +80461,17 @@ function generateHandoffOutput(params) {
|
|
|
78171
80461
|
return lines.join(`
|
|
78172
80462
|
`);
|
|
78173
80463
|
}
|
|
80464
|
+
function composeInitMessage(_input) {
|
|
80465
|
+
return "";
|
|
80466
|
+
}
|
|
80467
|
+
function composeInitPrompt(input) {
|
|
80468
|
+
const systemPrompt = composeSystemPrompt2(input);
|
|
80469
|
+
const initMessage = composeInitMessage(input);
|
|
80470
|
+
const initPrompt = initMessage ? `${systemPrompt}
|
|
80471
|
+
|
|
80472
|
+
${initMessage}` : systemPrompt;
|
|
80473
|
+
return { systemPrompt, initMessage, initPrompt };
|
|
80474
|
+
}
|
|
78174
80475
|
var init_generator = __esm(() => {
|
|
78175
80476
|
init_command();
|
|
78176
80477
|
init_reminder();
|
|
@@ -79085,6 +81386,83 @@ var init_complete = __esm(() => {
|
|
|
79085
81386
|
init_error_formatting();
|
|
79086
81387
|
});
|
|
79087
81388
|
|
|
81389
|
+
// src/commands/enhancer/complete.ts
|
|
81390
|
+
var exports_complete2 = {};
|
|
81391
|
+
__export(exports_complete2, {
|
|
81392
|
+
enhancerComplete: () => enhancerComplete
|
|
81393
|
+
});
|
|
81394
|
+
async function createDefaultDeps10() {
|
|
81395
|
+
const client4 = await getConvexClient();
|
|
81396
|
+
return {
|
|
81397
|
+
backend: {
|
|
81398
|
+
mutation: (endpoint, args2) => client4.mutation(endpoint, args2),
|
|
81399
|
+
query: (endpoint, args2) => client4.query(endpoint, args2)
|
|
81400
|
+
},
|
|
81401
|
+
session: {
|
|
81402
|
+
getSessionId,
|
|
81403
|
+
getConvexUrl,
|
|
81404
|
+
getOtherSessionUrls
|
|
81405
|
+
}
|
|
81406
|
+
};
|
|
81407
|
+
}
|
|
81408
|
+
function handleCompleteError2(err) {
|
|
81409
|
+
return exports_Effect.sync(() => {
|
|
81410
|
+
if (err._tag === "NotAuthenticated") {
|
|
81411
|
+
formatAuthError(err.convexUrl, err.otherUrls);
|
|
81412
|
+
process.exit(1);
|
|
81413
|
+
}
|
|
81414
|
+
if (err._tag === "InvalidChatroomId") {
|
|
81415
|
+
formatChatroomIdError(err.id);
|
|
81416
|
+
process.exit(1);
|
|
81417
|
+
}
|
|
81418
|
+
console.error(`
|
|
81419
|
+
❌ ERROR: Enhancer complete failed`);
|
|
81420
|
+
console.error(`
|
|
81421
|
+
${err.errorData?.message ?? err.cause.message}`);
|
|
81422
|
+
process.exit(1);
|
|
81423
|
+
});
|
|
81424
|
+
}
|
|
81425
|
+
async function enhancerComplete(chatroomId, options) {
|
|
81426
|
+
const deps = await createDefaultDeps10();
|
|
81427
|
+
await exports_Effect.runPromise(enhancerCompleteEffect(chatroomId, options).pipe(exports_Effect.provide(commandServicesLayerFromDeps(deps)), exports_Effect.catchAll(handleCompleteError2)));
|
|
81428
|
+
}
|
|
81429
|
+
var enhancerCompleteEffect = (chatroomId, options) => exports_Effect.gen(function* () {
|
|
81430
|
+
const backend2 = yield* BackendService;
|
|
81431
|
+
const sessionId = yield* requireSessionIdEffect((a) => ({
|
|
81432
|
+
_tag: "NotAuthenticated",
|
|
81433
|
+
convexUrl: a.convexUrl,
|
|
81434
|
+
otherUrls: a.otherUrls
|
|
81435
|
+
}));
|
|
81436
|
+
yield* validateChatroomIdEffect(chatroomId, (id3) => ({
|
|
81437
|
+
_tag: "InvalidChatroomId",
|
|
81438
|
+
id: id3
|
|
81439
|
+
}));
|
|
81440
|
+
yield* backend2.mutation(api.web.enhancer.index.complete, {
|
|
81441
|
+
sessionId,
|
|
81442
|
+
chatroomId,
|
|
81443
|
+
jobId: options.jobId,
|
|
81444
|
+
enhancedContent: options.enhancedContent
|
|
81445
|
+
}).pipe(exports_Effect.mapError((cause3) => {
|
|
81446
|
+
let errorData;
|
|
81447
|
+
if (cause3 instanceof ConvexError) {
|
|
81448
|
+
errorData = cause3.data;
|
|
81449
|
+
}
|
|
81450
|
+
return { _tag: "CompleteFailed", cause: cause3, errorData };
|
|
81451
|
+
}));
|
|
81452
|
+
yield* exports_Effect.sync(() => {
|
|
81453
|
+
console.log(`✅ Enhancer job ${options.jobId} completed`);
|
|
81454
|
+
});
|
|
81455
|
+
});
|
|
81456
|
+
var init_complete2 = __esm(() => {
|
|
81457
|
+
init_values();
|
|
81458
|
+
init_esm();
|
|
81459
|
+
init_api3();
|
|
81460
|
+
init_storage();
|
|
81461
|
+
init_client2();
|
|
81462
|
+
init_services();
|
|
81463
|
+
init_error_formatting();
|
|
81464
|
+
});
|
|
81465
|
+
|
|
79088
81466
|
// src/commands/backlog/backlog-fs-service.ts
|
|
79089
81467
|
import * as nodeFs from "node:fs/promises";
|
|
79090
81468
|
var BacklogFsService, BacklogFsServiceLive, BacklogFsServiceFrom = (ops) => exports_Layer.succeed(BacklogFsService, {
|
|
@@ -79191,7 +81569,7 @@ function buildBaseLayer(d) {
|
|
|
79191
81569
|
function buildFsLayer(fs11) {
|
|
79192
81570
|
return fs11 ? BacklogFsServiceFrom(fs11) : BacklogFsServiceLive;
|
|
79193
81571
|
}
|
|
79194
|
-
async function
|
|
81572
|
+
async function createDefaultDeps11() {
|
|
79195
81573
|
const client4 = await getConvexClient();
|
|
79196
81574
|
const fs11 = await import("node:fs/promises");
|
|
79197
81575
|
return {
|
|
@@ -79247,47 +81625,47 @@ function computeContentHash(content) {
|
|
|
79247
81625
|
return createHash("sha256").update(content).digest("hex");
|
|
79248
81626
|
}
|
|
79249
81627
|
async function listBacklog(chatroomId, options, deps) {
|
|
79250
|
-
const d = deps ?? await
|
|
81628
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79251
81629
|
await exports_Effect.runPromise(listBacklogEffect(chatroomId, options).pipe(exports_Effect.catchAll(handleBacklogError), exports_Effect.provide(buildBaseLayer(d))));
|
|
79252
81630
|
}
|
|
79253
81631
|
async function addBacklog(chatroomId, options, deps) {
|
|
79254
|
-
const d = deps ?? await
|
|
81632
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79255
81633
|
await exports_Effect.runPromise(addBacklogEffect(chatroomId, options).pipe(exports_Effect.catchAll(handleBacklogError), exports_Effect.provide(buildBaseLayer(d))));
|
|
79256
81634
|
}
|
|
79257
81635
|
async function completeBacklog(chatroomId, options, deps) {
|
|
79258
|
-
const d = deps ?? await
|
|
81636
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79259
81637
|
await exports_Effect.runPromise(completeBacklogEffect(chatroomId, options).pipe(exports_Effect.catchAll(handleBacklogError), exports_Effect.provide(buildBaseLayer(d))));
|
|
79260
81638
|
}
|
|
79261
81639
|
async function reopenBacklog(chatroomId, options, deps) {
|
|
79262
|
-
const d = deps ?? await
|
|
81640
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79263
81641
|
await exports_Effect.runPromise(reopenBacklogEffect(chatroomId, options).pipe(exports_Effect.catchAll(handleBacklogError), exports_Effect.provide(buildBaseLayer(d))));
|
|
79264
81642
|
}
|
|
79265
81643
|
async function patchBacklog(chatroomId, options, deps) {
|
|
79266
|
-
const d = deps ?? await
|
|
81644
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79267
81645
|
await exports_Effect.runPromise(patchBacklogEffect(chatroomId, options).pipe(exports_Effect.catchAll(handleBacklogError), exports_Effect.provide(buildBaseLayer(d))));
|
|
79268
81646
|
}
|
|
79269
81647
|
async function scoreBacklog(chatroomId, options, deps) {
|
|
79270
|
-
const d = deps ?? await
|
|
81648
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79271
81649
|
await exports_Effect.runPromise(scoreBacklogEffect(chatroomId, options).pipe(exports_Effect.catchAll(handleBacklogError), exports_Effect.provide(buildBaseLayer(d))));
|
|
79272
81650
|
}
|
|
79273
81651
|
async function markForReviewBacklog(chatroomId, options, deps) {
|
|
79274
|
-
const d = deps ?? await
|
|
81652
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79275
81653
|
await exports_Effect.runPromise(markForReviewBacklogEffect(chatroomId, options).pipe(exports_Effect.catchAll(handleBacklogError), exports_Effect.provide(buildBaseLayer(d))));
|
|
79276
81654
|
}
|
|
79277
81655
|
async function historyBacklog(chatroomId, options, deps) {
|
|
79278
|
-
const d = deps ?? await
|
|
81656
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79279
81657
|
await exports_Effect.runPromise(historyBacklogEffect(chatroomId, options).pipe(exports_Effect.catchAll(handleBacklogError), exports_Effect.provide(buildBaseLayer(d))));
|
|
79280
81658
|
}
|
|
79281
81659
|
async function updateBacklog(chatroomId, options, deps) {
|
|
79282
|
-
const d = deps ?? await
|
|
81660
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79283
81661
|
await exports_Effect.runPromise(updateBacklogEffect(chatroomId, options).pipe(exports_Effect.catchAll(handleBacklogError), exports_Effect.provide(buildBaseLayer(d))));
|
|
79284
81662
|
}
|
|
79285
81663
|
async function closeBacklog(chatroomId, options, deps) {
|
|
79286
|
-
const d = deps ?? await
|
|
81664
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79287
81665
|
await exports_Effect.runPromise(closeBacklogEffect(chatroomId, options).pipe(exports_Effect.catchAll(handleBacklogError), exports_Effect.provide(buildBaseLayer(d))));
|
|
79288
81666
|
}
|
|
79289
81667
|
async function exportBacklog(chatroomId, options, deps) {
|
|
79290
|
-
const d = deps ?? await
|
|
81668
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79291
81669
|
if (!d.fs) {
|
|
79292
81670
|
console.error("❌ File system operations not available");
|
|
79293
81671
|
process.exit(1);
|
|
@@ -79296,7 +81674,7 @@ async function exportBacklog(chatroomId, options, deps) {
|
|
|
79296
81674
|
await exports_Effect.runPromise(exportBacklogEffect(chatroomId, options).pipe(exports_Effect.catchAll(handleBacklogError), exports_Effect.provide(exports_Layer.merge(buildBaseLayer(d), buildFsLayer(d.fs)))));
|
|
79297
81675
|
}
|
|
79298
81676
|
async function importBacklog(chatroomId, options, deps) {
|
|
79299
|
-
const d = deps ?? await
|
|
81677
|
+
const d = deps ?? await createDefaultDeps11();
|
|
79300
81678
|
if (!d.fs) {
|
|
79301
81679
|
console.error("❌ File system operations not available");
|
|
79302
81680
|
process.exit(1);
|
|
@@ -80057,7 +82435,7 @@ __export(exports_read, {
|
|
|
80057
82435
|
taskReadEffect: () => taskReadEffect,
|
|
80058
82436
|
taskRead: () => taskRead
|
|
80059
82437
|
});
|
|
80060
|
-
async function
|
|
82438
|
+
async function createDefaultDeps12() {
|
|
80061
82439
|
const client4 = await getConvexClient();
|
|
80062
82440
|
return {
|
|
80063
82441
|
backend: {
|
|
@@ -80099,7 +82477,7 @@ function handleTaskReadError(err) {
|
|
|
80099
82477
|
});
|
|
80100
82478
|
}
|
|
80101
82479
|
async function taskRead(chatroomId, options, deps) {
|
|
80102
|
-
const d = deps ?? await
|
|
82480
|
+
const d = deps ?? await createDefaultDeps12();
|
|
80103
82481
|
const layer = commandServicesLayerFromDeps(d);
|
|
80104
82482
|
await exports_Effect.runPromise(taskReadEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleTaskReadError(err)), exports_Effect.provide(layer)));
|
|
80105
82483
|
}
|
|
@@ -80190,7 +82568,7 @@ __export(exports_skill, {
|
|
|
80190
82568
|
activateSkillEffect: () => activateSkillEffect,
|
|
80191
82569
|
activateSkill: () => activateSkill
|
|
80192
82570
|
});
|
|
80193
|
-
async function
|
|
82571
|
+
async function createDefaultDeps13() {
|
|
80194
82572
|
const client4 = await getConvexClient();
|
|
80195
82573
|
return {
|
|
80196
82574
|
backend: {
|
|
@@ -80259,12 +82637,12 @@ function handleActivateSkillError(err) {
|
|
|
80259
82637
|
});
|
|
80260
82638
|
}
|
|
80261
82639
|
async function listSkills(chatroomId, options, deps) {
|
|
80262
|
-
const d = deps ?? await
|
|
82640
|
+
const d = deps ?? await createDefaultDeps13();
|
|
80263
82641
|
const layer = commandServicesLayerFromDeps(d);
|
|
80264
82642
|
await exports_Effect.runPromise(listSkillsEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleListSkillsError(err)), exports_Effect.provide(layer)));
|
|
80265
82643
|
}
|
|
80266
82644
|
async function activateSkill(chatroomId, skillId, options, deps) {
|
|
80267
|
-
const d = deps ?? await
|
|
82645
|
+
const d = deps ?? await createDefaultDeps13();
|
|
80268
82646
|
const layer = commandServicesLayerFromDeps(d);
|
|
80269
82647
|
await exports_Effect.runPromise(activateSkillEffect(chatroomId, skillId, options).pipe(exports_Effect.catchAll((err) => handleActivateSkillError(err)), exports_Effect.provide(layer)));
|
|
80270
82648
|
}
|
|
@@ -80342,7 +82720,7 @@ __export(exports_messages, {
|
|
|
80342
82720
|
listBySenderRoleEffect: () => listBySenderRoleEffect,
|
|
80343
82721
|
listBySenderRole: () => listBySenderRole
|
|
80344
82722
|
});
|
|
80345
|
-
async function
|
|
82723
|
+
async function createDefaultDeps14() {
|
|
80346
82724
|
const client4 = await getConvexClient();
|
|
80347
82725
|
return {
|
|
80348
82726
|
backend: {
|
|
@@ -80403,12 +82781,12 @@ function handleMessagesError(err) {
|
|
|
80403
82781
|
});
|
|
80404
82782
|
}
|
|
80405
82783
|
async function listBySenderRole(chatroomId, options, deps) {
|
|
80406
|
-
const d = deps ?? await
|
|
82784
|
+
const d = deps ?? await createDefaultDeps14();
|
|
80407
82785
|
const layer = commandServicesLayerFromDeps(d);
|
|
80408
82786
|
await exports_Effect.runPromise(listBySenderRoleEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleMessagesError(err)), exports_Effect.provide(layer)));
|
|
80409
82787
|
}
|
|
80410
82788
|
async function listSinceMessage(chatroomId, options, deps) {
|
|
80411
|
-
const d = deps ?? await
|
|
82789
|
+
const d = deps ?? await createDefaultDeps14();
|
|
80412
82790
|
const layer = commandServicesLayerFromDeps(d);
|
|
80413
82791
|
await exports_Effect.runPromise(listSinceMessageEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleMessagesError(err)), exports_Effect.provide(layer)));
|
|
80414
82792
|
}
|
|
@@ -80538,7 +82916,7 @@ __export(exports_context2, {
|
|
|
80538
82916
|
inspectContextEffect: () => inspectContextEffect,
|
|
80539
82917
|
inspectContext: () => inspectContext
|
|
80540
82918
|
});
|
|
80541
|
-
async function
|
|
82919
|
+
async function createDefaultDeps15() {
|
|
80542
82920
|
const client4 = await getConvexClient();
|
|
80543
82921
|
return {
|
|
80544
82922
|
backend: {
|
|
@@ -80579,17 +82957,17 @@ function handleContextError(err) {
|
|
|
80579
82957
|
});
|
|
80580
82958
|
}
|
|
80581
82959
|
async function readContext(chatroomId, options, deps) {
|
|
80582
|
-
const d = deps ?? await
|
|
82960
|
+
const d = deps ?? await createDefaultDeps15();
|
|
80583
82961
|
const layer = commandServicesLayerFromDeps(d);
|
|
80584
82962
|
await exports_Effect.runPromise(readContextEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleContextError(err)), exports_Effect.provide(layer)));
|
|
80585
82963
|
}
|
|
80586
82964
|
async function newContext(chatroomId, options, deps) {
|
|
80587
|
-
const d = deps ?? await
|
|
82965
|
+
const d = deps ?? await createDefaultDeps15();
|
|
80588
82966
|
const layer = commandServicesLayerFromDeps(d);
|
|
80589
82967
|
await exports_Effect.runPromise(newContextEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleContextError(err)), exports_Effect.provide(layer)));
|
|
80590
82968
|
}
|
|
80591
82969
|
async function listContexts(chatroomId, options, deps) {
|
|
80592
|
-
const d = deps ?? await
|
|
82970
|
+
const d = deps ?? await createDefaultDeps15();
|
|
80593
82971
|
const layer = commandServicesLayerFromDeps(d);
|
|
80594
82972
|
await exports_Effect.runPromise(listContextsEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleContextError(err)), exports_Effect.provide(layer)));
|
|
80595
82973
|
}
|
|
@@ -80597,7 +82975,7 @@ function viewTemplate() {
|
|
|
80597
82975
|
return getContextViewTemplate();
|
|
80598
82976
|
}
|
|
80599
82977
|
async function inspectContext(chatroomId, options, deps) {
|
|
80600
|
-
const d = deps ?? await
|
|
82978
|
+
const d = deps ?? await createDefaultDeps15();
|
|
80601
82979
|
const layer = commandServicesLayerFromDeps(d);
|
|
80602
82980
|
await exports_Effect.runPromise(inspectContextEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleContextError(err)), exports_Effect.provide(layer)));
|
|
80603
82981
|
}
|
|
@@ -80838,7 +83216,7 @@ __export(exports_guidelines, {
|
|
|
80838
83216
|
listGuidelineTypesEffect: () => listGuidelineTypesEffect,
|
|
80839
83217
|
listGuidelineTypes: () => listGuidelineTypes
|
|
80840
83218
|
});
|
|
80841
|
-
async function
|
|
83219
|
+
async function createDefaultDeps16() {
|
|
80842
83220
|
const client4 = await getConvexClient();
|
|
80843
83221
|
return {
|
|
80844
83222
|
backend: {
|
|
@@ -80879,12 +83257,12 @@ function handleListGuidelineTypesError(err) {
|
|
|
80879
83257
|
});
|
|
80880
83258
|
}
|
|
80881
83259
|
async function viewGuidelines(options, deps) {
|
|
80882
|
-
const d = deps ?? await
|
|
83260
|
+
const d = deps ?? await createDefaultDeps16();
|
|
80883
83261
|
const layer = layerFromDeps7(d);
|
|
80884
83262
|
await exports_Effect.runPromise(viewGuidelinesEffect(options).pipe(exports_Effect.catchAll((err) => handleViewGuidelinesError(err)), exports_Effect.provide(layer)));
|
|
80885
83263
|
}
|
|
80886
83264
|
async function listGuidelineTypes(deps) {
|
|
80887
|
-
const d = deps ?? await
|
|
83265
|
+
const d = deps ?? await createDefaultDeps16();
|
|
80888
83266
|
const layer = layerFromDeps7(d);
|
|
80889
83267
|
await exports_Effect.runPromise(listGuidelineTypesEffect().pipe(exports_Effect.catchAll((err) => handleListGuidelineTypesError(err)), exports_Effect.provide(layer)));
|
|
80890
83268
|
}
|
|
@@ -80954,7 +83332,7 @@ __export(exports_artifact, {
|
|
|
80954
83332
|
createArtifactEffect: () => createArtifactEffect,
|
|
80955
83333
|
createArtifact: () => createArtifact
|
|
80956
83334
|
});
|
|
80957
|
-
async function
|
|
83335
|
+
async function createDefaultDeps17() {
|
|
80958
83336
|
const client4 = await getConvexClient();
|
|
80959
83337
|
return {
|
|
80960
83338
|
backend: {
|
|
@@ -80976,19 +83354,19 @@ function handleArtifactError(err) {
|
|
|
80976
83354
|
});
|
|
80977
83355
|
}
|
|
80978
83356
|
async function createArtifact(chatroomId, options, deps) {
|
|
80979
|
-
const d = deps ?? await
|
|
83357
|
+
const d = deps ?? await createDefaultDeps17();
|
|
80980
83358
|
const layer = commandServicesLayerFromDeps(d);
|
|
80981
83359
|
return exports_Effect.runPromise(createArtifactEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleArtifactError(err).pipe(exports_Effect.map(() => {
|
|
80982
83360
|
return;
|
|
80983
83361
|
}))), exports_Effect.provide(layer)));
|
|
80984
83362
|
}
|
|
80985
83363
|
async function viewArtifact(chatroomId, options, deps) {
|
|
80986
|
-
const d = deps ?? await
|
|
83364
|
+
const d = deps ?? await createDefaultDeps17();
|
|
80987
83365
|
const layer = commandServicesLayerFromDeps(d);
|
|
80988
83366
|
await exports_Effect.runPromise(viewArtifactEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleArtifactError(err)), exports_Effect.provide(layer)));
|
|
80989
83367
|
}
|
|
80990
83368
|
async function viewManyArtifacts(chatroomId, options, deps) {
|
|
80991
|
-
const d = deps ?? await
|
|
83369
|
+
const d = deps ?? await createDefaultDeps17();
|
|
80992
83370
|
const layer = commandServicesLayerFromDeps(d);
|
|
80993
83371
|
await exports_Effect.runPromise(viewManyArtifactsEffect(chatroomId, options).pipe(exports_Effect.catchAll((err) => handleArtifactError(err)), exports_Effect.provide(layer)));
|
|
80994
83372
|
}
|
|
@@ -81338,7 +83716,7 @@ __export(exports_telegram, {
|
|
|
81338
83716
|
sendMessageEffect: () => sendMessageEffect,
|
|
81339
83717
|
sendMessage: () => sendMessage
|
|
81340
83718
|
});
|
|
81341
|
-
async function
|
|
83719
|
+
async function createDefaultDeps18() {
|
|
81342
83720
|
const client4 = await getConvexClient();
|
|
81343
83721
|
return {
|
|
81344
83722
|
backend: {
|
|
@@ -81420,7 +83798,7 @@ ${err.cause.message}`);
|
|
|
81420
83798
|
});
|
|
81421
83799
|
}
|
|
81422
83800
|
async function sendMessage(options, deps) {
|
|
81423
|
-
const d = deps ?? await
|
|
83801
|
+
const d = deps ?? await createDefaultDeps18();
|
|
81424
83802
|
const layer = layerFromDeps8(d);
|
|
81425
83803
|
await exports_Effect.runPromise(sendMessageEffect(options).pipe(exports_Effect.catchAll((err) => handleSendMessageError(err)), exports_Effect.provide(layer)));
|
|
81426
83804
|
}
|
|
@@ -81471,18 +83849,6 @@ var init_featureFlags = __esm(() => {
|
|
|
81471
83849
|
};
|
|
81472
83850
|
});
|
|
81473
83851
|
|
|
81474
|
-
// ../../services/backend/config/reliability.ts
|
|
81475
|
-
var HARNESS_SESSION_READY_TIMEOUT_MS = 5000, NATIVE_DELIVERY_RECONCILE_MS = 1e4, DAEMON_HEARTBEAT_INTERVAL_MS, DAEMON_HEARTBEAT_TTL_MS, AGENT_REQUEST_DEADLINE_MS = 120000, OBSERVED_FULL_PUSH_INTERVAL_MS, OBSERVED_SAFETY_POLL_MS = 30000, OBSERVED_SYNC_RECONCILE_MS, WORKSPACE_RECENCY_WINDOW_MS, WORKSPACE_LIST_RECONCILE_MS, CONNECTION_CLOSE_REQUEST_TTL_MS;
|
|
81476
|
-
var init_reliability = __esm(() => {
|
|
81477
|
-
DAEMON_HEARTBEAT_INTERVAL_MS = 5 * 60000;
|
|
81478
|
-
DAEMON_HEARTBEAT_TTL_MS = 6 * DAEMON_HEARTBEAT_INTERVAL_MS;
|
|
81479
|
-
OBSERVED_FULL_PUSH_INTERVAL_MS = 5 * 60000;
|
|
81480
|
-
OBSERVED_SYNC_RECONCILE_MS = 15 * 60000;
|
|
81481
|
-
WORKSPACE_RECENCY_WINDOW_MS = 7 * 24 * 60 * 60 * 1000;
|
|
81482
|
-
WORKSPACE_LIST_RECONCILE_MS = 60 * 60 * 1000;
|
|
81483
|
-
CONNECTION_CLOSE_REQUEST_TTL_MS = 10 * 60000;
|
|
81484
|
-
});
|
|
81485
|
-
|
|
81486
83852
|
// src/commands/machine/daemon-start/command-event-types.ts
|
|
81487
83853
|
function isDaemonCommandEventType(value) {
|
|
81488
83854
|
return DAEMON_COMMAND_EVENT_TYPES.includes(value);
|
|
@@ -96924,7 +99290,7 @@ async function emitPhase(deps, event, phase, detail) {
|
|
|
96924
99290
|
detail
|
|
96925
99291
|
});
|
|
96926
99292
|
}
|
|
96927
|
-
function
|
|
99293
|
+
function sleep6(ms) {
|
|
96928
99294
|
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
96929
99295
|
}
|
|
96930
99296
|
async function waitForHarnessSessionId(deps, event, pid) {
|
|
@@ -96946,7 +99312,7 @@ async function waitForHarnessSessionId(deps, event, pid) {
|
|
|
96946
99312
|
if (slot?.harnessSessionId) {
|
|
96947
99313
|
return slot.harnessSessionId;
|
|
96948
99314
|
}
|
|
96949
|
-
await
|
|
99315
|
+
await sleep6(100);
|
|
96950
99316
|
}
|
|
96951
99317
|
await deps.session.backend.mutation(api.machines.emitHarnessSessionTimeout, {
|
|
96952
99318
|
sessionId: deps.session.sessionId,
|
|
@@ -98454,7 +100820,7 @@ function logWaitingForShutdown(pid) {
|
|
|
98454
100820
|
function logDaemonAlreadyRunning(pid) {
|
|
98455
100821
|
console.error(`❌ Daemon already running for ${getConvexUrl()} (PID: ${pid})`);
|
|
98456
100822
|
}
|
|
98457
|
-
async function waitForLockOrTimeout(deadline, intervalMs,
|
|
100823
|
+
async function waitForLockOrTimeout(deadline, intervalMs, sleep7) {
|
|
98458
100824
|
let loggedWait = false;
|
|
98459
100825
|
while (Date.now() < deadline) {
|
|
98460
100826
|
if (tryAcquireLock()) {
|
|
@@ -98465,16 +100831,16 @@ async function waitForLockOrTimeout(deadline, intervalMs, sleep6) {
|
|
|
98465
100831
|
logWaitingForShutdown(pid);
|
|
98466
100832
|
loggedWait = true;
|
|
98467
100833
|
}
|
|
98468
|
-
await
|
|
100834
|
+
await sleep7(intervalMs);
|
|
98469
100835
|
}
|
|
98470
100836
|
return false;
|
|
98471
100837
|
}
|
|
98472
100838
|
async function acquireLockWithRetry(options) {
|
|
98473
100839
|
const intervalMs = options?.intervalMs ?? LOCK_RETRY_INTERVAL_MS;
|
|
98474
100840
|
const maxWaitMs = options?.maxWaitMs ?? LOCK_RETRY_MAX_WAIT_MS;
|
|
98475
|
-
const
|
|
100841
|
+
const sleep7 = options?.sleep ?? ((ms) => new Promise((resolve4) => setTimeout(resolve4, ms)));
|
|
98476
100842
|
const deadline = Date.now() + maxWaitMs;
|
|
98477
|
-
if (await waitForLockOrTimeout(deadline, intervalMs,
|
|
100843
|
+
if (await waitForLockOrTimeout(deadline, intervalMs, sleep7)) {
|
|
98478
100844
|
return true;
|
|
98479
100845
|
}
|
|
98480
100846
|
const { pid } = isDaemonRunning();
|
|
@@ -101470,6 +103836,104 @@ var init_start_subscriptions2 = __esm(() => {
|
|
|
101470
103836
|
init_convex_agentic_query_run_repository();
|
|
101471
103837
|
});
|
|
101472
103838
|
|
|
103839
|
+
// src/commands/machine/daemon-start/enhancer/constants.ts
|
|
103840
|
+
var ENHANCER_AGENT_ROLE = "enhancer";
|
|
103841
|
+
|
|
103842
|
+
// src/commands/machine/daemon-start/enhancer/job-subscriber.ts
|
|
103843
|
+
function startEnhancerJobSubscriber(sessionId, machineId, convexUrl, backend2, wsClient2, agentServices) {
|
|
103844
|
+
const inFlight = new Set;
|
|
103845
|
+
const unsub = wsClient2.onUpdate(api.daemon.enhancer.index.pendingForMachine, { sessionId, machineId }, (jobs) => {
|
|
103846
|
+
for (const job of jobs ?? []) {
|
|
103847
|
+
if (inFlight.has(job.jobId))
|
|
103848
|
+
continue;
|
|
103849
|
+
inFlight.add(job.jobId);
|
|
103850
|
+
(async () => {
|
|
103851
|
+
let claimed = false;
|
|
103852
|
+
let chatroomId = job.chatroomId;
|
|
103853
|
+
let jobId = job.jobId;
|
|
103854
|
+
try {
|
|
103855
|
+
const claim = await backend2.mutation(api.daemon.enhancer.index.claimForSpawn, {
|
|
103856
|
+
sessionId,
|
|
103857
|
+
jobId: job.jobId,
|
|
103858
|
+
machineId
|
|
103859
|
+
});
|
|
103860
|
+
if (!claim.claimed)
|
|
103861
|
+
return;
|
|
103862
|
+
claimed = true;
|
|
103863
|
+
const payload = await backend2.query(api.daemon.enhancer.index.getSpawnPayload, {
|
|
103864
|
+
sessionId,
|
|
103865
|
+
jobId: job.jobId
|
|
103866
|
+
});
|
|
103867
|
+
chatroomId = payload.chatroomId;
|
|
103868
|
+
jobId = payload.jobId;
|
|
103869
|
+
const service3 = agentServices.get(payload.agentHarness);
|
|
103870
|
+
if (!service3) {
|
|
103871
|
+
await backend2.mutation(api.web.enhancer.index.recordAttemptFailure, {
|
|
103872
|
+
sessionId,
|
|
103873
|
+
chatroomId: payload.chatroomId,
|
|
103874
|
+
jobId: payload.jobId,
|
|
103875
|
+
error: `Harness ${payload.agentHarness} not available on machine`
|
|
103876
|
+
});
|
|
103877
|
+
return;
|
|
103878
|
+
}
|
|
103879
|
+
const spawnResult = await service3.spawn({
|
|
103880
|
+
workingDir: payload.workingDir,
|
|
103881
|
+
prompt: createSpawnPrompt(payload.taskEnvelope),
|
|
103882
|
+
systemPrompt: payload.systemPrompt,
|
|
103883
|
+
model: payload.model,
|
|
103884
|
+
context: {
|
|
103885
|
+
machineId,
|
|
103886
|
+
chatroomId: payload.chatroomId,
|
|
103887
|
+
role: ENHANCER_AGENT_ROLE
|
|
103888
|
+
},
|
|
103889
|
+
resolvedConvexUrl: convexUrl
|
|
103890
|
+
});
|
|
103891
|
+
await new Promise((resolve4) => {
|
|
103892
|
+
spawnResult.onExit(() => resolve4());
|
|
103893
|
+
});
|
|
103894
|
+
const status3 = await backend2.query(api.web.enhancer.index.getJob, {
|
|
103895
|
+
sessionId,
|
|
103896
|
+
chatroomId: payload.chatroomId,
|
|
103897
|
+
jobId: payload.jobId
|
|
103898
|
+
});
|
|
103899
|
+
if (status3?.status === "running") {
|
|
103900
|
+
await backend2.mutation(api.web.enhancer.index.recordAttemptFailure, {
|
|
103901
|
+
sessionId,
|
|
103902
|
+
chatroomId: payload.chatroomId,
|
|
103903
|
+
jobId: payload.jobId,
|
|
103904
|
+
error: "Agent exited without completing enhancer job"
|
|
103905
|
+
});
|
|
103906
|
+
}
|
|
103907
|
+
} catch (err) {
|
|
103908
|
+
console.warn("[enhancer] spawn error:", err instanceof Error ? err.message : String(err));
|
|
103909
|
+
if (claimed) {
|
|
103910
|
+
await backend2.mutation(api.web.enhancer.index.recordAttemptFailure, {
|
|
103911
|
+
sessionId,
|
|
103912
|
+
chatroomId,
|
|
103913
|
+
jobId,
|
|
103914
|
+
error: err instanceof Error ? err.message : String(err)
|
|
103915
|
+
});
|
|
103916
|
+
}
|
|
103917
|
+
} finally {
|
|
103918
|
+
inFlight.delete(job.jobId);
|
|
103919
|
+
}
|
|
103920
|
+
})();
|
|
103921
|
+
}
|
|
103922
|
+
}, (err) => console.warn("[enhancer] subscription error:", err));
|
|
103923
|
+
return { stop: unsub };
|
|
103924
|
+
}
|
|
103925
|
+
var init_job_subscriber = __esm(() => {
|
|
103926
|
+
init_api3();
|
|
103927
|
+
});
|
|
103928
|
+
|
|
103929
|
+
// src/commands/machine/daemon-start/enhancer/start-subscriptions.ts
|
|
103930
|
+
function startEnhancerSubscriptions(sessionId, machineId, convexUrl, backend2, wsClient2, agentServices) {
|
|
103931
|
+
return startEnhancerJobSubscriber(sessionId, machineId, convexUrl, backend2, wsClient2, agentServices);
|
|
103932
|
+
}
|
|
103933
|
+
var init_start_subscriptions3 = __esm(() => {
|
|
103934
|
+
init_job_subscriber();
|
|
103935
|
+
});
|
|
103936
|
+
|
|
101473
103937
|
// src/commands/machine/daemon-start/file-content-classifier.ts
|
|
101474
103938
|
function extensionOf(path3) {
|
|
101475
103939
|
const lastDot = path3.lastIndexOf(".");
|
|
@@ -108912,7 +111376,7 @@ async function discoverModelsForHarness(harness, service3) {
|
|
|
108912
111376
|
async function discoverModels(agentServices) {
|
|
108913
111377
|
return exports_Effect.runPromise(discoverModelsEffect(agentServices));
|
|
108914
111378
|
}
|
|
108915
|
-
function
|
|
111379
|
+
function createDefaultDeps19() {
|
|
108916
111380
|
return {
|
|
108917
111381
|
backend: {
|
|
108918
111382
|
mutation: async () => {
|
|
@@ -109250,7 +111714,7 @@ var init_init2 = __esm(() => {
|
|
|
109250
111714
|
convexUrl,
|
|
109251
111715
|
agentServices,
|
|
109252
111716
|
cachedModels,
|
|
109253
|
-
deps:
|
|
111717
|
+
deps: createDefaultDeps19()
|
|
109254
111718
|
});
|
|
109255
111719
|
yield* registerEventListenersEffect().pipe(exports_Effect.provide(daemonSessionToLayers(init2)));
|
|
109256
111720
|
yield* logStartupEffect(cachedModels).pipe(exports_Effect.provide(daemonSessionToLayers(init2)));
|
|
@@ -112217,6 +114681,7 @@ var init_command_loop = __esm(() => {
|
|
|
112217
114681
|
init_daemon_services();
|
|
112218
114682
|
init_start_subscriptions();
|
|
112219
114683
|
init_start_subscriptions2();
|
|
114684
|
+
init_start_subscriptions3();
|
|
112220
114685
|
init_file_content_subscription();
|
|
112221
114686
|
init_file_tree_subscription();
|
|
112222
114687
|
init_file_write_subscription();
|
|
@@ -112403,6 +114868,7 @@ var init_command_loop = __esm(() => {
|
|
|
112403
114868
|
}, wsClient2, activeSessions, harnesses);
|
|
112404
114869
|
aqPendingPromptSubscriptionHandle = aqHandles.pendingPromptSubscriptionHandle;
|
|
112405
114870
|
aqPendingHarnessSessionSubscriptionHandle = aqHandles.pendingHarnessSessionSubscriptionHandle;
|
|
114871
|
+
const enhancerSub = startEnhancerSubscriptions(session2.sessionId, session2.machineId, session2.convexUrl, session2.backend, wsClient2, session2.agentServices);
|
|
112406
114872
|
}
|
|
112407
114873
|
console.log(`
|
|
112408
114874
|
Listening for commands...`);
|
|
@@ -112597,7 +115063,7 @@ async function isChatroomInstalledDefault() {
|
|
|
112597
115063
|
return false;
|
|
112598
115064
|
}
|
|
112599
115065
|
}
|
|
112600
|
-
async function
|
|
115066
|
+
async function createDefaultDeps20() {
|
|
112601
115067
|
const client4 = await getConvexClient();
|
|
112602
115068
|
const fs12 = await import("fs/promises");
|
|
112603
115069
|
return {
|
|
@@ -112672,7 +115138,7 @@ After installation, run this command again.`;
|
|
|
112672
115138
|
});
|
|
112673
115139
|
}
|
|
112674
115140
|
async function installTool(options = {}, deps) {
|
|
112675
|
-
const d = deps ?? await
|
|
115141
|
+
const d = deps ?? await createDefaultDeps20();
|
|
112676
115142
|
const layer = layerFromDeps9(d);
|
|
112677
115143
|
return exports_Effect.runPromise(installToolEffect(options).pipe(exports_Effect.catchAll((err) => handleInstallError(err)), exports_Effect.provide(layer)));
|
|
112678
115144
|
}
|
|
@@ -113223,6 +115689,68 @@ handoffCommandGroup.requiredOption("--chatroom-id <id>", "Chatroom identifier").
|
|
|
113223
115689
|
console.error("❌ Message is empty");
|
|
113224
115690
|
process.exit(1);
|
|
113225
115691
|
}
|
|
115692
|
+
const shouldEnhance = options.role.toLowerCase() === "planner" && options.nextRole.toLowerCase() === "builder";
|
|
115693
|
+
if (shouldEnhance) {
|
|
115694
|
+
const { api: api3 } = await Promise.resolve().then(() => (init_api3(), exports_api));
|
|
115695
|
+
const { getConvexClient: getConvexClient2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
115696
|
+
const { getSessionId: getSessionId2 } = await Promise.resolve().then(() => (init_storage(), exports_storage));
|
|
115697
|
+
const { waitForEnhancerJob: waitForEnhancerJob2 } = await Promise.resolve().then(() => (init_wait_for_job(), exports_wait_for_job));
|
|
115698
|
+
const client4 = await getConvexClient2();
|
|
115699
|
+
const sessionId = await getSessionId2();
|
|
115700
|
+
if (sessionId) {
|
|
115701
|
+
try {
|
|
115702
|
+
const config4 = await client4.query(api3.web.enhancer.index.getConfig, {
|
|
115703
|
+
sessionId,
|
|
115704
|
+
chatroomId: options.chatroomId
|
|
115705
|
+
});
|
|
115706
|
+
if (config4 && config4.enabled) {
|
|
115707
|
+
const result = await client4.mutation(api3.web.enhancer.index.enqueueHandoff, {
|
|
115708
|
+
sessionId,
|
|
115709
|
+
chatroomId: options.chatroomId,
|
|
115710
|
+
senderRole: options.role,
|
|
115711
|
+
targetRole: options.nextRole,
|
|
115712
|
+
content: message
|
|
115713
|
+
});
|
|
115714
|
+
const jobId = result.jobId;
|
|
115715
|
+
const outcome = await waitForEnhancerJob2(options.chatroomId, jobId, {
|
|
115716
|
+
query: (endpoint, args2) => client4.query(endpoint, args2),
|
|
115717
|
+
mutation: (endpoint, args2) => client4.mutation(endpoint, args2),
|
|
115718
|
+
getSessionId: () => Promise.resolve(sessionId),
|
|
115719
|
+
endpoints: {
|
|
115720
|
+
getJob: api3.web.enhancer.index.getJob,
|
|
115721
|
+
recordAttemptFailure: api3.web.enhancer.index.recordAttemptFailure
|
|
115722
|
+
}
|
|
115723
|
+
});
|
|
115724
|
+
if (outcome === "failed") {
|
|
115725
|
+
console.error(`
|
|
115726
|
+
❌ ERROR: Enhancer failed after all retries. No handoff was delivered.`);
|
|
115727
|
+
process.exit(1);
|
|
115728
|
+
}
|
|
115729
|
+
if (outcome === "cancelled" || outcome === "complete") {
|
|
115730
|
+
const { generateHandoffOutput: generateHandoffOutput2 } = await Promise.resolve().then(() => (init_generator(), exports_generator));
|
|
115731
|
+
const { getConvexUrl: getConvexUrl2 } = await Promise.resolve().then(() => (init_client2(), exports_client));
|
|
115732
|
+
const convexUrl = await getConvexUrl2();
|
|
115733
|
+
console.log(generateHandoffOutput2({
|
|
115734
|
+
role: options.role,
|
|
115735
|
+
nextRole: options.nextRole,
|
|
115736
|
+
chatroomId: options.chatroomId,
|
|
115737
|
+
convexUrl
|
|
115738
|
+
}));
|
|
115739
|
+
return;
|
|
115740
|
+
}
|
|
115741
|
+
}
|
|
115742
|
+
} catch (err) {
|
|
115743
|
+
const error51 = err;
|
|
115744
|
+
if (error51?.data?.code !== "ENHANCER_NOT_ENABLED") {
|
|
115745
|
+
console.error(`
|
|
115746
|
+
❌ ERROR: Enhancer interception failed`);
|
|
115747
|
+
console.error(`
|
|
115748
|
+
${error51?.data?.message ?? err.message}`);
|
|
115749
|
+
process.exit(1);
|
|
115750
|
+
}
|
|
115751
|
+
}
|
|
115752
|
+
}
|
|
115753
|
+
}
|
|
113226
115754
|
const { handoff: handoff2 } = await Promise.resolve().then(() => (init_handoff(), exports_handoff));
|
|
113227
115755
|
await handoff2(options.chatroomId, {
|
|
113228
115756
|
role: options.role,
|
|
@@ -113257,6 +115785,29 @@ agenticQueryCommand.command("complete").description("Submit the structured agent
|
|
|
113257
115785
|
result
|
|
113258
115786
|
});
|
|
113259
115787
|
});
|
|
115788
|
+
var enhancerCommand = program2.command("enhancer").description("Handoff enhancer commands");
|
|
115789
|
+
enhancerCommand.command("complete").description("Submit the enhanced handoff markdown").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--job-id <id>", "Enhancer job identifier").action(async (options) => {
|
|
115790
|
+
await maybeRequireAuth();
|
|
115791
|
+
const { decode: decode5 } = await Promise.resolve().then(() => exports_decode);
|
|
115792
|
+
const stdinContent = await readStdin();
|
|
115793
|
+
let body;
|
|
115794
|
+
try {
|
|
115795
|
+
const { ENHANCER_STDIN_DELIMITER: ENHANCER_STDIN_DELIMITER2, HANDOFF_MESSAGE_MARKER: HANDOFF_MESSAGE_MARKER2, validateStdinHeredocBody: validateStdinHeredocBody2 } = await Promise.resolve().then(() => (init_stdin_heredoc(), exports_stdin_heredoc));
|
|
115796
|
+
const decoded = decode5(stdinContent, { singleParam: "result" });
|
|
115797
|
+
body = decoded.result;
|
|
115798
|
+
body = body.replace(new RegExp(`^(${HANDOFF_MESSAGE_MARKER2}\\s*)+`, "i"), "").trim();
|
|
115799
|
+
validateStdinHeredocBody2(body, ENHANCER_STDIN_DELIMITER2);
|
|
115800
|
+
} catch (err) {
|
|
115801
|
+
console.error(`❌ Failed to decode stdin: ${err.message}`);
|
|
115802
|
+
process.exit(1);
|
|
115803
|
+
}
|
|
115804
|
+
if (!body?.trim()) {
|
|
115805
|
+
console.error("❌ Enhanced handoff body is empty");
|
|
115806
|
+
process.exit(1);
|
|
115807
|
+
}
|
|
115808
|
+
const { enhancerComplete: enhancerComplete2 } = await Promise.resolve().then(() => (init_complete2(), exports_complete2));
|
|
115809
|
+
await enhancerComplete2(options.chatroomId, { jobId: options.jobId, enhancedContent: body });
|
|
115810
|
+
});
|
|
113260
115811
|
var backlogCommand = program2.command("backlog").description("Manage task queue and backlog");
|
|
113261
115812
|
backlogCommand.command("list").description("List backlog items").requiredOption("--chatroom-id <id>", "Chatroom identifier").requiredOption("--role <role>", "Your role").option("--limit <n>", "Maximum number of items to show").option("--sort <sort>", "Sort order: date:desc (default) | priority:desc").option("--filter <filter>", "Filter: unscored (only items without priority score)").action(async (options) => {
|
|
113262
115813
|
await maybeRequireAuth();
|
|
@@ -113541,4 +116092,4 @@ program2.hook("preAction", async (_thisCommand, actionCommand) => {
|
|
|
113541
116092
|
});
|
|
113542
116093
|
program2.parse();
|
|
113543
116094
|
|
|
113544
|
-
//# debugId=
|
|
116095
|
+
//# debugId=594320A213AD613364756E2164756E21
|