@pushpalsdev/cli 1.0.31 → 1.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/pushpals-cli.js +33 -4
  2. package/monitor-ui/+not-found.html +1 -1
  3. package/monitor-ui/_expo/static/js/web/{entry-275c5f7972e2d2f4f0422fe2213a7f89.js → entry-5e6db7139bc13703a24f952bd64faf4c.js} +2 -2
  4. package/monitor-ui/_sitemap.html +1 -1
  5. package/monitor-ui/index.html +1 -1
  6. package/monitor-ui/modal.html +1 -1
  7. package/package.json +1 -1
  8. package/runtime/prompts/localbuddy/localbuddy_planner_git_diff_section.md +0 -1
  9. package/runtime/prompts/localbuddy/localbuddy_planner_git_status_section.md +0 -1
  10. package/runtime/prompts/localbuddy/localbuddy_planner_output_contract.md +1 -0
  11. package/runtime/prompts/remotebuddy/autonomy_ideation_system_prompt.md +31 -30
  12. package/runtime/prompts/remotebuddy/autonomy_scoring_system_prompt.md +2 -2
  13. package/runtime/prompts/remotebuddy/context_packer_user_prompt.md +1 -0
  14. package/runtime/prompts/remotebuddy/remotebuddy_system_prompt.md +1 -0
  15. package/runtime/prompts/review_agent/review_prompt_template.md +1 -0
  16. package/runtime/prompts/review_agent/reviewer.md +6 -4
  17. package/runtime/prompts/workerpals/commit_message_prompt.md +3 -0
  18. package/runtime/prompts/workerpals/miniswe_broker_system_prompt.md +10 -9
  19. package/runtime/prompts/workerpals/miniswe_strict_tool_use_guidance.md +1 -0
  20. package/runtime/prompts/workerpals/openai_codex_runtime_policy_appendix.md +1 -0
  21. package/runtime/prompts/workerpals/openai_codex_task_execute_system_prompt.md +2 -0
  22. package/runtime/prompts/workerpals/task_quality_critic_system_prompt.md +3 -2
  23. package/runtime/sandbox/apps/workerpals/src/backends/openai_codex_backend.ts +4 -4
  24. package/runtime/sandbox/apps/workerpals/src/backends/openhands_task_execute.ts +1 -4
  25. package/runtime/sandbox/apps/workerpals/src/common/execution_utils.ts +5 -3
  26. package/runtime/sandbox/apps/workerpals/src/common/generic_python_executor.ts +1 -4
  27. package/runtime/sandbox/apps/workerpals/src/common/worktree_cleanup.ts +3 -2
  28. package/runtime/sandbox/apps/workerpals/src/docker_executor.ts +42 -27
  29. package/runtime/sandbox/apps/workerpals/src/execute_job.ts +7 -7
  30. package/runtime/sandbox/apps/workerpals/src/job_runner.ts +7 -4
  31. package/runtime/sandbox/apps/workerpals/src/workerpals_main.ts +2 -1
  32. package/runtime/sandbox/packages/shared/src/autonomy_policy.ts +8 -3
  33. package/runtime/sandbox/packages/shared/src/communication.ts +19 -8
  34. package/runtime/sandbox/packages/shared/src/config.ts +9 -24
  35. package/runtime/sandbox/packages/shared/src/config_template_parity.ts +5 -6
  36. package/runtime/sandbox/packages/shared/src/git_backend.ts +5 -9
  37. package/runtime/sandbox/packages/shared/src/local_network.ts +3 -1
  38. package/runtime/sandbox/packages/shared/src/localbuddy_runtime.ts +4 -5
  39. package/runtime/sandbox/packages/shared/src/vision.ts +6 -2
  40. package/runtime/sandbox/prompts/workerpals/commit_message_prompt.md +3 -0
  41. package/runtime/sandbox/prompts/workerpals/miniswe_broker_system_prompt.md +10 -9
  42. package/runtime/sandbox/prompts/workerpals/miniswe_strict_tool_use_guidance.md +1 -0
  43. package/runtime/sandbox/prompts/workerpals/openai_codex_runtime_policy_appendix.md +1 -0
  44. package/runtime/sandbox/prompts/workerpals/openai_codex_task_execute_system_prompt.md +2 -0
  45. package/runtime/sandbox/prompts/workerpals/task_quality_critic_system_prompt.md +3 -2
  46. package/runtime/vision.example.md +24 -5
