cclaw-cli 0.42.0 → 0.44.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.
@@ -154,6 +154,7 @@ exit 0
154
154
  `;
155
155
  }
156
156
  export function workflowGuardScript(options = {}) {
157
+ const workflowGuardMode = options.workflowGuardMode === "strict" ? "strict" : "advisory";
157
158
  const tddEnforcementMode = options.tddEnforcementMode === "strict" ? "strict" : "advisory";
158
159
  const tddTestGlobs = options.tddTestGlobs && options.tddTestGlobs.length > 0
159
160
  ? options.tddTestGlobs.join(",")
@@ -162,7 +163,7 @@ export function workflowGuardScript(options = {}) {
162
163
  # cclaw workflow guard hook — generated by cclaw sync
163
164
  # Enforces stage-aware command discipline and recent flow-state read hygiene.
164
165
  set -uo pipefail
165
- WORKFLOW_GUARD_MODE="\${CCLAW_WORKFLOW_GUARD_MODE:-advisory}"
166
+ WORKFLOW_GUARD_MODE="\${CCLAW_WORKFLOW_GUARD_MODE:-${workflowGuardMode}}"
166
167
  MAX_FLOW_READ_AGE_SEC="\${CCLAW_WORKFLOW_GUARD_MAX_AGE_SEC:-1800}"
167
168
  TDD_ENFORCEMENT_MODE="${tddEnforcementMode}"
168
169
  TDD_TEST_GLOBS="${tddTestGlobs}"
@@ -342,6 +343,81 @@ is_cclaw_cli_payload() {
342
343
  printf '%s' "$1" | grep -Eq '(cclaw |npx cclaw |/cc-|/cc[^[:alnum:]_-])'
343
344
  }
344
345
 
346
+ extract_flow_state_after_json() {
347
+ if command -v jq >/dev/null 2>&1; then
348
+ printf '%s' "$INPUT" | jq -r '
349
+ .tool_input?.content //
350
+ .input?.content //
351
+ .arguments?.content //
352
+ .params?.content //
353
+ .payload?.content //
354
+ .content //
355
+ .input?.new_string //
356
+ .tool_input?.new_string //
357
+ ""
358
+ ' 2>/dev/null || echo ""
359
+ return 0
360
+ fi
361
+
362
+ if command -v python3 >/dev/null 2>&1; then
363
+ INPUT_JSON="$INPUT" python3 - <<'PY'
364
+ import json
365
+ import os
366
+
367
+ try:
368
+ payload = json.loads(os.environ.get("INPUT_JSON", "{}"))
369
+ except Exception:
370
+ payload = {}
371
+
372
+ def pick(value):
373
+ if not isinstance(value, dict):
374
+ return ""
375
+ for key in ("tool_input", "input", "arguments", "params", "payload"):
376
+ nested = value.get(key)
377
+ if isinstance(nested, dict):
378
+ content = nested.get("content")
379
+ if isinstance(content, str) and content.strip():
380
+ return content
381
+ new_string = nested.get("new_string")
382
+ if isinstance(new_string, str) and new_string.strip():
383
+ return new_string
384
+ content = value.get("content")
385
+ if isinstance(content, str) and content.strip():
386
+ return content
387
+ return ""
388
+
389
+ print(pick(payload))
390
+ PY
391
+ return 0
392
+ fi
393
+
394
+ printf ''
395
+ return 0
396
+ }
397
+
398
+ verify_flow_state_candidate() {
399
+ local candidate_json="$1"
400
+ [ -n "$candidate_json" ] || return 1
401
+ local tmp_file="$STATE_DIR/.flow-state-candidate.$$.$RANDOM.json"
402
+ printf '%s' "$candidate_json" > "$tmp_file" 2>/dev/null || {
403
+ rm -f "$tmp_file" 2>/dev/null || true
404
+ return 1
405
+ }
406
+
407
+ local verify_cmd=(npx -y cclaw-cli internal verify-flow-state-diff --after-file="$tmp_file" --quiet)
408
+ if command -v cclaw >/dev/null 2>&1; then
409
+ verify_cmd=(cclaw internal verify-flow-state-diff --after-file="$tmp_file" --quiet)
410
+ fi
411
+
412
+ if "\${verify_cmd[@]}" >/dev/null 2>&1; then
413
+ rm -f "$tmp_file" 2>/dev/null || true
414
+ return 0
415
+ fi
416
+
417
+ rm -f "$tmp_file" 2>/dev/null || true
418
+ return 1
419
+ }
420
+
345
421
  is_preimplementation_stage() {
346
422
  case "$1" in
347
423
  brainstorm|scope|design|spec|plan) return 0 ;;
@@ -480,6 +556,22 @@ if [ -n "$TARGET_STAGE" ] && [ "$CURRENT_STAGE" != "none" ]; then
480
556
  fi
481
557
  fi
482
558
 
559
+ if is_mutating_tool "$TOOL_LOWER" && printf '%s' "$PAYLOAD_LOWER" | grep -Eq '\.cclaw/state/flow-state\.json'; then
560
+ if [ -n "$REASONS" ]; then
561
+ REASONS="$REASONS,direct_flow_state_edit"
562
+ else
563
+ REASONS="direct_flow_state_edit"
564
+ fi
565
+ FLOW_STATE_AFTER_JSON=$(extract_flow_state_after_json)
566
+ if [ -n "$FLOW_STATE_AFTER_JSON" ]; then
567
+ if ! verify_flow_state_candidate "$FLOW_STATE_AFTER_JSON"; then
568
+ REASONS="$REASONS,flow_state_edit_failed_internal_validation"
569
+ fi
570
+ else
571
+ REASONS="$REASONS,flow_state_edit_without_serialized_content"
572
+ fi
573
+ fi
574
+
483
575
  if is_preimplementation_stage "$CURRENT_STAGE" && is_mutating_tool "$TOOL_LOWER"; then
484
576
  if ! printf '%s' "$PAYLOAD_LOWER" | grep -Eq '\.cclaw/'; then
485
577
  if [ -n "$REASONS" ]; then
@@ -567,7 +659,11 @@ PY
567
659
  fi
568
660
 
569
661
  if [ -n "$REASONS" ]; then
570
- NOTE="Cclaw workflow guard: detected potential flow violation (\${REASONS}). Re-read ${RUNTIME_ROOT}/state/flow-state.json, avoid source edits before tdd stage, and enforce RED -> GREEN -> REFACTOR discipline inside tdd."
662
+ if printf '%s' "$REASONS" | grep -Eq 'direct_flow_state_edit'; then
663
+ NOTE="Cclaw workflow guard: direct flow-state edit bypasses the canonical stage-complete helper (\${REASONS}). Prefer: bash ${RUNTIME_ROOT}/hooks/stage-complete.sh <stage>. In strict mode this is blocked."
664
+ else
665
+ NOTE="Cclaw workflow guard: detected potential flow violation (\${REASONS}). Re-read ${RUNTIME_ROOT}/state/flow-state.json, avoid source edits before tdd stage, and enforce RED -> GREEN -> REFACTOR discipline inside tdd."
666
+ fi
571
667
  if command -v jq >/dev/null 2>&1; then
572
668
  ENTRY=$(jq -n -c \
573
669
  --arg ts "$TS" \
@@ -1826,6 +1922,9 @@ export function codexHooksJsonWithObservation() {
1826
1922
  hooks: [{
1827
1923
  type: "command",
1828
1924
  command: `bash ${RUNTIME_ROOT}/hooks/prompt-guard.sh`
1925
+ }, {
1926
+ type: "command",
1927
+ command: "bash -lc 'if command -v cclaw >/dev/null 2>&1; then cclaw internal verify-current-state --quiet >/dev/null || true; else npx -y cclaw-cli internal verify-current-state --quiet >/dev/null || true; fi'"
1829
1928
  }]
1830
1929
  }],
1831
1930
  PreToolUse: [{
@@ -99,16 +99,21 @@ Shared closeout sequence applied by every stage skill.
99
99
  ## Required order
100
100
 
101
101
  1. Verify mandatory delegations are completed or explicitly waived.
102
- 2. Update \`.cclaw/state/flow-state.json\`:
103
- - mark passed gates,
104
- - clear blocked gates that are resolved,
105
- - update \`guardEvidence\`.
106
- 3. Persist stage artifact under \`.cclaw/artifacts/\`.
107
- 4. Run \`npx cclaw doctor\` and resolve failures.
108
- 5. **Capture through-flow learnings** see the policy below. Knowledge
102
+ 2. Persist stage artifact under \`.cclaw/artifacts/\`.
103
+ 3. Use the canonical helper:
104
+ - \`bash .cclaw/hooks/stage-complete.sh <stage>\`
105
+ - helper responsibilities: validate mandatory delegations, validate
106
+ current-stage gate evidence/artifact lint, update
107
+ \`stageGateCatalog\` + \`guardEvidence\`, and advance \`currentStage\`.
108
+ 4. Legacy fallback (only when helper is unavailable): manually edit
109
+ \`.cclaw/state/flow-state.json\` to mark passed gates, clear resolved
110
+ blocked gates, and update \`guardEvidence\`. This path is legacy and
111
+ intentionally noisy in workflow guards.
112
+ 5. Run \`npx cclaw doctor\` and resolve failures.
113
+ 6. **Capture through-flow learnings** — see the policy below. Knowledge
109
114
  accrues continuously across stages, not just at retro.
110
- 6. Notify user with stage completion and next action (\`/cc-next\`).
111
- 7. Stop; do not auto-run the next stage unless user asks.
115
+ 7. Notify user with stage completion and next action (\`/cc-next\`).
116
+ 8. Stop; do not auto-run the next stage unless user asks.
112
117
 
113
118
  ## Through-flow knowledge capture
114
119
 
@@ -222,6 +222,9 @@ function completionParametersBlock(schema) {
222
222
  - \`gates\`: ${gateList}
223
223
  - \`artifact\`: \`${RUNTIME_ROOT}/artifacts/${schema.artifactFile}\`
224
224
  - \`mandatory delegations\`: ${mandatory}
225
+ - \`completion helper\`: \`bash .cclaw/hooks/stage-complete.sh ${schema.stage}\`
226
+ - Record mandatory delegation completion/waiver in \`${RUNTIME_ROOT}/state/delegation-log.json\` with rationale as needed.
227
+ - Use the completion helper instead of raw \`flow-state.json\` edits (legacy direct edits trigger workflow-guard warnings or strict-mode blocks).
225
228
 
226
229
  Apply shared completion logic from:
227
230
  \`${COMPLETION_PROTOCOL_PATH}\`
@@ -42,6 +42,7 @@ export const DESIGN = {
42
42
  "If a section has no issues, say 'No issues found' and move on.",
43
43
  "Do not skip failure-mode mapping.",
44
44
  "For design baseline approval: present the full baseline. **STOP.** Do NOT proceed until user explicitly approves the design.",
45
+ "**STOP BEFORE ADVANCE.** Mandatory delegation `planner` must be marked completed or explicitly waived in `.cclaw/state/delegation-log.json`. Then close the stage via `bash .cclaw/hooks/stage-complete.sh design` (do not hand-edit `.cclaw/state/flow-state.json`).",
45
46
  "Take a firm position on every recommendation. Do NOT hedge with 'it depends' or 'you could do either'. State your opinion, then justify it.",
46
47
  "Use pushback patterns for weak framing: if the user says 'it's just a small change', respond with 'small changes to shared interfaces have outsized blast radius — let's map it'. If 'we'll refactor later', respond with 'later never comes — show me the refactor ticket or do it now'.",
47
48
  "When the user's proposed architecture is suboptimal, say so directly. Offer the alternative with concrete trade-offs, do not bury criticism in praise.",
@@ -29,7 +29,7 @@ export const PLAN = {
29
29
  "Map scope Locked Decisions — every D-XX from scope is referenced by at least one plan task (or explicitly marked deferred with reason).",
30
30
  "Run anti-placeholder + anti-scope-reduction scans — block `TODO/TBD/...` and phrasing like `v1`, `for now`, `later` for locked boundaries.",
31
31
  "Define checkpoints — mark points where progress should be validated before continuing.",
32
- "WAIT_FOR_CONFIRM — write plan artifact and explicitly pause. **STOP.** Do NOT proceed until user confirms. Then update `flow-state.json` and tell user to run `/cc-next`."
32
+ "WAIT_FOR_CONFIRM — write plan artifact and explicitly pause. **STOP.** Do NOT proceed until user confirms. Then close the stage with `bash .cclaw/hooks/stage-complete.sh plan` and tell user to run `/cc-next`."
33
33
  ],
34
34
  interactionProtocol: [
35
35
  "Plan in read-only mode relative to implementation.",
@@ -38,7 +38,8 @@ export const PLAN = {
38
38
  "Attach verification step to every task.",
39
39
  "Preserve locked scope boundaries: no silent scope reduction language in task rows.",
40
40
  "Enforce WAIT_FOR_CONFIRM: present the plan summary with options (A) Approve / (B) Revise / (C) Reject.",
41
- "**STOP.** Do NOT proceed until user explicitly approves. Then update `flow-state.json` and tell user to run `/cc-next`."
41
+ "**STOP.** Do NOT proceed until user explicitly approves.",
42
+ "**STOP BEFORE ADVANCE.** Mandatory delegation `planner` must be marked completed or explicitly waived in `.cclaw/state/delegation-log.json`. Then close the stage via `bash .cclaw/hooks/stage-complete.sh plan` and tell the user to run `/cc-next`."
42
43
  ],
43
44
  process: [
44
45
  "Build dependency graph and ordered slices.",
@@ -41,7 +41,8 @@ export const SCOPE = {
41
41
  "Record explicit in-scope and out-of-scope contract.",
42
42
  "Once the user accepts or rejects a recommendation, commit fully. Do not re-argue.",
43
43
  "Produce a clean scope summary after all issues are resolved.",
44
- "**STOP.** Wait for explicit user approval of scope contract before advancing to design."
44
+ "**STOP.** Wait for explicit user approval of scope contract before advancing to design.",
45
+ "**STOP BEFORE ADVANCE.** Mandatory delegation `planner` must be marked completed or explicitly waived in `.cclaw/state/delegation-log.json`. Then close the stage via `bash .cclaw/hooks/stage-complete.sh scope` (do not hand-edit `.cclaw/state/flow-state.json`)."
45
46
  ],
46
47
  process: [
47
48
  "Run premise challenge and existing-solution leverage check.",
@@ -92,18 +92,11 @@ export const TDD = {
92
92
  ],
93
93
  commonRationalizations: [
94
94
  "Writing code before failing test",
95
- "Asserting implementation details instead of behavior",
96
- "Big-bang implementation across multiple slices",
97
95
  "Partial test runs presented as GREEN",
98
96
  "Skipping evidence capture",
99
97
  "Undocumented refactor changes",
100
- "Adding features beyond what RED tests require",
101
- "No failing test output (RED missing)",
102
- "Implementation edits appear before RED evidence",
103
98
  "No full-suite GREEN evidence",
104
- "No refactor notes",
105
- "Multiple tasks implemented in one pass without justification",
106
- "Files changed outside current slice scope"
99
+ "Multiple tasks implemented in one pass without justification"
107
100
  ],
108
101
  policyNeedles: ["RED", "GREEN", "REFACTOR", "failing test", "full test suite", "acceptance criteria", "traceable to plan slice"],
109
102
  artifactFile: "06-tdd.md",
package/dist/install.d.ts CHANGED
@@ -9,13 +9,12 @@ export declare function syncCclaw(projectRoot: string): Promise<void>;
9
9
  /**
10
10
  * Refresh generated files in `.cclaw/` without touching user-authored
11
11
  * artifacts, state, or custom config keys. Only the `version` + `flowVersion`
12
- * stamps are rewritten so the on-disk config reflects the installed CLI;
13
- * `promptGuardMode`, `tddEnforcement`, `gitHookGuards`, `languageRulePacks`,
14
- * `trackHeuristics`, and `sliceReview` are preserved verbatim from the
15
- * existing config.
12
+ * stamps are rewritten so the on-disk config reflects the installed CLI.
16
13
  *
17
- * For an explicit reset, run `cclaw-cli uninstall && cclaw-cli init`
18
- * (after optionally archiving the current run via `/cc-ops archive`).
14
+ * Shape preservation: if the user previously hand-authored advanced keys
15
+ * (e.g. `tddTestGlobs`, `trackHeuristics`, `sliceReview`), those stay in the
16
+ * yaml. If their existing config is minimal, the upgrade keeps it minimal —
17
+ * advanced knobs are never silently added.
19
18
  */
20
19
  export declare function upgradeCclaw(projectRoot: string): Promise<void>;
21
20
  export declare function uninstallCclaw(projectRoot: string): Promise<void>;
package/dist/install.js CHANGED
@@ -3,7 +3,7 @@ import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { promisify } from "node:util";
5
5
  import { CCLAW_VERSION, COMMAND_FILE_ORDER, FLOW_VERSION, REQUIRED_DIRS, RUNTIME_ROOT } from "./constants.js";
6
- import { writeConfig, createDefaultConfig, readConfig, configPath } from "./config.js";
6
+ import { writeConfig, createDefaultConfig, readConfig, configPath, detectLanguageRulePacks, detectAdvancedKeys } from "./config.js";
7
7
  import { commandContract } from "./content/contracts.js";
8
8
  import { contextModeFiles, createInitialContextModeState } from "./content/contexts.js";
9
9
  import { learnSkillMarkdown, learnCommandContract } from "./content/learnings.js";
@@ -23,7 +23,7 @@ import { archiveCommandContract, archiveCommandSkillMarkdown } from "./content/a
23
23
  import { rewindCommandContract, rewindCommandSkillMarkdown } from "./content/rewind-command.js";
24
24
  import { subagentDrivenDevSkill, parallelAgentsSkill } from "./content/subagents.js";
25
25
  import { sessionHooksSkillMarkdown } from "./content/session-hooks.js";
26
- import { sessionStartScript, stopCheckpointScript, preCompactScript, opencodePluginJs, claudeHooksJson, codexHooksJson, cursorHooksJson } from "./content/hooks.js";
26
+ import { sessionStartScript, stopCheckpointScript, stageCompleteScript, preCompactScript, opencodePluginJs, claudeHooksJson, codexHooksJson, cursorHooksJson } from "./content/hooks.js";
27
27
  import { contextMonitorScript, promptGuardScript, workflowGuardScript } from "./content/observe.js";
28
28
  import { META_SKILL_NAME, usingCclawSkillMarkdown } from "./content/meta-skill.js";
29
29
  import { decisionProtocolMarkdown, completionProtocolMarkdown, ethosProtocolMarkdown } from "./content/protocols.js";
@@ -616,11 +616,13 @@ async function writeHooks(projectRoot, config) {
616
616
  await ensureDir(hooksDir);
617
617
  await writeFileSafe(path.join(hooksDir, "session-start.sh"), sessionStartScript());
618
618
  await writeFileSafe(path.join(hooksDir, "stop-checkpoint.sh"), stopCheckpointScript());
619
+ await writeFileSafe(path.join(hooksDir, "stage-complete.sh"), stageCompleteScript());
619
620
  await writeFileSafe(path.join(hooksDir, "pre-compact.sh"), preCompactScript());
620
621
  await writeFileSafe(path.join(hooksDir, "prompt-guard.sh"), promptGuardScript({
621
622
  strictMode: config.promptGuardMode === "strict"
622
623
  }));
623
624
  await writeFileSafe(path.join(hooksDir, "workflow-guard.sh"), workflowGuardScript({
625
+ workflowGuardMode: config.strictness ?? "advisory",
624
626
  tddEnforcementMode: config.tddEnforcement ?? "advisory",
625
627
  tddTestGlobs: config.tddTestGlobs
626
628
  }));
@@ -631,6 +633,7 @@ async function writeHooks(projectRoot, config) {
631
633
  for (const script of [
632
634
  "session-start.sh",
633
635
  "stop-checkpoint.sh",
636
+ "stage-complete.sh",
634
637
  "pre-compact.sh",
635
638
  "prompt-guard.sh",
636
639
  "workflow-guard.sh",
@@ -1156,13 +1159,24 @@ async function materializeRuntime(projectRoot, config, forceStateReset) {
1156
1159
  await ensureGitignore(projectRoot);
1157
1160
  }
1158
1161
  export async function initCclaw(options) {
1159
- const config = createDefaultConfig(options.harnesses, options.track);
1160
- await writeConfig(options.projectRoot, config);
1162
+ const baseConfig = createDefaultConfig(options.harnesses, options.track);
1163
+ // Best-effort auto-detect: a Node project gets `typescript`, a Go module
1164
+ // gets `go`, etc. Skipped entirely when the project root has no manifests.
1165
+ const detectedPacks = await detectLanguageRulePacks(options.projectRoot);
1166
+ const config = {
1167
+ ...baseConfig,
1168
+ languageRulePacks: detectedPacks
1169
+ };
1170
+ // Write a minimal `config.yaml` — advanced knobs live in docs/config.md
1171
+ // and only appear in the on-disk file when the user sets them explicitly
1172
+ // or a non-default value was detected (e.g. languageRulePacks).
1173
+ await writeConfig(options.projectRoot, config, { mode: "minimal" });
1161
1174
  await materializeRuntime(options.projectRoot, config, true);
1162
1175
  }
1163
1176
  export async function syncCclaw(projectRoot) {
1177
+ const configExists = await exists(configPath(projectRoot));
1164
1178
  const config = await readConfig(projectRoot);
1165
- if (!(await exists(configPath(projectRoot)))) {
1179
+ if (!configExists) {
1166
1180
  await writeConfig(projectRoot, createDefaultConfig(config.harnesses));
1167
1181
  }
1168
1182
  await materializeRuntime(projectRoot, config, false);
@@ -1170,22 +1184,25 @@ export async function syncCclaw(projectRoot) {
1170
1184
  /**
1171
1185
  * Refresh generated files in `.cclaw/` without touching user-authored
1172
1186
  * artifacts, state, or custom config keys. Only the `version` + `flowVersion`
1173
- * stamps are rewritten so the on-disk config reflects the installed CLI;
1174
- * `promptGuardMode`, `tddEnforcement`, `gitHookGuards`, `languageRulePacks`,
1175
- * `trackHeuristics`, and `sliceReview` are preserved verbatim from the
1176
- * existing config.
1187
+ * stamps are rewritten so the on-disk config reflects the installed CLI.
1177
1188
  *
1178
- * For an explicit reset, run `cclaw-cli uninstall && cclaw-cli init`
1179
- * (after optionally archiving the current run via `/cc-ops archive`).
1189
+ * Shape preservation: if the user previously hand-authored advanced keys
1190
+ * (e.g. `tddTestGlobs`, `trackHeuristics`, `sliceReview`), those stay in the
1191
+ * yaml. If their existing config is minimal, the upgrade keeps it minimal —
1192
+ * advanced knobs are never silently added.
1180
1193
  */
1181
1194
  export async function upgradeCclaw(projectRoot) {
1195
+ const advancedKeysPresent = await detectAdvancedKeys(projectRoot);
1182
1196
  const existing = await readConfig(projectRoot);
1183
1197
  const upgraded = {
1184
1198
  ...existing,
1185
1199
  version: CCLAW_VERSION,
1186
1200
  flowVersion: FLOW_VERSION
1187
1201
  };
1188
- await writeConfig(projectRoot, upgraded);
1202
+ await writeConfig(projectRoot, upgraded, {
1203
+ mode: "minimal",
1204
+ advancedKeysPresent
1205
+ });
1189
1206
  await materializeRuntime(projectRoot, upgraded, false);
1190
1207
  }
1191
1208
  function stripManagedHookCommands(value) {
@@ -1246,7 +1263,12 @@ function stripManagedHookCommands(value) {
1246
1263
  }
1247
1264
  function isManagedRuntimeHookCommand(command) {
1248
1265
  const normalized = command.trim().replace(/\s+/gu, " ");
1249
- return /(^|\s)(?:bash\s+)?(?:\.\/)?\.cclaw\/hooks\/(?:session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor)\.sh(?:\s|$)/u.test(normalized);
1266
+ if (/(^|\s)(?:bash\s+)?(?:\.\/)?\.cclaw\/hooks\/(?:session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor)\.sh(?:\s|$)/u.test(normalized)) {
1267
+ return true;
1268
+ }
1269
+ // Codex UserPromptSubmit non-blocking state nudge:
1270
+ // bash -lc '... cclaw internal verify-current-state --quiet ...'
1271
+ return /internal verify-current-state --quiet/u.test(normalized);
1250
1272
  }
1251
1273
  async function removeManagedHookEntries(hookFilePath) {
1252
1274
  if (!(await exists(hookFilePath)))
@@ -0,0 +1,7 @@
1
+ import type { Writable } from "node:stream";
2
+ interface InternalIo {
3
+ stdout: Writable;
4
+ stderr: Writable;
5
+ }
6
+ export declare function runInternalCommand(projectRoot: string, argv: string[], io: InternalIo): Promise<number>;
7
+ export {};