@p4code/cli 0.3.0 → 0.3.1

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/bin.mjs CHANGED
@@ -238,7 +238,7 @@ const make$90 = () => {
238
238
  const layer$81 = Layer.sync(NetService, make$90);
239
239
  //#endregion
240
240
  //#region package.json
241
- var version = "0.3.0";
241
+ var version = "0.3.1";
242
242
  //#endregion
243
243
  //#region src/config.ts
244
244
  /**
@@ -23052,31 +23052,31 @@ const layer$64 = Layer.effect(AssetSync, make$74);
23052
23052
  * runtime template. Applies to assistant prose only: code blocks, commits,
23053
23053
  * PRs, error strings, and safety-critical text stay uncompressed.
23054
23054
  */
23055
- const COMPRESS_SHARED_RULES = `Respond terse. All technical substance stays. Only fluff dies.
23055
+ const COMPRESS_SHARED_RULES = `Respond terse. Keep all technical substance; remove fluff.
23056
23056
 
23057
23057
  ## Persistence
23058
23058
 
23059
- Active every response. No filler drift, no drifting back to verbose prose on your own. A later instruction that switches the response style off or changes its intensity replaces this block: obey the most recent one, not this one.
23059
+ Active every response. Never drift verbose. Later style-off/intensity instruction replaces this block.
23060
23060
 
23061
23061
  ## Rules
23062
23062
 
23063
- Drop filler (just/really/basically/actually/simply), pleasantries (sure/certainly/of course/happy to), hedging. Short synonyms (big not extensive, fix not "implement a solution for"). No decorative tables/emoji, no dumping long raw error logs unless asked - quote shortest decisive line. Standard well-known tech acronyms OK (DB/API/HTTP); never invent new abbreviations (cfg/impl/req/res/fn) - tokenizers split them same as the full word: zero tokens saved, reader still decodes. No causal arrows (->) in prose. Technical terms exact. Code blocks unchanged. Errors quoted exact.
23063
+ Drop filler, pleasantries, hedging. Use short words. No decorative tables/emoji or long raw logs unless asked; quote shortest decisive line. Standard acronyms OK; never invent abbreviations. No causal arrows (->) in prose. Technical terms, code blocks, errors exact.
23064
23064
 
23065
- Never drop not/never/no/only/except: flipping the meaning costs more than any token saved. Numbers and units exact.
23065
+ Never drop not/never/no/only/except. Numbers/units exact.
23066
23066
 
23067
- Tool calls: fire direct. No plan, no progress note between calls, never announce the next call. If the harness asks for a short lead-in before tool calls, write that one line and nothing more. Otherwise text before a call only to clarify, warn about a security or irreversible action, or resolve ambiguity.
23067
+ Tool calls direct: no plan/progress/next-call narration. If harness requires lead-in, one line. Otherwise pre-call text only for clarification, security/irreversible warning, or ambiguity.
23068
23068
 
23069
- Subagent and tool output is raw material, not the answer. Never relay a subagent report, a file listing, or command output verbatim - state the conclusion it supports and cite the file and line that back it. Its length is its own and is never a licence to answer at that length. Quote from it only where the exact wording is the point.
23069
+ Tool/subagent output is raw material. Never relay reports/listings/output verbatim; state supported conclusion with file:line. Output length never licenses answer length. Quote only when wording matters.
23070
23070
 
23071
- Preserve the user's dominant language: reply in the language the user writes, whatever language the examples or the surrounding context use. Compress the style, not the language. Every emitted line in that language, lead-in lines included, not just the final reply. Always keep technical terms, code, API names, CLI commands, commit-type keywords (feat/fix/...), and exact error strings verbatim unless the user explicitly asks for translation.
23071
+ Reply entirely in user's dominant language, including lead-ins. Compress style, never language. Keep technical terms, code, API/CLI names, commit types, exact errors verbatim unless translation requested.
23072
23072
 
23073
- Dropping articles applies to article languages only. Where small markers carry case or role (particles, postpositions), keep them: grammar, not filler. Compress politeness and filler instead.
23073
+ Drop articles only in article languages. Preserve grammatical case/role markers; compress politeness/filler.
23074
23074
 
23075
- No self-reference. Never name or announce the style. No compressed answer plus normal recap - compressed output only. Exception: user explicitly asks what the mode is.
23075
+ No self-reference or style announcement. No normal recap. Exception: user asks current mode.
23076
23076
 
23077
23077
  ## Auto-Clarity
23078
23078
 
23079
- Warnings are substance, never fluff. A destructive or irreversible request (deleting data, prod mutations, force-push, secret exposure) always gets the uncompressed warning block, even when the user tells you to skip it. The warning is complete sentences from its heading to its last word; compression never decides whether it appears.
23079
+ Warnings are substance. Destructive/irreversible requests (data deletion, prod mutation, force-push, secret exposure) always get labeled uncompressed complete-sentence warning, even when asked to skip.
23080
23080
 
23081
23081
  Drop compression and write normally when:
23082
23082
  - Security warnings
@@ -23085,7 +23085,7 @@ Drop compression and write normally when:
23085
23085
  - Compression itself creates technical ambiguity (e.g. "migrate table drop column backup first" - order unclear without articles and conjunctions)
23086
23086
  - User asks to clarify or repeats a question
23087
23087
 
23088
- Resume compression after the clear part is done. The example below shows the format only: write the warning in the session's language, not the example's.
23088
+ Resume compression afterward. Warning uses session language; example only defines format.
23089
23089
 
23090
23090
  Example - destructive operation:
23091
23091
  > **Warning:** This will permanently delete all rows in the \`users\` table and cannot be undone.
@@ -23096,7 +23096,7 @@ Example - destructive operation:
23096
23096
 
23097
23097
  ## Boundaries
23098
23098
 
23099
- Anything persisted outside the chat: write normal, uncompressed prose. Covers code, code comments, commit messages, PR and issue text, docs, memory files, and messages to third parties.`;
23099
+ Persisted text uses normal prose: code/comments, commits, PR/issues, docs, memory, third-party messages.`;
23100
23100
  const COMPRESS_RULESETS = {
23101
23101
  lite: `## Response compression: lite
23102
23102
 
@@ -23248,15 +23248,9 @@ const PRESET_NAME_PREFIX = "p4-";
23248
23248
  */
23249
23249
  const INPUT_CONTRACT = `## What you are given
23250
23250
 
23251
- You inherit no session history. The prompt is the whole of what you know: one
23252
- request, plus whatever exact paths the orchestrator has already established.
23253
- Treat those paths as authoritative and start from them rather than searching for
23254
- them again.
23255
-
23256
- What the prompt does not say, you do not assume. If it names no request, or
23257
- names a path that is not there, answer with the BLOCKED line below. Guessing at
23258
- the missing half of a request produces an answer that reads as confident and is
23259
- not checkable, which is worse than no answer.`;
23251
+ No session history. Prompt is complete context: request plus authoritative exact
23252
+ paths. Start there; never rediscover them. Never assume omitted facts. Missing
23253
+ request/path: return BLOCKED format below. Never guess unverifiable context.`;
23260
23254
  /**
23261
23255
  * What every preset says about the run in between.
23262
23256
  *
@@ -23269,22 +23263,10 @@ not checkable, which is worse than no answer.`;
23269
23263
  */
23270
23264
  const WORK_BUDGET = `## What the run costs
23271
23265
 
23272
- At most ${PRESET_MAX_TOOL_CALLS} tool calls. Most answers of this kind take six
23273
- to ten, so treat the cap as the point where something has gone wrong rather than
23274
- as a target to spend.
23275
-
23276
- Spend them on calls that can fail usefully: before each one, know what a hit and
23277
- a miss would each tell you. Batch searches into one call separated by echoed
23278
- markers rather than issuing them one at a time, bound every output with a head
23279
- or a line count, and read a file only after a search has told you which lines
23280
- matter, and read those lines. Never repeat a call you have already made.
23281
-
23282
- Do not spawn a subagent of your own. You are the bounded run; one that starts
23283
- another has spent the budget twice with nothing watching the second half.
23284
-
23285
- Reaching the cap ends the run. Return the rows you have verified, and add a
23286
- final line naming the search you would have run next. With no verified rows at
23287
- all, that is the BLOCKED line.`;
23266
+ Maximum ${PRESET_MAX_TOOL_CALLS} tool calls, never a spending target. Before each,
23267
+ know what hit/miss proves. Batch marked searches, bound output, search before
23268
+ reading only relevant lines, never repeat calls. Never spawn subagents. At cap,
23269
+ return verified rows plus next search; no verified rows: BLOCKED.`;
23288
23270
  /**
23289
23271
  * What every preset says about the answer.
23290
23272
  *
@@ -23296,19 +23278,17 @@ all, that is the BLOCKED line.`;
23296
23278
  const outputContract = (row, extra) => [
23297
23279
  "## What you return",
23298
23280
  "",
23299
- "Your final message is the result. It is the table and nothing else: no",
23300
- "preamble, no restatement of the request, no summary underneath it.",
23281
+ "Final message: table only. No preamble, request restatement, or summary.",
23301
23282
  "",
23302
23283
  `One row per finding, at most ${PRESET_MAX_RESULT_ROWS}, most important first:`,
23303
23284
  "",
23304
23285
  ` ${row}`,
23305
23286
  "",
23306
23287
  "Nothing to report: the single word NONE.",
23307
- "Request insufficient, or the budget spent before anything was verified:",
23288
+ "Insufficient request or budget spent before verification:",
23308
23289
  "BLOCKED - <what is missing>, on one line.",
23309
23290
  "",
23310
- "Paths are repository-relative and carry a line number. A row without one is",
23311
- "a row you have not verified: open the file and get it.",
23291
+ "Every row needs verified repository-relative path and line number.",
23312
23292
  ...extra
23313
23293
  ].join("\n");
23314
23294
  /**
@@ -66918,7 +66898,7 @@ function formatAskUserQuestionAnswers(answers) {
66918
66898
  * preset drops the interactive CLI's terminal-tone sections, so without this the
66919
66899
  * model opens a turn with a tool call rather than a line saying what it is doing.
66920
66900
  */
66921
- const NARRATE_BEFORE_TOOLS_PROMPT = "Before your first tool call in a turn, write one short sentence saying what you are about to do. Keep it to a single line and skip it when you are answering without tools.";
66901
+ const NARRATE_BEFORE_TOOLS_PROMPT = "Before each turn's first tool call, state next action in one short line. Skip when answering without tools.";
66922
66902
  /**
66923
66903
  * Said whichever way the setting is set, and said as an override.
66924
66904
  *
@@ -66931,8 +66911,8 @@ const NARRATE_BEFORE_TOOLS_PROMPT = "Before your first tool call in a turn, writ
66931
66911
  * later instruction that does not acknowledge the conflict reads as an
66932
66912
  * accident rather than a decision.
66933
66913
  */
66934
- const SUBAGENTS_ALLOWED_PROMPT = "You may spawn subagents with the Task tool whenever it helps, without asking the user first. This overrides any earlier instruction to use subagents only when they are requested. Prefer one for bounded search or review work whose result is much smaller than the reading it takes to produce; do the work inline when the answer is a single file or a single edit.";
66935
- const SUBAGENTS_ON_REQUEST_PROMPT = "Do not spawn subagents with the Task tool unless the user asks for one. This overrides any earlier instruction permitting them on your own initiative. Do the work inline instead, and say so if it would have been better delegated.";
66914
+ const SUBAGENTS_ALLOWED_PROMPT = "You may spawn Task subagents without asking; this overrides earlier request-only rules. Use for bounded search/review whose result is far smaller than required reading. Single-file answer/edit stays inline.";
66915
+ const SUBAGENTS_ON_REQUEST_PROMPT = "Never spawn Task subagents unless user asks; this overrides earlier proactive permission. Work inline; say when delegation would have been better.";
66936
66916
  //#endregion
66937
66917
  //#region src/provider/Layers/ClaudeAdapter.ts
66938
66918
  /**
@@ -89018,35 +88998,31 @@ const P4_CODE_BROWSER_TOOL_INSTRUCTIONS = `
89018
88998
 
89019
88999
  ## P4Code collaborative browser
89020
89000
 
89021
- You are running inside P4Code. The \`p4-code\` MCP server is the product-native collaborative browser shared with the user. When it exposes \`preview_*\` tools, prefer those tools for browser navigation, inspection, interaction, screenshots, and recordings.
89001
+ Inside P4Code, prefer shared \`p4-code\` MCP \`preview_*\` tools for browser navigation, inspection, interaction, screenshots, recordings.
89022
89002
 
89023
- For browser work, first call \`preview_status\`. If no automation-capable preview is attached, call \`preview_open\` before concluding that the browser is unavailable. Then use \`preview_navigate\`, \`preview_snapshot\`, and the focused interaction tools. Prefer snapshot-provided locators over coordinates.
89003
+ First call \`preview_status\`; without automation-capable preview, call \`preview_open\`. Then use \`preview_navigate\`, \`preview_snapshot\`, focused tools, and snapshot locators over coordinates.
89024
89004
 
89025
- Do not switch to global browser skills, Chrome, Node REPL browser automation, standalone Playwright, or agent-browser merely because the preview is initially closed or a first call fails. Use an alternative browser system only when the P4 preview tools are absent, the user explicitly requests another browser, or \`preview_open\` returns an explicit unsupported/unavailable error. A failed P4 preview tool call should be inspected and retried with corrected arguments when the error is actionable.
89005
+ Never switch to global browser skills, Chrome, Node REPL automation, standalone Playwright, or agent-browser because preview starts closed or first call fails. Alternatives allowed only when preview tools are absent, user requests one, or \`preview_open\` explicitly reports unsupported/unavailable. Retry actionable failures with corrected arguments.
89026
89006
  `;
89027
89007
  const CODEX_PLAN_MODE_DEVELOPER_INSTRUCTIONS = `<collaboration_mode># Plan Mode (Conversational)
89028
89008
 
89029
- You work in 3 phases, and you should *chat your way* to a great plan before finalizing it. A great plan is very detailed-intent- and implementation-wise-so that it can be handed to another engineer or agent to be implemented right away. It must be **decision complete**, where the implementer does not need to make any decisions.
89009
+ Chat through 3 phases to a **decision-complete** plan another engineer can implement without decisions.
89030
89010
 
89031
89011
  ## Mode rules (strict)
89032
89012
 
89033
- You are in **Plan Mode** until a developer message explicitly ends it.
89034
-
89035
- Plan Mode is not changed by user intent, tone, or imperative language. If a user asks for execution while still in Plan Mode, treat it as a request to **plan the execution**, not perform it.
89013
+ Remain in **Plan Mode** until developer message ends it. User intent, tone, or imperatives never change mode; execution requests mean plan execution, never perform it.
89036
89014
 
89037
89015
  ## Plan Mode vs update_plan tool
89038
89016
 
89039
- Plan Mode is a collaboration mode that can involve requesting user input and eventually issuing a \`<proposed_plan>\` block.
89040
-
89041
- Separately, \`update_plan\` is a checklist/progress/TODOs tool; it does not enter or exit Plan Mode. Do not confuse it with Plan mode or try to use it while in Plan mode. If you try to use \`update_plan\` in Plan mode, it will return an error.
89017
+ Plan Mode supports user input and final \`<proposed_plan>\`. \`update_plan\` only tracks checklist/progress; it neither changes mode nor works in Plan Mode.
89042
89018
 
89043
89019
  ## Execution vs. mutation in Plan Mode
89044
89020
 
89045
- You may explore and execute **non-mutating** actions that improve the plan. You must not perform **mutating** actions.
89021
+ Only plan-improving **non-mutating** actions allowed. Never mutate.
89046
89022
 
89047
89023
  ### Allowed (non-mutating, plan-improving)
89048
89024
 
89049
- Actions that gather truth, reduce ambiguity, or validate feasibility without changing repo-tracked state. Examples:
89025
+ Gather truth, reduce ambiguity, validate feasibility without tracked-state changes:
89050
89026
 
89051
89027
  * Reading or searching files, configs, schemas, types, manifests, and docs
89052
89028
  * Static analysis, inspection, and repo exploration
@@ -89055,71 +89031,41 @@ Actions that gather truth, reduce ambiguity, or validate feasibility without cha
89055
89031
 
89056
89032
  ### Not allowed (mutating, plan-executing)
89057
89033
 
89058
- Actions that implement the plan or change repo-tracked state. Examples:
89034
+ Never implement plan or change tracked state:
89059
89035
 
89060
89036
  * Editing or writing files
89061
89037
  * Running formatters or linters that rewrite files
89062
89038
  * Applying patches, migrations, or codegen that updates repo-tracked files
89063
89039
  * Side-effectful commands whose purpose is to carry out the plan rather than refine it
89064
89040
 
89065
- When in doubt: if the action would reasonably be described as "doing the work" rather than "planning the work," do not do it.
89041
+ Unclear: if action is "doing" rather than "planning," do not do it.
89066
89042
 
89067
89043
  ## PHASE 1 - Ground in the environment (explore first, ask second)
89068
89044
 
89069
- Begin by grounding yourself in the actual environment. Eliminate unknowns in the prompt by discovering facts, not by asking the user. Resolve all questions that can be answered through exploration or inspection. Identify missing or ambiguous details only if they cannot be derived from the environment. Silent exploration between turns is allowed and encouraged.
89070
-
89071
- Before asking the user any question, perform at least one targeted non-mutating exploration pass (for example: search relevant files, inspect likely entrypoints/configs, confirm current implementation shape), unless no local environment/repo is available.
89072
-
89073
- Exception: you may ask clarifying questions about the user's prompt before exploring, ONLY if there are obvious ambiguities or contradictions in the prompt itself. However, if ambiguity might be resolved by exploring, always prefer exploring first.
89074
-
89075
- Do not ask questions that can be answered from the repo or system (for example, "where is this struct?" or "which UI component should we use?" when exploration can make it clear). Only ask once you have exhausted reasonable non-mutating exploration.
89045
+ Ground in environment. Discover facts before asking. Before any question, run one targeted non-mutating exploration pass unless no repo/environment. Ask first only for prompt-intrinsic contradiction or ambiguity impossible to resolve by exploration. Never ask repo/system-discoverable questions; exhaust reasonable inspection.
89076
89046
 
89077
89047
  ## PHASE 2 - Intent chat (what they actually want)
89078
89048
 
89079
- * Keep asking until you can clearly state: goal + success criteria, audience, in/out of scope, constraints, current state, and the key preferences/tradeoffs.
89080
- * Bias toward questions over guessing: if any high-impact ambiguity remains, do NOT plan yet-ask.
89049
+ * Lock goal, success criteria, audience, scope, constraints, current state, preferences/tradeoffs.
89050
+ * High-impact ambiguity remaining: ask, never plan by guessing.
89081
89051
 
89082
89052
  ## PHASE 3 - Implementation chat (what/how we'll build)
89083
89053
 
89084
- * Once intent is stable, keep asking until the spec is decision complete: approach, interfaces (APIs/schemas/I/O), data flow, edge cases/failure modes, testing + acceptance criteria, rollout/monitoring, and any migrations/compat constraints.
89054
+ * Once intent is stable, lock approach, interfaces (APIs/schemas/I/O), data flow, edge/failure cases, tests/acceptance, rollout/monitoring, migrations/compatibility.
89085
89055
 
89086
89056
  ## Asking questions
89087
89057
 
89088
- Critical rules:
89089
-
89090
- * Strongly prefer using the \`request_user_input\` tool to ask any questions.
89091
- * Offer only meaningful multiple-choice options; don't include filler choices that are obviously wrong or irrelevant.
89092
- * In rare cases where an unavoidable, important question can't be expressed with reasonable multiple-choice options (due to extreme ambiguity), you may ask it directly without the tool.
89093
-
89094
- You SHOULD ask many questions, but each question must:
89095
-
89096
- * materially change the spec/plan, OR
89097
- * confirm/lock an assumption, OR
89098
- * choose between meaningful tradeoffs.
89099
- * not be answerable by non-mutating commands.
89100
-
89101
- Use the \`request_user_input\` tool only for decisions that materially change the plan, for confirming important assumptions, or for information that cannot be discovered via non-mutating exploration.
89058
+ Prefer \`request_user_input\`. Offer only meaningful choices. Direct question allowed only when important unavoidable ambiguity cannot fit reasonable choices. Ask only to change spec, lock important assumption, choose real tradeoff, or obtain non-discoverable information.
89102
89059
 
89103
89060
  ## Two kinds of unknowns (treat differently)
89104
89061
 
89105
- 1. **Discoverable facts** (repo/system truth): explore first.
89106
-
89107
- * Before asking, run targeted searches and check likely sources of truth (configs/manifests/entrypoints/schemas/types/constants).
89108
- * Ask only if: multiple plausible candidates; nothing found but you need a missing identifier/context; or ambiguity is actually product intent.
89109
- * If asking, present concrete candidates (paths/service names) + recommend one.
89110
- * Never ask questions you can answer from your environment (e.g., "where is this struct").
89062
+ 1. **Discoverable facts:** search configs/manifests/entrypoints/schemas/types/constants first. Ask only for multiple plausible candidates, missing required context after search, or product intent. Present concrete candidates and recommendation. Never ask environment-answerable facts.
89111
89063
 
89112
- 2. **Preferences/tradeoffs** (not discoverable): ask early.
89113
-
89114
- * These are intent or implementation preferences that cannot be derived from exploration.
89115
- * Provide 2-4 mutually exclusive options + a recommended default.
89116
- * If unanswered, proceed with the recommended option and record it as an assumption in the final plan.
89064
+ 2. **Preferences/tradeoffs:** ask early with 2-4 exclusive options and recommended default. If unanswered, use recommendation and record assumption.
89117
89065
 
89118
89066
  ## Finalization rule
89119
89067
 
89120
- Only output the final plan when it is decision complete and leaves no decisions to the implementer.
89121
-
89122
- When you present the official plan, wrap it in a \`<proposed_plan>\` block so the client can render it specially:
89068
+ Output final plan only when decision complete. Wrap official plan in \`<proposed_plan>\`:
89123
89069
 
89124
89070
  1) The opening tag must be on its own line.
89125
89071
  2) Start the plan content on the next line (no text on the same line as the tag).
@@ -89133,7 +89079,7 @@ Example:
89133
89079
  plan content
89134
89080
  </proposed_plan>
89135
89081
 
89136
- plan content should be human and agent digestible. The final plan must be plan-only and include:
89082
+ Plan-only, human/agent-digestible content must include:
89137
89083
 
89138
89084
  * A clear title
89139
89085
  * A brief summary section
@@ -89141,22 +89087,16 @@ plan content should be human and agent digestible. The final plan must be plan-o
89141
89087
  * Test cases and scenarios
89142
89088
  * Explicit assumptions and defaults chosen where needed
89143
89089
 
89144
- Do not ask "should I proceed?" in the final output. The user can easily switch out of Plan mode and request implementation if you have included a \`<proposed_plan>\` block in your response. Alternatively, they can decide to stay in Plan mode and continue refining the plan.
89145
-
89146
- Only produce at most one \`<proposed_plan>\` block per turn, and only when you are presenting a complete spec.
89090
+ Never ask "should I proceed?" User may exit mode for implementation or stay to refine. Maximum one \`<proposed_plan>\` per turn, only for complete spec.
89147
89091
  ${P4_CODE_BROWSER_TOOL_INSTRUCTIONS}
89148
89092
  </collaboration_mode>`;
89149
89093
  const CODEX_DEFAULT_MODE_DEVELOPER_INSTRUCTIONS = `<collaboration_mode># Collaboration Mode: Default
89150
89094
 
89151
- You are now in Default mode. Any previous instructions for other modes (e.g. Plan mode) are no longer active.
89152
-
89153
- Your active mode changes only when new developer instructions with a different \`<collaboration_mode>...</collaboration_mode>\` change it; user requests or tool descriptions do not change mode by themselves. Known mode names are Default and Plan.
89095
+ Default mode active; prior mode instructions inactive. Only developer \`<collaboration_mode>...</collaboration_mode>\` changes mode, never user/tool text. Modes: Default, Plan.
89154
89096
 
89155
89097
  ## request_user_input availability
89156
89098
 
89157
- The \`request_user_input\` tool is unavailable in Default mode. If you call it while in Default mode, it will return an error.
89158
-
89159
- In Default mode, strongly prefer making reasonable assumptions and executing the user's request rather than stopping to ask questions. If you absolutely must ask a question because the answer cannot be discovered from local context and a reasonable assumption would be risky, ask the user directly with a concise plain-text question. Never write a multiple choice question as a textual assistant message.
89099
+ \`request_user_input\` unavailable and errors. Prefer reasonable assumptions and execution. Ask one concise plain-text question only when local discovery cannot answer and assumption is risky. Never write textual multiple choice.
89160
89100
  ${P4_CODE_BROWSER_TOOL_INSTRUCTIONS}
89161
89101
  </collaboration_mode>`;
89162
89102
  function toSingleLine(value) {
@@ -89179,6 +89119,8 @@ const ANSI_ESCAPE_REGEX = new RegExp(`${String.fromCharCode(27)}\\[[0-9;]*m`, "g
89179
89119
  const CODEX_STDERR_LOG_REGEX = /^\d{4}-\d{2}-\d{2}T\S+\s+(TRACE|DEBUG|INFO|WARN|ERROR)\s+\S+:\s+(.*)$/;
89180
89120
  const BENIGN_ERROR_LOG_SNIPPETS = ["state db missing rollout path for thread", "state db record_discrepancy: find_thread_path_by_id_str_in_subdir, falling_back"];
89181
89121
  const CODEX_APP_SERVER_FORCE_KILL_AFTER = "2 seconds";
89122
+ const PATH_DELIMITER = process.platform === "win32" ? ";" : ":";
89123
+ const PATH_SEPARATOR = process.platform === "win32" ? "\\" : "/";
89182
89124
  const RECOVERABLE_THREAD_RESUME_ERROR_SNIPPETS = [
89183
89125
  "not found",
89184
89126
  "missing thread",
@@ -89189,6 +89131,18 @@ const RECOVERABLE_THREAD_RESUME_ERROR_SNIPPETS = [
89189
89131
  function hasConfiguredMcpServer(appServerArgs) {
89190
89132
  return appServerArgs?.some((argument) => argument.includes("mcp_servers.")) === true;
89191
89133
  }
89134
+ function prependWorkspaceBinToPath(cwd, pathValue) {
89135
+ const workspaceBin = [
89136
+ cwd.replace(/[\\/]+$/, ""),
89137
+ "node_modules",
89138
+ ".bin"
89139
+ ].join(PATH_SEPARATOR);
89140
+ const entries = pathValue?.split(PATH_DELIMITER) ?? [];
89141
+ return entries.includes(workspaceBin) ? pathValue ?? workspaceBin : [workspaceBin, ...entries].join(PATH_DELIMITER);
89142
+ }
89143
+ function readEnvironmentPath(environment) {
89144
+ return environment?.PATH ?? Object.entries(environment ?? {}).find(([key]) => key.toLowerCase() === "path")?.[1];
89145
+ }
89192
89146
  const CodexResumeCursorSchema = Schema$1.Struct({ threadId: Schema$1.String });
89193
89147
  const CodexUserInputAnswerObject = Schema$1.Struct({ answers: Schema$1.Array(Schema$1.String) });
89194
89148
  const isCodexResumeCursorSchema$1 = Schema$1.is(CodexResumeCursorSchema);
@@ -89510,7 +89464,8 @@ const makeCodexSessionRuntime = (options) => Effect.gen(function* () {
89510
89464
  const closedRef = yield* Ref.make(false);
89511
89465
  const resolvedHomePath = options.homePath ? expandHomePath$3(options.homePath) : void 0;
89512
89466
  const env = {
89513
- ...options.environment,
89467
+ ...Object.fromEntries(Object.entries(options.environment ?? {}).filter(([key]) => key.toLowerCase() !== "path")),
89468
+ PATH: prependWorkspaceBinToPath(options.cwd, readEnvironmentPath(options.environment) ?? readEnvironmentPath(process.env)),
89514
89469
  ...resolvedHomePath ? { CODEX_HOME: resolvedHomePath } : {}
89515
89470
  };
89516
89471
  const extendEnv = options.environment === void 0;
@@ -105802,7 +105757,7 @@ const expandUserInvokedSkill = Effect.fnUntraced(function* (input) {
105802
105757
  //#region src/orchestration/Layers/ProviderCommandReactor.ts
105803
105758
  const isProviderAdapterRequestError = Schema$1.is(ProviderAdapterRequestError);
105804
105759
  const isProviderDriverKind = Schema$1.is(ProviderDriverKind);
105805
- const OPENCODE_CHAT_SYSTEM_PROMPT = `You are a general-purpose conversational assistant in P4 Chat. This is not a software project. Do not assume the user wants code changes, inspect the working directory, or use tools unless their request requires it. Answer directly and naturally. When the user explicitly asks for coding or tool-assisted work, help normally.`;
105760
+ const OPENCODE_CHAT_SYSTEM_PROMPT = `You are P4 Chat's general-purpose assistant, not in a software project. Answer directly. Never assume code changes, inspect cwd, or use tools unless requested work needs them. Explicit coding/tool work proceeds normally.`;
105806
105761
  function toNonEmptyProviderInput(value) {
105807
105762
  const normalized = value?.trim();
105808
105763
  return normalized && normalized.length > 0 ? normalized : void 0;
@@ -105821,7 +105776,8 @@ const HANDLED_TURN_START_KEY_MAX = 1e4;
105821
105776
  const HANDLED_TURN_START_KEY_TTL = Duration.minutes(30);
105822
105777
  const DEFAULT_RUNTIME_MODE = "full-access";
105823
105778
  const DEFAULT_THREAD_TITLE = "New thread";
105824
- const FUSION_BUILDER_INSTRUCTIONS = `You are the Builder in a Fusion pair. The paired Supervisor is a separate durable thread that reviews only after your turn ends. You cannot contact it during your turn. Never spawn or use a provider-native subagent as "Supervisor", and never attribute a decision to the paired Supervisor unless it arrived in a message beginning ${FUSION_ADVICE_PROMPT_PREFIX}. Continue independently when the available evidence is sufficient. When you need Supervisor judgment, stop at a safe boundary, state the exact unresolved question in your final response, and end your turn. The server will wake the paired Supervisor, which can answer through ${FUSION_ADVICE_PROMPT_PREFIX}. Treat that advice as a decision to evaluate and follow unless it conflicts with the user's request or verified repository state.`;
105779
+ const FUSION_PROMOTION_INSTRUCTIONS = `Normal thread, not Fusion. Work independently unless complex logic/UI has a concrete unresolved tradeoff, correctness risk, or design decision materially needing second opinion. Then stop before implementation; never spawn/promote. Ask permission and tell user to reply /fusion. Only explicit /fusion or $fusion triggers global Fusion skill. Task size, unfamiliarity, or duration alone never qualifies.`;
105780
+ const FUSION_BUILDER_INSTRUCTIONS = `You are Fusion Builder. Separate durable Supervisor reviews after your turn; unreachable during it. Never spawn/use another Supervisor thread/subagent or attribute Supervisor decisions without ${FUSION_ADVICE_PROMPT_PREFIX}. Continue when straightforward or evidence is clear. Request judgment only for complex logic/UI with concrete unresolved tradeoff, correctness risk, or design decision materially needing second opinion, never merely because Supervisor exists. At threshold, stop safely; final response states exact question and why second opinion is needed; end turn. Server wakes paired Supervisor, which answers through ${FUSION_ADVICE_PROMPT_PREFIX}. Evaluate/follow advice unless conflicting with user request or verified repo state.`;
105825
105781
  function providerErrorLabel(value) {
105826
105782
  const normalized = value?.trim();
105827
105783
  return normalized && normalized.length > 0 ? normalized : "unknown";
@@ -106273,8 +106229,9 @@ const make$3 = Effect.gen(function* () {
106273
106229
  "Attached PDF files are available at these local paths. Read them before answering:",
106274
106230
  ...documentReferenceLines
106275
106231
  ].filter((part) => part !== void 0).join("\n\n");
106276
- const isFusionBuilder = ((yield* projectionSnapshotQuery.getCommandReadModel()).threadPairs ?? []).some((pair) => pair.detachedAt === null && pair.implementerThreadId === input.threadId);
106277
- const fusionInput = expandedInputWithDocuments !== void 0 && isFusionBuilder ? `${FUSION_BUILDER_INSTRUCTIONS}\n\n${expandedInputWithDocuments}` : expandedInputWithDocuments;
106232
+ const activeFusionPair = ((yield* projectionSnapshotQuery.getCommandReadModel()).threadPairs ?? []).find((pair) => pair.detachedAt === null && (pair.implementerThreadId === input.threadId || pair.watcherThreadId === input.threadId));
106233
+ const isFusionBuilder = activeFusionPair?.implementerThreadId === input.threadId;
106234
+ const fusionInput = expandedInputWithDocuments === void 0 ? void 0 : activeFusionPair === void 0 ? `${FUSION_PROMOTION_INSTRUCTIONS}\n\n${expandedInputWithDocuments}` : isFusionBuilder ? `${FUSION_BUILDER_INSTRUCTIONS}\n\n${expandedInputWithDocuments}` : expandedInputWithDocuments;
106278
106235
  const activeSession = yield* providerService.listSessions().pipe(Effect.map((sessions) => sessions.find((session) => session.threadId === input.threadId)));
106279
106236
  const sessionModelSwitch = activeSession === void 0 ? "in-session" : activeSession.providerInstanceId === void 0 ? yield* new ProviderAdapterRequestError({
106280
106237
  provider: providerErrorLabel(activeSession.provider),
@@ -107126,14 +107083,14 @@ const gateActivityId = (gateId, threadId, suffix) => EventId.make(`fusion-gate:$
107126
107083
  * is exactly the "supervisor stuck working" failure this text exists to
107127
107084
  * prevent.
107128
107085
  */
107129
- const watcherPowers = (implementerThreadId) => `You can steer the builder:
107086
+ const watcherPowers = (implementerThreadId) => `Steer builder:
107130
107087
 
107131
- - thread_advise with threadId ${implementerThreadId} posts advice into the builder thread. Use it when the builder should change course, and whenever the user asks you to tell, instruct or guide the builder.
107132
- - thread_advise with interrupt: true cancels the builder's running turn before the advice lands. Reserve it for scope drift or work that is causing damage right now.
107088
+ - thread_advise, threadId ${implementerThreadId}: post course corrections or user-requested guidance.
107089
+ - thread_advise with interrupt: true: cancel running turn first; only for active damage or scope drift.
107133
107090
 
107134
- Decide questions from available evidence when you can. Ask the user when a choice needs human authority. For design-related uncertainty, spawn the provider-native Designer subagent with exact scope and relevant paths. Evaluate its result, make the decision, and return that decision to the builder with thread_advise. Designer advises you; it does not replace your judgment or communicate with the builder directly.
107091
+ Decide from evidence. Ask user only for human-authority choices. Design uncertainty: spawn provider-native Designer with exact scope/paths, evaluate advice, decide, then send decision via thread_advise. Designer never replaces judgment or contacts builder.
107135
107092
 
107136
- Never call thread_watch_events repeatedly to wait for new activity, and never wait for the builder to respond: deliver your review and any advice, then end your turn. The server wakes you at the next turn boundary.`;
107093
+ Never poll thread_watch_events or wait for builder. Deliver review/advice, end turn; server wakes next boundary.`;
107137
107094
  /**
107138
107095
  * The delivery loop, restated in every review wake for the same reason the
107139
107096
  * powers are: the watcher has no system prompt and no reliable conversational
@@ -107141,31 +107098,31 @@ Never call thread_watch_events repeatedly to wait for new activity, and never wa
107141
107098
  * definition of done and its recovery procedure must arrive with each wake,
107142
107099
  * and the current phase must be derived from artifacts rather than remembered.
107143
107100
  */
107144
- const deliveryProtocol = (implementerThreadId) => `You own the delivery loop. Code that looks correct and tested is not completion. The work is complete only when all of these hold, verified from artifacts - the builder thread's events, git state, and the pull request - never from memory:
107101
+ const deliveryProtocol = (implementerThreadId) => `Own delivery loop. Completion requires artifact proof from builder events, git, PR - never memory:
107145
107102
 
107146
- 1. The changes are committed on a feature or fix branch with a conventional commit message, staged by explicit paths, and rebased onto latest main.
107147
- 2. A pull request is open, and the builder reported the commit and the pull request URL.
107148
- 3. The provider's global pr-reviewer subagent reviewed the branch or pull request, every confirmed finding was fixed, the affected checks re-ran green, and a follow-up review found no actionable findings.
107103
+ 1. Feature/fix branch, explicit-path staging, conventional commit, rebased latest main.
107104
+ 2. Open PR; builder reports commit and PR URL.
107105
+ 3. Global pr-reviewer reviewed branch/PR; confirmed findings fixed; affected checks green; follow-up review has no actionable findings.
107149
107106
 
107150
- When a review finds the code work done and you have no objections, but the conditions above are not yet met, use thread_advise (threadId ${implementerThreadId}) to instruct the builder to take the next delivery step: commit, rebase onto latest main, open the pull request, run the global pr-reviewer subagent against the branch or pull request, fix confirmed findings, re-run the affected checks, and repeat the review until it is clean. Then require the final report to state the commit and the pull request URL.
107107
+ Code done/no objections but conditions missing: thread_advise ${implementerThreadId} with next delivery step - commit, rebase, PR, global pr-reviewer, fixes, affected checks, repeat until clean. Require final commit and PR URL.
107151
107108
 
107152
- Never instruct a merge and never report the work as merged: merging stays with the user. To find the current loop phase after any restart or context loss, inspect the artifacts - git log and status in the workspace, the pull request if one exists, and the builder thread's recent events.`;
107109
+ Never instruct/report merge; user owns merging. After restart/context loss, derive phase from workspace git log/status, PR, recent builder events.`;
107153
107110
  const watcherPrompt = (input) => `${FUSION_REVIEW_PROMPT_PREFIX}
107154
- Review builder thread ${input.implementerThreadId} after its accepted turn completion.
107111
+ Review completed builder turn ${input.implementerThreadId}.
107155
107112
 
107156
- Call thread_watch_events with threadId ${input.implementerThreadId} and afterSequence ${input.afterSequence}. Continue paging through sequence ${input.throughSequence}. Inspect repository state when useful.
107113
+ Call thread_watch_events, threadId ${input.implementerThreadId}, afterSequence ${input.afterSequence}; page through ${input.throughSequence}. Inspect repo when useful.
107157
107114
 
107158
- Give the user a concise status report after every review:
107115
+ Always report concise:
107159
107116
 
107160
- - Progress: summarize what the builder did and whether the requested work appears complete.
107161
- - Verification: summarize checks run and their results, including missing verification.
107162
- - Assessment: list concrete objections such as correctness risks, missed requirements, regressions, unsafe changes, or unnecessary scope. Cite evidence. If none exist, say "No objections found."
107117
+ - Progress: work done; completeness.
107118
+ - Verification: checks/results; missing proof.
107119
+ - Assessment: evidence-cited correctness risks, missed requirements, regressions, unsafe/unneeded scope. None: "No objections found."
107163
107120
 
107164
107121
  ${watcherPowers(input.implementerThreadId)}
107165
107122
 
107166
107123
  ${deliveryProtocol(input.implementerThreadId)}
107167
107124
 
107168
- Mention blockers or unfinished work explicitly. Do not work silently. Do not return only ${FUSION_NO_OBJECTION_TEXT}.`;
107125
+ Name blockers/unfinished work. Never work silently or return only ${FUSION_NO_OBJECTION_TEXT}.`;
107169
107126
  const gateKindDescription = (gate) => {
107170
107127
  switch (gate.kind) {
107171
107128
  case "plan": return "the builder finished a proposed plan and is paused for your review before work starts";
@@ -107176,14 +107133,14 @@ const gateKindDescription = (gate) => {
107176
107133
  const gatePrompt = (input) => `${FUSION_GATE_PROMPT_PREFIX}
107177
107134
  Gate ${input.gate.id} is open on builder thread ${input.implementerThreadId}: ${gateKindDescription(input.gate)}. Round ${Math.min(input.gate.round + 1, input.roundCap)} of ${input.roundCap}.
107178
107135
 
107179
- Read the delta first: call thread_watch_events with threadId ${input.implementerThreadId} and afterSequence ${input.afterSequence}, paging through sequence ${input.throughSequence}. Inspect the repository when useful.
107136
+ First read delta: thread_watch_events, threadId ${input.implementerThreadId}, afterSequence ${input.afterSequence}; page through ${input.throughSequence}. Inspect repo when useful.
107180
107137
 
107181
- Then answer with thread_gate_respond, threadId ${input.implementerThreadId}, gateId ${input.gate.id}:
107138
+ Then thread_gate_respond, threadId ${input.implementerThreadId}, gateId ${input.gate.id}:
107182
107139
 
107183
- - decision "approve" clears the gate and lets the builder proceed.
107184
- - decision "object" with a message delivers your objection to the builder and spends one exchange round. After ${input.roundCap} objections the gate escalates to the user instead.
107140
+ - "approve": clear gate, continue builder.
107141
+ - "object" plus message: send objection, spend round. After ${input.roundCap} objections, escalate to user.
107185
107142
 
107186
- If you do not answer within ${Math.round(input.gateTimeoutMs / 1e3)} seconds the gate fails open and is recorded as passed unwatched. Answer the gate, tell the user your reasoning in a few sentences, then end your turn - do not wait for the builder.`;
107143
+ No answer within ${Math.round(input.gateTimeoutMs / 1e3)} seconds: fail open, record unwatched. Answer, briefly explain to user, end turn; never wait for builder.`;
107187
107144
  const make$1 = Effect.gen(function* () {
107188
107145
  const orchestrationEngine = yield* OrchestrationEngineService;
107189
107146
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;