@@ -2,38 +2,39 @@ You are RemoteBuddyAutonomousEngine ideation planner for a monorepo.
2
2
  Generate objective candidates only from provided evidence signals.
3
3
  Return strict JSON with this shape:
4
4
  {
5
- "candidates": [{
6
- "id": "cand_...",
7
- "title": "...",
8
- "objective_type": "flaky_test|lint_fix|type_fix|small_refactor|feature_small|feature_medium|feature_large|docs|dep_bump",
9
- "problem_statement": "...",
10
- "trigger_type": "test_failure|lint_failure|typecheck_failure|queue_health|regret_signal",
11
- "component_area": "apps/server|apps/remotebuddy|apps/workerpals|apps/client|packages/protocol|packages/shared|tests/integration|tests/unit",
12
- "target_paths": ["repo/relative/path"],
13
- "scope": { "read_anywhere": false, "write_globs": ["repo/relative/glob"] },
14
- "risk_level": "low|medium|high",
15
- "expected_validation": ["command"],
16
- "estimated_effort": "small|medium|large",
17
- "why_now_signal_ids": ["sig_x"],
18
- "confidence": 0.0,
19
- "vision_alignment_reason": "...",
20
- "vision_section_refs": ["6", "9"],
21
- "feature_hypotheses": ["feature idea A", "feature idea B"],
22
- "engine_trial": {
23
- "building_block_id": "short_id",
24
- "algorithm": "algorithm label",
25
- "source": "llm|engine_mapped|engine_fallback",
26
- "score": 0.0,
27
- "objective_ids": ["objective_id"],
28
- "gap_ids": ["gap_id"],
29
- "summary": "short summary",
30
- "hypothesis": "short hypothesis"
31
- },
32
- "requires_user_input": false,
33
- "question_if_blocked": ""
34
- }]
5
+ "candidates": [{
6
+ "id": "cand\_...",
7
+ "title": "...",
8
+ "objective_type": "flaky_test|lint_fix|type_fix|small_refactor|feature_small|feature_medium|feature_large|docs|dep_bump",
9
+ "problem_statement": "...",
10
+ "trigger_type": "test_failure|lint_failure|typecheck_failure|queue_health|regret_signal",
11
+ "component_area": "apps/server|apps/remotebuddy|apps/workerpals|apps/client|packages/protocol|packages/shared|tests/integration|tests/unit",
12
+ "target_paths": ["repo/relative/path"],
13
+ "scope": { "read_anywhere": false, "write_globs": ["repo/relative/glob"] },
14
+ "risk_level": "low|medium|high",
15
+ "expected_validation": ["command"],
16
+ "estimated_effort": "small|medium|large",
17
+ "why_now_signal_ids": ["sig_x"],
18
+ "confidence": 0.0,
19
+ "vision_alignment_reason": "...",
20
+ "vision_section_refs": ["6", "9"],
21
+ "feature_hypotheses": ["feature idea A", "feature idea B"],
22
+ "engine_trial": {
23
+ "building_block_id": "short_id",
24
+ "algorithm": "algorithm label",
25
+ "source": "llm|engine_mapped|engine_fallback",
26
+ "score": 0.0,
27
+ "objective_ids": ["objective_id"],
28
+ "gap_ids": ["gap_id"],
29
+ "summary": "short summary",
30
+ "hypothesis": "short hypothesis"
31
+ },
32
+ "requires_user_input": false,
33
+ "question_if_blocked": ""
34
+ }]
35
35
  }
36
36
  Constraints:
37
+
37
38
  - You will receive `vision.markdown`; use it as inspiration and prioritize candidates that clearly advance that vision.
38
39
  - You will also receive `vision.sections`; if numbered sections are present, cite at least one section number in `vision_section_refs`.
39
40
  - You will also receive `vision.key_items`; prioritize alignment with `priorities` + `objectives`, respect `guardrails` + `constraints`, and avoid `non_goals`.
@@ -1,6 +1,6 @@
1
1
  Score each candidate and return top ids.
2
2
  Return strict JSON:
3
3
  {
4
- "scores": [{ "id": "cand_1", "llm_score": 0.0, "rationale": "..." }],
5
- "top_candidate_ids": ["cand_1", "cand_2", "cand_3"]
4
+ "scores": [{ "id": "cand_1", "llm_score": 0.0, "rationale": "..." }],
5
+ "top_candidate_ids": ["cand_1", "cand_2", "cand_3"]
6
6
  }
@@ -5,6 +5,7 @@ Current packed memory:
5
5
  {{current_memory}}
6
6
 
7
7
  Update the packed memory with maximal fidelity. Requirements:
8
+
8
9
  - Preserve concrete instructions, constraints, IDs, file paths, env vars, and error text.
9
10
  - Keep conflicting details if present; do not silently discard.
10
11
  - Keep output under {{memory_char_budget}} characters.
@@ -23,6 +23,7 @@ Intent taxonomy (choose the single best fit):
23
23
  - `other` — do NOT use `other` with `requires_worker=false`. `other` must always have `requires_worker=true`. When in doubt, prefer `code_change`.
24
24
 
25
25
  Classification rules (applied in order):
26
+
26
27
  1. Action verb present (add, fix, update, implement, create, remove, test, run, build, configure, refactor, improve, etc.) → `code_change` + `requires_worker=true`
27
28
  2. File/test/config/component reference + no explicit read-only ask → `code_change` + `requires_worker=true`
28
29
  3. Read-only analysis explicitly requested → `analysis` + `requires_worker=false`
@@ -11,6 +11,7 @@ Pull Request: #{{pr_number}} - {{pr_title}}
11
11
  Branch: {{head_ref}} -> {{base_ref}}
12
12
 
13
13
  Diff:
14
+
14
15
  ```diff
15
16
  {{diff}}
16
17
  ```
@@ -7,6 +7,7 @@ Return an objective quality score and specific, actionable feedback. The ReviewA
7
7
  ## Rating Criteria
8
8
 
9
9
  ### 9.0-10.0: Distinguished Engineer quality
10
+
10
11
  - Code is correct, complete, and production-ready with zero known defects
11
12
  - All edge cases and error paths are handled explicitly
12
13
  - Tests cover both positive (happy path) and negative (failure/edge) cases with meaningful assertions
@@ -21,6 +22,7 @@ Return an objective quality score and specific, actionable feedback. The ReviewA
21
22
  ### 1.0-6.9: Not production-ready - list specific issues and remediation steps
22
23
 
23
24
  Common rejection reasons:
25
+
24
26
  - Missing negative test assertions
25
27
  - Incomplete error handling
26
28
  - Tests that pass trivially (no real assertions)
@@ -32,8 +34,8 @@ Common rejection reasons:
32
34
 
33
35
  Respond with a JSON object only (no markdown wrapper):
34
36
  {
35
- "score": <number 1.0-10.0>,
36
- "summary": "<one sentence verdict>",
37
- "issues": ["<issue 1>", "<issue 2>", ...],
38
- "fix_instruction": "<precise instruction for the worker to fix all issues - this will be sent directly to the WorkerPal as its task>"
37
+ "score": <number 1.0-10.0>,
38
+ "summary": "<one sentence verdict>",
39
+ "issues": ["<issue 1>", "<issue 2>", ...],
40
+ "fix_instruction": "<precise instruction for the worker to fix all issues - this will be sent directly to the WorkerPal as its task>"
39
41
  }
@@ -10,6 +10,7 @@ Output only the raw commit message text — no markdown fences, no explanation,
10
10
  - <specific implementation detail>
11
11
 
12
12
  Tests:
13
+
13
14
  - <test runner command>
14
15
 
15
16
  ## Writing rules
@@ -25,12 +26,14 @@ Background context: "can you add one more unit test for localbuddy"
25
26
 
26
27
  Bad (copies instruction / uses planning language):
27
28
  {{type}}({{area}}): lets add one more unit test for localbuddy
29
+
28
30
  - At least one new unit test is added validating a meaningful LocalBuddy behavior.
29
31
  - All existing and new tests pass.
30
32
  - No unrelated files are modified.
31
33
 
32
34
  Good (reads the diff):
33
35
  {{type}}({{area}}): add unit test for LocalBuddy request routing and error response handling
36
+
34
37
  - add test case in localbuddy.test.ts asserting router returns 404 for unknown tool calls
