wile 0.6.1 → 0.6.2

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.
@@ -274,13 +274,21 @@ mkdir -p .wile/screenshots
274
274
 
275
275
  echo ""
276
276
  echo "══════════════════════════════════════════════════════"
277
- echo " Starting Wile Loop"
277
+ if [ "${WILE_MODE:-}" = "compact" ]; then
278
+ echo " Starting Wile Compact"
279
+ else
280
+ echo " Starting Wile Loop"
281
+ fi
278
282
  echo "══════════════════════════════════════════════════════"
279
283
  echo ""
280
284
 
281
- # Run the main loop
285
+ # Run the main loop or compact flow
282
286
  EXIT_CODE=0
283
- "$SCRIPT_DIR/wile.sh" "$MAX_ITERATIONS" || EXIT_CODE=$?
287
+ if [ "${WILE_MODE:-}" = "compact" ]; then
288
+ "$SCRIPT_DIR/wile-compact.sh" || EXIT_CODE=$?
289
+ else
290
+ "$SCRIPT_DIR/wile.sh" "$MAX_ITERATIONS" || EXIT_CODE=$?
291
+ fi
284
292
 
285
293
  echo ""
286
294
  echo "══════════════════════════════════════════════════════"
@@ -290,8 +298,18 @@ echo "════════════════════════
290
298
  # Handle completion/partial completion
291
299
  if [ $EXIT_CODE -eq 0 ]; then
292
300
  echo "All tasks completed successfully!"
293
- # Ensure final state is pushed
294
- git push || true
301
+ if [ "${WILE_MODE:-}" = "compact" ]; then
302
+ if ! git diff --quiet || ! git diff --staged --quiet; then
303
+ git add -A
304
+ git commit -m "chore: compact wile prd and progress"
305
+ git push || true
306
+ else
307
+ git push || true
308
+ fi
309
+ else
310
+ # Ensure final state is pushed
311
+ git push || true
312
+ fi
295
313
  elif [ $EXIT_CODE -eq 1 ]; then
296
314
  echo "Max iterations reached. Committing partial work..."
297
315
 
@@ -1,6 +1,56 @@
1
1
  #!/bin/sh
2
2
  set -e
3
3
 
4
+ if [ "${WILE_MODE:-}" = "compact" ]; then
5
+ node - <<'NODE'
6
+ const fs = require("fs");
7
+
8
+ const prdPath = ".wile/prd.json";
9
+ const progressPath = ".wile/progress.txt";
10
+ const prd = JSON.parse(fs.readFileSync(prdPath, "utf8"));
11
+ const stories = Array.isArray(prd.userStories) ? prd.userStories : [];
12
+ const firstStory = stories[0] || {};
13
+ const lastStory = stories[stories.length - 1] || {};
14
+ const priority = typeof firstStory.priority === "number" ? firstStory.priority : 1;
15
+ const taskIds = `From ${firstStory.id || "TASK-001"} to ${lastStory.id || "TASK-001"}`;
16
+
17
+ const compactStory = {
18
+ id: "GROUP-001",
19
+ title: "summary of everything done here",
20
+ tasks: [
21
+ "High level of what was accomplished here",
22
+ "Should NOT have all tasks in here, should be very summarized"
23
+ ],
24
+ taskIds,
25
+ priority,
26
+ passes: true,
27
+ notes: "Don't repeat task ids when starting the next one."
28
+ };
29
+
30
+ fs.writeFileSync(prdPath, JSON.stringify({ userStories: [compactStory] }, null, 2) + "\n");
31
+
32
+ const progressLines = [
33
+ "# Wile Progress Log",
34
+ "",
35
+ "## Codebase Patterns",
36
+ "- Summarized key learnings for future agents.",
37
+ "",
38
+ "---",
39
+ "",
40
+ "Compacted the progress log to highlight the most important work and patterns.",
41
+ "Kept only high-level details to preserve context without noise.",
42
+ ""
43
+ ];
44
+
45
+ fs.writeFileSync(progressPath, progressLines.join("\n"));
46
+ NODE
47
+
48
+ cat <<'JSON'
49
+ {"type":"assistant","message":{"content":[{"type":"text","text":"{\"id\":\"GROUP-001\",\"title\":\"summary of everything done here\",\"tasks\":[\"High level of what was accomplished here\",\"Should NOT have all tasks in here, should be very summarized\"],\"taskIds\":\"From TASK-001 to TASK-029\",\"priority\":1,\"passes\":true,\"notes\":\"Don't repeat task ids when starting the next one.\"}\n"}]}}
50
+ JSON
51
+ exit 0
52
+ fi
53
+
4
54
  COUNT_FILE="/tmp/wile-claude-mock-count"