35
38
  - add negative test for malformed request payload returning 400 with error message
36
39
  - extract shared test fixtures into testHelpers.ts to reduce duplication
@@ -5,18 +5,19 @@ Repository root: {{repo}}
5
5
 
6
6
  Output format (STRICT JSON, no markdown, no extra keys unless specified):
7
7
  {
8
- "actions": [
9
- {"type":"read_file","path":"README.md"},
10
- {"type":"append_line","path":"README.md","line":"..."},
11
- {"type":"replace_text_once","path":"x","old":"a","new":"b"},
12
- {"type":"write_file","path":"x","content":"..."},
13
- {"type":"run_shell","command":"git status --porcelain"}
14
- ],
15
- "done": false,
16
- "note": "short explanation"
8
+ "actions": [
9
+ {"type":"read_file","path":"README.md"},
10
+ {"type":"append_line","path":"README.md","line":"..."},
11
+ {"type":"replace_text_once","path":"x","old":"a","new":"b"},
12
+ {"type":"write_file","path":"x","content":"..."},
13
+ {"type":"run_shell","command":"git status --porcelain"}
14
+ ],
15
+ "done": false,
16
+ "note": "short explanation"
17
17
  }
18
18
 
19
19
  Rules:
20
+
20
21
  - Keep actions minimal and directly relevant.
21
22
  - JSON syntax must be exact: use ":" between keys and values, never ",".
22
23
  - Use double quotes for all keys and string values.
@@ -1,4 +1,5 @@
1
1
  CRITICAL: You must use tools to make progress.
2
+
2
3
  - Use the environment's tools (file read/list/search, and file edit/write/patch) to inspect and modify the repo.
3
4
  - Do NOT only describe what you would do; actually do it.
4
5
  - Avoid broad scans; choose one target file quickly.
@@ -1,4 +1,5 @@
1
1
  Runtime policy guardrails (mandatory):
2
+
2
3
  - Codex CLI is required infrastructure in this environment.
3
4
  - Never bypass Codex usage by changing tests/code expectations.
4
5
  - If Codex CLI auth/execution is unavailable, hard-fail and stop.
@@ -1,12 +1,14 @@
1
1
  You are PushPals WorkerPal running via the OpenAI Codex CLI backend.
2
2
 
3
3
  Non-negotiable runtime invariants:
4
+
4
5
  - Codex CLI is required infrastructure in this environment.
5
6
  - Do not modify tests or production code to bypass, stub, or remove Codex CLI usage due to assumed environment limitations.
6
7
  - Do not "adapt around" missing Codex access by rewriting coverage or behavior expectations.
7
8
  - If Codex CLI authentication/execution is unavailable, fail loudly with a clear error and stop.
8
9
 
9
10
  Execution rules:
11
+
10
12
  - Keep edits minimal, correct, and scoped to the requested task.
11
13
  - Read relevant files before editing, then run focused validation.
12
14
  - Report blockers explicitly; do not hide platform/runtime issues with workaround edits.
@@ -2,8 +2,9 @@ You are a strict code-review critic for worker-generated patches.
2
2
  Return exactly one JSON object with keys:
3
3
  {"score": <0-10 number>, "findings": [string], "must_fix": [string], "revision_guidance": string}
4
4
  Scoring rubric:
5
+
5
6
  - 10: complete, correct, and robust with strong validation coverage.
6
7
  - 8-9: good quality with minor non-blocking issues.
7
8
  - <=7: requires revision before commit.
8
- must_fix must list blocking issues only.
9
- Do not include markdown or prose outside JSON.
9
+ must_fix must list blocking issues only.
10
+ Do not include markdown or prose outside JSON.
@@ -27,14 +27,14 @@ function warmupProbeCommand(sharedVenvPython: string): string {
27
27
  'AUTH_MODE="$(printf %s "$AUTH_MODE_RAW" | tr "[:upper:]" "[:lower:]")"; ' +
28
28
  'if [ ! -x "$PY" ]; then PY="$(command -v python3 || command -v python || true)"; fi; ' +
29
29
  '[ -n "$PY" ] || { echo "python runtime not found" >&2; exit 1; }; ' +
30
- 'if command -v bunx >/dev/null 2>&1; then ' +
30
+ "if command -v bunx >/dev/null 2>&1; then " +
31
31
  ' CODEX_CMD="bunx --yes @openai/codex"; ' +
32
- 'elif command -v codex >/dev/null 2>&1; then ' +
32
+ "elif command -v codex >/dev/null 2>&1; then " +
33
33
  ' CODEX_CMD="codex"; ' +
34
- 'else ' +
34
+ "else " +
35
35
  ' echo "Neither bunx nor codex was found in PATH" >&2; ' +
36
36
  " exit 1; " +
37
- 'fi; ' +
37
+ "fi; " +
38
38
  'sh -lc "$CODEX_CMD --version"; ' +
39
39
  'NEED_LOGIN="0"; ' +
40
40
  'if [ "$AUTH_MODE" = "chatgpt" ] || [ "$AUTH_MODE" = "chatgpt_login" ] || [ "$AUTH_MODE" = "subscription" ]; then NEED_LOGIN="1"; fi; ' +
@@ -55,10 +55,7 @@ function estimateJobTokenUsage(
55
55
  };
56
56
  }
57
57
 