5
55
  if [ ! -f "$COUNT_FILE" ]; then
6
56
  echo "0" > "$COUNT_FILE"
@@ -0,0 +1,41 @@
1
+ You are running a one-shot compaction task.
2
+
3
+ Goal: compact both `.wile/prd.json` and `.wile/progress.txt` while preserving important information.
4
+
5
+ Steps:
6
+ 1. Read `.wile/prd.json` and `.wile/progress.txt`.
7
+ 2. Update `.wile/prd.json` to:
8
+ - Keep every story where `passes` is `false` exactly as-is.
9
+ - Replace all stories where `passes` is `true` with a single grouped story.
10
+ - The final structure must be: `{ "userStories": [ { ...GROUP-001... }, ...all-passes-false-stories ] }`.
11
+ - The grouped story must use `id: "GROUP-001"`.
12
+ - `title`: a concise summary of everything done.
13
+ - `tasks`: 2-4 short bullet items derived from the summary tasks.
14
+ - `taskIds`: a single string in the form `From TASK-001 to TASK-029` using the first and last task IDs you find.
15
+ - `priority`: copy the priority from the first story in the original file.
16
+ - `passes`: `true` (hardcoded).
17
+ - `notes`: `Don't repeat task ids when starting the next one.` (exact text).
18
+ 3. Update `.wile/progress.txt`:
19
+ - Keep the header `# Wile Progress Log` and `## Codebase Patterns`.
20
+ - Add bullet points at the top under `## Codebase Patterns` for any important learnings that would help future agents.
21
+ - Replace the rest of the log with a short, high-level summary in a few paragraphs.
22
+ - Do not lose important info, but avoid detailed step-by-step logs.
23
+ - Ignore preflight failures in the history.
24
+
25
+ Response format:
26
+ - Your response must end with a single-line JSON object and nothing after it (no trailing text).
27
+ - The final non-empty line of output must be valid JSON exactly matching this shape:
28
+ {
29
+ "id": "GROUP-001",
30
+ "title": "summary of everything done here",
31
+ "tasks": [
32
+ "High level of what was accomplished here",
33
+ "Should NOT have all tasks in here, should be very summarized"
34
+ ],
35
+ "taskIds": "From TASK-001 to TASK-029",
36
+ "priority": 1,
37
+ "passes": true,
38
+ "notes": "Don't repeat task ids when starting the next one."
39
+ }
40
+ - Do not wrap the JSON in code fences.
41
+ - Ensure nothing appears after the JSON line.
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env node
2
+ const fs = require("node:fs");
3
+
4
+ const prdPath = ".wile/prd.json";
5
+ const progressPath = ".wile/progress.txt";
6
+ const prdOriginalPath = ".wile/prd.json.original";
7
+
8
+ if (!fs.existsSync(prdPath)) {
9
+ console.error("Missing .wile/prd.json after compact.");
10
+ process.exit(1);
11
+ }
12
+
13
+ if (!fs.existsSync(progressPath)) {
14
+ console.error("Missing .wile/progress.txt after compact.");
15
+ process.exit(1);
16
+ }
17
+
18
+ let payload;
19
+ try {
20
+ payload = JSON.parse(fs.readFileSync(prdPath, "utf8"));
21
+ } catch {
22
+ console.error("Compacted .wile/prd.json is not valid JSON.");
23
+ process.exit(1);
24
+ }
25
+
26
+ if (!payload || !Array.isArray(payload.userStories) || payload.userStories.length === 0) {
27
+ console.error("Compacted .wile/prd.json must contain at least one user story.");
28
+ process.exit(1);
29
+ }
30
+
31
+ const groupStory = payload.userStories.find((story) => story?.id === "GROUP-001");
32
+ if (!groupStory) {
33
+ console.error('Compacted .wile/prd.json must include a GROUP-001 story.');
34
+ process.exit(1);
35
+ }
36
+
37
+ const requiredKeys = ["id", "title", "tasks", "taskIds", "priority", "passes", "notes"];
38
+ for (const key of requiredKeys) {
39
+ if (!(key in groupStory)) {
40
+ console.error(`Compact output missing key: ${key}`);
41
+ process.exit(1);
42
+ }
43
+ }
44
+
45
+ if (groupStory.id !== "GROUP-001") {
46
+ console.error('Compact output "id" must be GROUP-001.');
47
+ process.exit(1);
48
+ }
49
+
50
+ if (typeof groupStory.title !== "string" || groupStory.title.trim().length === 0) {
51
+ console.error('Compact output "title" must be a non-empty string.');
52
+ process.exit(1);
53
+ }
54
+
55
+ if (!Array.isArray(groupStory.tasks) || groupStory.tasks.length === 0) {
56
+ console.error('Compact output "tasks" must be a non-empty array.');
57
+ process.exit(1);
58
+ }
59
+
60
+ if (!groupStory.tasks.every((task) => typeof task === "string" && task.trim().length > 0)) {
61
+ console.error('Compact output "tasks" must contain only non-empty strings.');
62
+ process.exit(1);
63
+ }
64
+
65
+ if (typeof groupStory.taskIds !== "string" || groupStory.taskIds.trim().length === 0) {
66
+ console.error('Compact output "taskIds" must be a non-empty string.');
67
+ process.exit(1);
68
+ }
69
+
70
+ if (typeof groupStory.priority !== "number" || !Number.isFinite(groupStory.priority)) {
71
+ console.error('Compact output "priority" must be a number.');
72
+ process.exit(1);
73
+ }
74
+
75
+ if (groupStory.passes !== true) {
76
+ console.error('Compact output "passes" must be true.');
77
+ process.exit(1);
78
+ }
79
+
80
+ if (groupStory.notes !== "Don't repeat task ids when starting the next one.") {
81
+ console.error('Compact output "notes" must match the required text.');
82
+ process.exit(1);
83
+ }
84
+
85
+ if (fs.existsSync(prdOriginalPath)) {
86
+ let original;
87
+ try {
88
+ original = JSON.parse(fs.readFileSync(prdOriginalPath, "utf8"));
89
+ } catch {
90
+ console.error("Original .wile/prd.json.original is not valid JSON.");
91
+ process.exit(1);
92
+ }
93
+ if (!original || !Array.isArray(original.userStories)) {
94
+ console.error("Original .wile/prd.json.original is missing userStories.");
95
+ process.exit(1);
96
+ }
97
+ const originalPending = original.userStories.filter((story) => story?.passes === false);
98
+ const currentPending = payload.userStories.filter((story) => story?.passes === false);
99
+ if (originalPending.length !== currentPending.length) {
100
+ console.error("Compaction must preserve all passes:false stories.");
101
+ process.exit(1);
102
+ }
103
+ const missingPending = originalPending.filter(
104
+ (story) => !currentPending.some((current) => current?.id === story?.id)
105
+ );
106
+ if (missingPending.length > 0) {
107
+ console.error("Compaction removed passes:false stories.");
108
+ process.exit(1);
109
+ }
110
+ }
111
+
112
+ const progressText = fs.readFileSync(progressPath, "utf8");
113
+ if (!progressText.startsWith("# Wile Progress Log")) {
114
+ console.error("Compacted progress log must start with # Wile Progress Log.");
115
+ process.exit(1);
116
+ }
117
+
118
+ if (!progressText.includes("## Codebase Patterns")) {
119
+ console.error("Compacted progress log must include ## Codebase Patterns.");
120
+ process.exit(1);
121
+ }
@@ -0,0 +1,96 @@
1
+ #!/bin/bash
2
+ #
3
+ # Wile - Compact PRD/Progress
4
+ #
5
+
6
+ set -e
7
+
8
+ CODING_AGENT=${CODING_AGENT:-CC}
9
+ CLAUDE_MODEL=${CC_CLAUDE_MODEL:-sonnet}
10
+ OC_PROVIDER=${OC_PROVIDER:-native}
11
+ OC_MODEL=${OC_MODEL:-opencode/grok-code}
12
+
13
+ # For openrouter provider, prepend vendor prefix if missing
14
+ if [ "$OC_PROVIDER" = "openrouter" ] && [[ "$OC_MODEL" != */* ]]; then
15
+ OC_MODEL="z-ai/$OC_MODEL"
16
+ fi
17
+
18
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
+ PROMPT_FILE="$SCRIPT_DIR/prompt-compact.md"
20
+ ADDITIONAL_PROMPT_FILE="${WILE_ADDITIONAL_INSTRUCTIONS:-}"
21
+ TEE_TARGET="${WILE_TEE_TARGET:-/dev/stderr}"
22
+ if ! ( : > "$TEE_TARGET" ) 2>/dev/null; then
23
+ TEE_TARGET="/dev/null"
24
+ fi
25
+
26
+ echo "══════════════════════════════════════════════════════"
27
+ echo " 🌵 WILE - Compact PRD & Progress"
28
+ echo "══════════════════════════════════════════════════════"
29
+ echo " Agent: $CODING_AGENT"
30
+ if [ "$CODING_AGENT" = "OC" ]; then
31
+ echo " Provider: $OC_PROVIDER"
32
+ echo " Model: $OC_MODEL"
33
+ else
34
+ echo " Model: $CLAUDE_MODEL"
35
+ fi
36
+ echo " Prompt file: $PROMPT_FILE"
37
+ echo "══════════════════════════════════════════════════════"
38
+ echo ""
39
+
40
+ if [ -n "$ADDITIONAL_PROMPT_FILE" ] && [ -f "$ADDITIONAL_PROMPT_FILE" ]; then
41
+ if [ -s "$ADDITIONAL_PROMPT_FILE" ]; then
42
+ STRIPPED_CONTENT=$(sed '/<!--/,/-->/d' "$ADDITIONAL_PROMPT_FILE" | tr -d '[:space:]')
43
+ if [ -n "$STRIPPED_CONTENT" ]; then
44
+ PROMPT_FILE="/tmp/wile-prompt-compact.md"
45
+ cat "$SCRIPT_DIR/prompt-compact.md" > "$PROMPT_FILE"
46
+ printf "\n\n## Additional Instructions\n\n" >> "$PROMPT_FILE"
47
+ cat "$ADDITIONAL_PROMPT_FILE" >> "$PROMPT_FILE"
48
+ echo " Extra: Using additional instructions"
49
+ echo " Prompt file: $PROMPT_FILE"
50
+ echo ""
51
+ fi
52
+ fi
53
+ fi
54
+
55
+ run_claude() {
56
+ local prompt_path="$1"
57
+ cat "$prompt_path" \
58
+ | claude --model "$CLAUDE_MODEL" --print --output-format stream-json --verbose --dangerously-skip-permissions \
59
+ | node "$SCRIPT_DIR/claude-stream.js"
60
+ }
61
+
62
+ run_opencode() {
63
+ local prompt_path="$1"
64
+ local model_arg="$OC_MODEL"
65
+ if [ "$OC_PROVIDER" = "openrouter" ]; then
66
+ model_arg="openrouter/$OC_MODEL"
67
+ fi
68
+ cat "$prompt_path" \
69
+ | opencode run --format json --model "$model_arg" \
70
+ | node "$SCRIPT_DIR/opencode-stream.js"
71
+ }
72
+
73
+ run_agent() {
74
+ local prompt_path="$1"
75
+ if [ "$CODING_AGENT" = "OC" ]; then
76
+ run_opencode "$prompt_path"
77
+ else
78
+ run_claude "$prompt_path"
79
+ fi
80
+ }
81
+
82
+ # Snapshot original PRD for validation of passes:false preservation.
83
+ if [ -f ".wile/prd.json" ]; then
84
+ cp ".wile/prd.json" ".wile/prd.json.original"
85
+ fi
86
+
87
+ echo "Running compact agent..."
88
+ OUTPUT=$(run_agent "$PROMPT_FILE" | tee "$TEE_TARGET") || true
89
+
90
+ # Validate the resulting files instead of the response format.
91
+ node "$SCRIPT_DIR/validate-compact.js"
92
+
93
+ echo ""
94
+ echo "══════════════════════════════════════════════════════"
95
+ echo " ✅ COMPACT COMPLETE"
96
+ echo "══════════════════════════════════════════════════════"
@@ -134,20 +134,15 @@ for i in $(seq 1 $MAX_ITERATIONS); do
134
134
  # Capture output while also displaying it (tee to stderr)
135
135
  OUTPUT=$(run_agent "$PROMPT_FILE" | tee "$TEE_TARGET") || true
136
136
 
137
- # Check for completion signal (tag must be on its own line; reject backticks/code fences)
137
+ # Check for completion signal (tag must be the final non-empty line)
138
138
  CLEAN_OUTPUT=$(printf '%s' "$OUTPUT" | tr -d '\r' | sed -e 's/[[:space:]]*$//')
139
- if printf '%s\n' "$CLEAN_OUTPUT" | grep -q -E '^[[:space:]]*<promise>ALL_STORIES_COMPLETED</promise>[[:space:]]*$'; then
140
- if printf '%s' "$CLEAN_OUTPUT" | grep -F '```' >/dev/null 2>&1; then
141
- :
142
- elif printf '%s' "$CLEAN_OUTPUT" | grep -F '`<promise>ALL_STORIES_COMPLETED</promise>`' >/dev/null 2>&1; then
143
- :
144
- else
139
+ FINAL_LINE=$(printf '%s\n' "$CLEAN_OUTPUT" | awk 'NF { last=$0 } END { print last }')
140
+ if printf '%s\n' "$FINAL_LINE" | grep -q -E '^[[:space:]]*<promise>ALL_STORIES_COMPLETED</promise>[[:space:]]*$'; then
145
141
  echo ""
146
142
  echo "══════════════════════════════════════════════════════"
147
143
  echo " ✅ ALL TASKS COMPLETE"
148
144
  echo "══════════════════════════════════════════════════════"
149
145
  exit 0
150
- fi
151
146
  fi
152
147
 
153
148
  echo ""
package/dist/cli.js CHANGED
@@ -7681,7 +7681,7 @@ var runConfig = async () => {
7681
7681
  { title: "opus", value: "opus" },
7682
7682
  { title: "haiku", value: "haiku" }
7683
7683
  ],
7684
- initial: existingEnv.CC_CLAUDE_MODEL === "opus" ? 1 : existingEnv.CC_CLAUDE_MODEL === "haiku" ? 2 : 0
7684
+ initial: existingEnv.CC_CLAUDE_MODEL === "sonnet" ? 0 : existingEnv.CC_CLAUDE_MODEL === "haiku" ? 2 : 1
7685
7685
  });
7686
7686
  } else {
7687
7687
  const providerDefault = existingEnv.OC_PROVIDER === "openrouter" ? "openrouter" : "native";
@@ -7874,11 +7874,9 @@ Wile config complete.`);
7874
7874
  }
7875
7875
  };
7876
7876
 
7877
- // src/commands/run.ts
7878
- import { existsSync as existsSync3, readFileSync as readFileSync2, mkdirSync, createWriteStream, writeFileSync } from "node:fs";
7879
- import { spawn, spawnSync } from "node:child_process";
7880
- import { resolve as resolve2, join as join3, dirname } from "node:path";
7881
- import { fileURLToPath } from "node:url";
7877
+ // src/commands/compact.ts
7878
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "node:fs";
7879
+ import { join as join4 } from "node:path";
7882
7880
 
7883
7881
  // src/lib/config.ts
7884
7882
  var import_dotenv2 = __toESM(require_main(), 1);
@@ -7974,6 +7972,10 @@ var readWileConfig = (options = {}) => {
7974
7972
  };
7975
7973
 
7976
7974
  // src/commands/run.ts
7975
+ import { existsSync as existsSync3, readFileSync as readFileSync2, mkdirSync, createWriteStream, writeFileSync } from "node:fs";
7976
+ import { spawn, spawnSync } from "node:child_process";
7977
+ import { resolve as resolve2, join as join3, dirname } from "node:path";
7978
+ import { fileURLToPath } from "node:url";
7977
7979
  var findAgentDir = (startDir) => {
7978
7980
  let current = startDir;
7979
7981
  while (true) {
@@ -8085,7 +8087,7 @@ var runDockerWithLogging = (args, logPath) => new Promise((resolvePromise, rejec
8085
8087
  resolvePromise();
8086
8088
  });
8087
8089
  });
8088
- var buildDockerArgs = (options, config, paths, cwd) => {
8090
+ var buildDockerArgs = (options, config, paths, cwd, extraEnv = []) => {
8089
8091
  const dockerArgs = ["run", "--rm"];
8090
8092
  if (options.test) {
8091
8093
  dockerArgs.push("-e", "WILE_TEST=true", "-e", "WILE_TEST_REPO_PATH=/home/wile/workspace/repo", "-v", `${cwd}:/home/wile/workspace/repo`);
@@ -8106,6 +8108,9 @@ var buildDockerArgs = (options, config, paths, cwd) => {
8106
8108
  for (const envFile of envFiles) {
8107
8109
  dockerArgs.push("--env-file", envFile);
8108
8110
  }
8111
+ for (const envEntry of extraEnv) {
8112
+ dockerArgs.push("-e", envEntry);
8113
+ }
8109
8114
  const additionalInstructionsPath = join3(paths.wileDir, "additional-instructions.md");
8110
8115
  if (existsSync3(additionalInstructionsPath)) {
8111
8116
  dockerArgs.push("-e", `WILE_ADDITIONAL_INSTRUCTIONS=${additionalInstructionsPath}`);
@@ -8177,6 +8182,61 @@ var runWile = async (options) => {
8177
8182
  writeFileSync(logPath, finishMessage, { flag: "a" });
8178
8183
  };
8179
8184
 
8185
+ // src/commands/compact.ts
8186
+ var runCompact = async (options) => {
8187
+ const cwd = process.cwd();
8188
+ let paths;
8189
+ let config;
8190
+ try {
8191
+ const result = readWileConfig({ cwd, validate: !options.test });
8192
+ paths = result.paths;
8193
+ config = result.config;
8194
+ } catch (error) {
8195
+ console.error(error.message);
8196
+ process.exit(1);
8197
+ }
8198
+ if (options.debug) {
8199
+ const initCwd = process.env.INIT_CWD ?? "(unset)";
8200
+ console.log("Debug:");
8201
+ console.log(`- cwd: ${cwd}`);
8202
+ console.log(`- INIT_CWD: ${initCwd}`);
8203
+ console.log(`- WILE_AGENT_DIR: ${process.env.WILE_AGENT_DIR ?? "(unset)"}`);
8204
+ console.log(`- codingAgent: ${config.codingAgent}`);
8205
+ console.log(`- repoSource: ${config.repoSource}`);
8206
+ console.log(`- githubRepoUrl: ${config.githubRepoUrl || "(empty)"}`);
8207
+ console.log(`- branchName: ${config.branchName || "(empty)"}`);
8208
+ }
8209
+ try {
8210
+ validateGitignore(paths.gitignorePath);
8211
+ } catch (error) {
8212
+ console.error(error.message);
8213
+ process.exit(1);
8214
+ }
8215
+ if (!existsSync4(paths.prdPath)) {
8216
+ console.error("Missing .wile/prd.json. Run 'bunx wile config'.");
8217
+ process.exit(1);
8218
+ }
8219
+ const progressPath = join4(paths.wileDir, "progress.txt");
8220
+ if (!existsSync4(progressPath)) {
8221
+ console.error("Missing .wile/progress.txt. Run 'bunx wile config'.");
8222
+ process.exit(1);
8223
+ }
8224
+ const agentDir = resolveAgentDir();
8225
+ const resolvedIterations = options.maxIterations || "1";
8226
+ buildAgentImage(agentDir);
8227
+ const dockerArgs = buildDockerArgs({ ...options, maxIterations: resolvedIterations }, config, paths, cwd, ["WILE_MODE=compact"]);
8228
+ const logsDir = join4(paths.wileDir, "logs");
8229
+ mkdirSync2(logsDir, { recursive: true });
8230
+ const logPath = join4(logsDir, `compact-${getTimestamp()}.log`);
8231
+ writeFileSync2(logPath, "", { flag: "w" });
8232
+ try {
8233
+ await runDockerWithLogging(dockerArgs, logPath);
8234
+ } catch (error) {
8235
+ console.error(error.message);
8236
+ process.exit(1);
8237
+ }
8238
+ };
8239
+
8180
8240
  // src/cli.ts
8181
8241
  var packageJsonPath = resolve3(new URL("../package.json", import.meta.url).pathname);
8182
8242
  var packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf8"));
@@ -8188,4 +8248,7 @@ program2.command("config").description("Configure the current project for Wile")
8188
8248
  program2.command("run").description("Run Wile on a repository").option("--repo <repo>", "Repository URL or local path").option("--max-iterations <count>", "Maximum iterations").option("--test", "Run in test mode").option("--debug", "Print debug info before running").action(async (options) => {
8189
8249
  await runWile(options);
8190
8250
  });
8251
+ program2.command("compact").description("Compact .wile/prd.json and .wile/progress.txt with an agent").option("--repo <repo>", "Repository URL or local path").option("--max-iterations <count>", "Maximum iterations (default: 1)").option("--test", "Run in test mode").option("--debug", "Print debug info before running").action(async (options) => {
8252
+ await runCompact(options);
8253
+ });
8191
8254
  program2.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wile",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Autonomous AI coding agent that ships features while you sleep",
5
5
  "type": "module",
6
6
  "bin": {