58
- function coerceJobTokenUsage(
59
- value: unknown,
60
- fallback: JobTokenUsage,
61
- ): JobTokenUsage {
58
+ function coerceJobTokenUsage(value: unknown, fallback: JobTokenUsage): JobTokenUsage {
62
59
  if (!value || typeof value !== "object" || Array.isArray(value)) {
63
60
  return fallback;
64
61
  }
@@ -16,8 +16,7 @@ export function resolveOutputCompactionPolicy(
16
16
  const maxOutputChars = Number(overrides.maxOutputChars ?? worker.outputMaxChars);
17
17
  const maxOutputLines = Number(overrides.maxOutputLines ?? worker.outputMaxLines);
18
18
  const maxOutputHeadLines = Number(overrides.maxOutputHeadLines ?? worker.outputMaxHeadLines);
19
- const executorResultPrefixRaw =
20
- overrides.executorResultPrefix ?? worker.executorResultPrefix;
19
+ const executorResultPrefixRaw = overrides.executorResultPrefix ?? worker.executorResultPrefix;
21
20
  const executorResultPrefix =
22
21
  typeof executorResultPrefixRaw === "string" && executorResultPrefixRaw.length > 0
23
22
  ? executorResultPrefixRaw
@@ -42,7 +41,10 @@ export function resolveOutputCompactionPolicy(
42
41
 
43
42
  // ---- Output truncation -------------------------------------------------------
44
43
 
45
- export function compactJobOutput(text: string, policyOverrides: Partial<OutputCompactionPolicy> = {}): string {
44
+ export function compactJobOutput(
45
+ text: string,
46
+ policyOverrides: Partial<OutputCompactionPolicy> = {},
47
+ ): string {
46
48
  if (!text) return "";
47
49
  const policy = resolveOutputCompactionPolicy(policyOverrides);
48
50
  const maxOutputChars = policy.maxOutputChars;
@@ -58,10 +58,7 @@ function estimateJobTokenUsage(
58
58
  };
59
59
  }
60
60
 
61
- function coerceJobTokenUsage(
62
- value: unknown,
63
- fallback: JobTokenUsage,
64
- ): JobTokenUsage {
61
+ function coerceJobTokenUsage(value: unknown, fallback: JobTokenUsage): JobTokenUsage {
65
62
  if (!value || typeof value !== "object" || Array.isArray(value)) {
66
63
  return fallback;
67
64
  }
@@ -39,7 +39,9 @@ export async function forceDeleteWorktreePath(
39
39
  const retries = Math.max(1, Math.floor(options.retries ?? 5));
40
40
  const delayMs = Math.max(0, Math.floor(options.delayMs ?? 120));
41
41
  const sleep = options.sleepFn ?? defaultSleep;
42
- const removePath = options.removeFn ?? ((targetPath: string) => rmSync(targetPath, { recursive: true, force: true }));
42
+ const removePath =
43
+ options.removeFn ??
44
+ ((targetPath: string) => rmSync(targetPath, { recursive: true, force: true }));
43
45
  const pathExists = options.existsFn ?? ((targetPath: string) => existsSync(targetPath));
44
46
  let lastError = "";
45
47
 
@@ -63,4 +65,3 @@ export async function forceDeleteWorktreePath(
63
65
  ...(lastError ? { lastError } : {}),
64
66
  };
65
67
  }
66
-
@@ -75,7 +75,10 @@ function resolveDockerExecutable(): string {
75
75
  return process.platform === "win32" ? "docker.exe" : "docker";
76
76
  }
77
77
 
78
- function resolveWorkerpalSandboxBuildContext(repoRoot: string): { root: string; dockerfilePath: string } {
78
+ function resolveWorkerpalSandboxBuildContext(repoRoot: string): {
79
+ root: string;
80
+ dockerfilePath: string;
81
+ } {
79
82
  const configuredRoot = String(process.env.PUSHPALS_WORKERPALS_SANDBOX_ROOT ?? "").trim();
80
83
  const sandboxRoot = configuredRoot || repoRoot;
81
84
  const dockerfilePath = configuredRoot
@@ -446,14 +449,11 @@ export class DockerExecutor {
446
449
  });
447
450
  await prune.exited;
448
451
 
449
- proc = Bun.spawn(
450
- ["git", "worktree", "add", "--force", "--detach", worktreePath, baseRef],
451
- {
452
- cwd: this.options.repo,
453
- stdout: "pipe",
454
- stderr: "pipe",
455
- },
456
- );
452
+ proc = Bun.spawn(["git", "worktree", "add", "--force", "--detach", worktreePath, baseRef], {
453
+ cwd: this.options.repo,
454
+ stdout: "pipe",
455
+ stderr: "pipe",
456
+ });
457
457
  exitCode = await proc.exited;
458
458
  stdout = await new Response(proc.stdout).text();
459
459
  stderr = await new Response(proc.stderr).text();
@@ -713,7 +713,10 @@ export class DockerExecutor {
713
713
 
714
714
  args.push("--entrypoint", "/bin/sh", this.options.imageName, "-lc", startupCmd);
715
715
 
716
- const proc = Bun.spawn([resolveDockerExecutable(), ...args], { stdout: "pipe", stderr: "pipe" });
716
+ const proc = Bun.spawn([resolveDockerExecutable(), ...args], {
717
+ stdout: "pipe",
718
+ stderr: "pipe",
719
+ });
717
720
  const [exitCode, stdout, stderr] = await Promise.all([
718
721
  proc.exited,
719
722
  new Response(proc.stdout).text(),
@@ -814,10 +817,13 @@ export class DockerExecutor {
814
817
  stderr: string;
815
818
  exitCode: number;
816
819
  }> {
817
- const proc = Bun.spawn([resolveDockerExecutable(), "exec", this.warmContainerName, "/bin/sh", "-lc", command], {
818
- stdout: "pipe",
819
- stderr: "pipe",
820
- });
820
+ const proc = Bun.spawn(
821
+ [resolveDockerExecutable(), "exec", this.warmContainerName, "/bin/sh", "-lc", command],
822
+ {
823
+ stdout: "pipe",
824
+ stderr: "pipe",
825
+ },
826
+ );
821
827
  const [stdout, stderr, exitCode] = await Promise.all([
822
828
  new Response(proc.stdout).text(),
823
829
  new Response(proc.stderr).text(),
@@ -854,10 +860,13 @@ export class DockerExecutor {
854
860
  }
855
861
 
856
862
  private async readWarmContainerLogs(tail = 160): Promise<string> {
857
- const proc = Bun.spawn([resolveDockerExecutable(), "logs", "--tail", String(tail), this.warmContainerName], {
858
- stdout: "pipe",
859
- stderr: "pipe",
860
- });
863
+ const proc = Bun.spawn(
864
+ [resolveDockerExecutable(), "logs", "--tail", String(tail), this.warmContainerName],
865
+ {
866
+ stdout: "pipe",
867
+ stderr: "pipe",
868
+ },
869
+ );
861
870
  const [stdout, stderr, exitCode] = await Promise.all([
862
871
  new Response(proc.stdout).text(),
863
872
  new Response(proc.stderr).text(),
@@ -1555,11 +1564,14 @@ export class DockerExecutor {
1555
1564
  `[DockerExecutor] Worktree path already exists; forcing cleanup before create: ${worktreePath}`,
1556
1565
  );
1557
1566
 
1558
- const unregister = Bun.spawn(["git", "worktree", "remove", "--force", "--force", worktreePath], {
1559
- cwd: this.options.repo,
1560
- stdout: "pipe",
1561
- stderr: "pipe",
1562
- });
1567
+ const unregister = Bun.spawn(
1568
+ ["git", "worktree", "remove", "--force", "--force", worktreePath],
1569
+ {
1570
+ cwd: this.options.repo,
1571
+ stdout: "pipe",
1572
+ stderr: "pipe",
1573
+ },
1574
+ );
1563
1575
  await unregister.exited;
1564
1576
 
1565
1577
  const prune = Bun.spawn(["git", "worktree", "prune"], {
@@ -1777,10 +1789,13 @@ export class DockerExecutor {
1777
1789
  * Check if the Docker image exists locally
1778
1790
  */
1779
1791
  private async imageExists(): Promise<boolean> {
1780
- const proc = Bun.spawn([resolveDockerExecutable(), "image", "inspect", this.options.imageName], {
1781
- stdout: "pipe",
1782
- stderr: "pipe",
1783
- });
1792
+ const proc = Bun.spawn(
1793
+ [resolveDockerExecutable(), "image", "inspect", this.options.imageName],
1794
+ {
1795
+ stdout: "pipe",
1796
+ stderr: "pipe",
1797
+ },
1798
+ );
1784
1799
  const exitCode = await proc.exited;
1785
1800
  return exitCode === 0;
1786
1801
  }
@@ -173,7 +173,10 @@ export function buildQualityGateRevisionIssues(
173
173
  if (!critic || critic.score >= qualityCriticMinScore) {
174
174
  return [...normalizedQualityIssues];
175
175
  }
176
- const merged = [...normalizedQualityIssues, ...buildCriticRevisionIssues(critic, qualityCriticMinScore)];
176
+ const merged = [
177
+ ...normalizedQualityIssues,
178
+ ...buildCriticRevisionIssues(critic, qualityCriticMinScore),
179
+ ];
177
180
  return [...new Set(merged)];
178
181
  }
179
182
 
@@ -2569,7 +2572,8 @@ function validateTaskExecutePlanning(
2569
2572
  if (!componentArea) {
2570
2573
  return {
2571
2574
  ok: false,
2572
- message: "task.execute planning.targetPaths must resolve to a repo-relative componentArea",
2575
+ message:
2576
+ "task.execute planning.targetPaths must resolve to a repo-relative componentArea",
2573
2577
  };
2574
2578
  }
2575
2579
  if (
@@ -3056,11 +3060,7 @@ export async function executeJob(
3056
3060
  return result;
3057
3061
  }
3058
3062
 
3059
- const issues = buildQualityGateRevisionIssues(
3060
- quality.issues,
3061
- critic,
3062
- qualityCriticMinScore,
3063
- );
3063
+ const issues = buildQualityGateRevisionIssues(quality.issues, critic, qualityCriticMinScore);
3064
3064
  const issueSummary = issues.map((entry) => toSingleLine(entry, 180)).join(" | ");
3065
3065
  if (revisionAttempt >= qualityMaxAutoRevisions) {
3066
3066
  if (qualitySoftPassOnExhausted) {
@@ -67,10 +67,13 @@ echo "password=${token}"
67
67
  writeFileSync(helperPath, helperScript, { mode: 0o755 });
68
68
 
69
69
  // Remove any legacy URL rewrite rules that may have embedded token credentials.
70
- const urlRules = Bun.spawnSync(["git", "config", "--global", "--get-regexp", "^url\\..*\\.insteadOf$"], {
71
- stdout: "pipe",
72
- stderr: "pipe",
73
- });
70
+ const urlRules = Bun.spawnSync(
71
+ ["git", "config", "--global", "--get-regexp", "^url\\..*\\.insteadOf$"],
72
+ {
73
+ stdout: "pipe",
74
+ stderr: "pipe",
75
+ },
76
+ );
74
77
  if (urlRules.exitCode === 0) {
75
78
  const lines = String(urlRules.stdout ?? "")
76
79
  .split(/\r?\n/)
@@ -123,7 +123,8 @@ function buildWorkerLlmUsageEvent(
123
123
  return {
124
124
  service: "workerpals",
125
125
  sessionId,
126
- backend: String(explicitUsage.backend ?? resolveExecutor(CONFIG)).trim() || resolveExecutor(CONFIG),
126
+ backend:
127
+ String(explicitUsage.backend ?? resolveExecutor(CONFIG)).trim() || resolveExecutor(CONFIG),
127
128
  modelId: String(explicitUsage.modelId ?? llmConfig.model).trim() || llmConfig.model,
128
129
  promptTokens,
129
130
  completionTokens,
@@ -263,8 +263,9 @@ export function globBreadthScore(glob: string): number {
263
263
  const rootWide = /^[\*]/.test(glob) || glob.startsWith("**/") ? 1 : 0;
264
264
  const literalSegments = glob
265
265
  .split("/")
266
- .filter((segment) => segment.length > 0 && !segment.includes("*") && !segment.includes("?"))
267
- .length;
266
+ .filter(
267
+ (segment) => segment.length > 0 && !segment.includes("*") && !segment.includes("?"),
268
+ ).length;
268
269
  const shallowPenalty = Math.max(0, 2 - Math.min(literalSegments, 2));
269
270
  return 4 * hasGlobStar + 2 * rootWide + Math.min(4, wildcardCount) + shallowPenalty;
270
271
  }
@@ -343,7 +344,11 @@ export function validateScopeInvariants(
343
344
  errors.push(`write_glob outside component root: ${normalized}`);
344
345
  continue;
345
346
  }
346
- if (!normalizedTargetPaths.some((targetPath) => targetPath === prefix || targetPath.startsWith(`${prefix}/`))) {
347
+ if (
348
+ !normalizedTargetPaths.some(
349
+ (targetPath) => targetPath === prefix || targetPath.startsWith(`${prefix}/`),
350
+ )
351
+ ) {
347
352
  errors.push(`write_glob prefix does not align with target_paths: ${normalized}`);
348
353
  continue;
349
354
  }
@@ -21,7 +21,10 @@ function stripPresenceSourcePrefix(value: string): string {
21
21
 
22
22
  export function normalizePresenceClientId(value: unknown): string {
23
23
  const raw = stripPresenceSourcePrefix(String(value ?? "").trim());
24
- return raw.replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "").trim();
24
+ return raw
25
+ .replace(/[^a-zA-Z0-9._-]+/g, "_")
26
+ .replace(/^_+|_+$/g, "")
27
+ .trim();
25
28
  }
26
29
 
27
30
  export function normalizePresenceClientLabel(value: unknown): string {
@@ -31,7 +34,9 @@ export function normalizePresenceClientLabel(value: unknown): string {
31
34
  }
32
35
 
33
36
  export function normalizePresenceLookupToken(value: unknown): string {
34
- return normalizePresenceClientLabel(value).toLowerCase().replace(/[^a-z0-9]+/g, "");
37
+ return normalizePresenceClientLabel(value)
38
+ .toLowerCase()
39
+ .replace(/[^a-z0-9]+/g, "");
35
40
  }
36
41
 
37
42
  type SessionTransportPresence = {
@@ -91,8 +96,9 @@ export class CommunicationManager {
91
96
  : `${normalizedFrom || "agent"}__${normalizedSessionId || "session"}`,
92
97
  kind: "agent",
93
98
  label: labelFrom || normalizedFrom || "Agent",
94
- version: String(process.env.PUSHPALS_RUNTIME_TAG ?? process.env.npm_package_version ?? "")
95
- .trim(),
99
+ version: String(
100
+ process.env.PUSHPALS_RUNTIME_TAG ?? process.env.npm_package_version ?? "",
101
+ ).trim(),
96
102
  platform: `${process.platform}/${process.arch}`,
97
103
  repoRoot,
98
104
  };
@@ -151,10 +157,15 @@ export class CommunicationManager {
151
157
  text: string,
152
158
  meta: EventMeta = {},
153
159
  ): Promise<boolean> {
154
- return this.emitToSession(sessionId, "message", { text }, {
155
- ...meta,
156
- from: meta.from ?? "client",
157
- });
160
+ return this.emitToSession(
161
+ sessionId,
162
+ "message",
163
+ { text },
164
+ {
165
+ ...meta,
166
+ from: meta.from ?? "client",
167
+ },
168
+ );
158
169
  }
159
170
 
160
171
  async userMessage(text: string, meta: EventMeta = {}): Promise<boolean> {