gnhf 0.1.11 → 0.1.12

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 (3) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.mjs +21 -13
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -128,7 +128,7 @@ npm link
128
128
  ```
129
129
 
130
130
  - **Incremental commits** — each successful iteration is a separate git commit, so you can cherry-pick or revert individual changes
131
- - **Runtime caps** — `--max-iterations` stops before the next iteration begins, while `--max-tokens` can abort mid-iteration once reported usage reaches the cap; uncommitted work is rolled back in either case
131
+ - **Runtime caps** — `--max-iterations` stops before the next iteration begins, while `--max-tokens` can abort mid-iteration once reported usage reaches the cap; uncommitted work is rolled back in either case, and in the interactive TUI the final state remains visible until you press Ctrl+C to exit
132
132
  - **Shared memory** — the agent reads `notes.md` (built up from prior iterations) to communicate across iterations
133
133
  - **Local run metadata** — gnhf stores prompt, notes, and resume metadata under `.gnhf/runs/` and ignores it locally, so your branch only contains intentional work
134
134
  - **Resume support** — run `gnhf` while on an existing `gnhf/` branch to pick up where a previous run left off
package/dist/cli.mjs CHANGED
@@ -2083,23 +2083,23 @@ function createAgent(name, runInfo, pathOverride) {
2083
2083
  //#endregion
2084
2084
  //#region src/templates/iteration-prompt.ts
2085
2085
  function buildIterationPrompt(params) {
2086
- return `You are working autonomously on an objective given below.
2087
- This is iteration ${params.n} of an ongoing loop to fully accomplish the objective.
2086
+ return `You are working autonomously towards an objective given below.
2087
+ This is iteration ${params.n}. Each iteration aims to make an incremental step forward, not to complete the entire objective.
2088
2088
 
2089
2089
  ## Instructions
2090
2090
 
2091
- 1. Read .gnhf/runs/${params.runId}/notes.md first to understand what has been done in previous iterations.
2092
- 2. Focus on the next smallest logical unit of work that's individually testable and would make incremental progress towards the objective - that's the scope of this iteration.
2093
- 3. If you made code changes, run build/tests/linters/formatters if available to validate your work.
2094
- 4. Do NOT make any git commits. Commits will be handled automatically by the gnhf orchestrator.
2095
- 5. When you are done, respond with a JSON object according to the provided schema.
2091
+ 1. Read .gnhf/runs/${params.runId}/notes.md first to understand what has been done in previous iterations
2092
+ 2. Identify the next smallest logical unit of work that's individually verifiable and would make incremental progress towards the objective, and treat that as the scope of this iteration
2093
+ 3. If you attempted a solution and it didn't end up moving the needle on the objective, document learnings and record success=false, then conclude the iteration rather than continuously pivoting
2094
+ 4. If you made code changes, run build/tests/linters/formatters if available to validate your work. Do NOT make any git commits - that will be handled automatically by the gnhf orchestrator
2095
+ 6. Finally, respond with a JSON object according to the provided schema
2096
2096
 
2097
2097
  ## Output
2098
2098
 
2099
- - success: whether you were able to complete your iteration. set to false only if something made it impossible for you to do your work
2099
+ - success: whether you were able to make a meaningful contribution that got us closer towards the objective. setting this to false means any code change you made should be discarded
2100
2100
  - summary: a concise one-sentence summary of the accomplishment in this iteration
2101
2101
  - key_changes_made: an array of descriptions for key changes you made. don't group this by file - group by logical units of work. don't describe activities - describe material outcomes
2102
- - key_learnings: an array of new learnings that were surprising and weren't captured by previous notes
2102
+ - key_learnings: an array of new learnings that were surprising, weren't captured by previous notes and would be informative for future iterations
2103
2103
 
2104
2104
  ## Objective
2105
2105
 
@@ -2120,6 +2120,7 @@ var Orchestrator = class extends EventEmitter {
2120
2120
  activeIterationPromise = null;
2121
2121
  activeAbortController = null;
2122
2122
  pendingAbortReason = null;
2123
+ loopDone = false;
2123
2124
  state = {
2124
2125
  status: "running",
2125
2126
  currentIteration: 0,
@@ -2151,6 +2152,10 @@ var Orchestrator = class extends EventEmitter {
2151
2152
  stop() {
2152
2153
  this.stopRequested = true;
2153
2154
  this.activeAbortController?.abort();
2155
+ if (this.loopDone) {
2156
+ this.emit("stopped");
2157
+ return;
2158
+ }
2154
2159
  if (this.stopPromise) return;
2155
2160
  this.stopPromise = (async () => {
2156
2161
  if (this.activeIterationPromise) {
@@ -2234,6 +2239,7 @@ var Orchestrator = class extends EventEmitter {
2234
2239
  this.activeIterationPromise = null;
2235
2240
  if (this.stopPromise) await this.stopPromise;
2236
2241
  else await this.closeAgent();
2242
+ this.loopDone = true;
2237
2243
  }
2238
2244
  }
2239
2245
  async runIteration(prompt) {
@@ -2758,6 +2764,7 @@ const MOON_PHASE_PERIOD = 1600;
2758
2764
  const MAX_MSG_LINES = 3;
2759
2765
  const MAX_MSG_LINE_LEN = CONTENT_WIDTH;
2760
2766
  const RESUME_HINT = "[ctrl+c to stop, gnhf again to resume]";
2767
+ const DONE_HINT = "[ctrl+c to exit]";
2761
2768
  function spacedLabel(text) {
2762
2769
  return text.split("").join(" ");
2763
2770
  }
@@ -2878,8 +2885,8 @@ function centerLineCells(content, width) {
2878
2885
  ...emptyCells(rightPad)
2879
2886
  ];
2880
2887
  }
2881
- function renderResumeHintCells(width) {
2882
- return centerLineCells(textToCells(RESUME_HINT, "dim"), width);
2888
+ function renderResumeHintCells(width, done) {
2889
+ return centerLineCells(textToCells(done ? DONE_HINT : RESUME_HINT, "dim"), width);
2883
2890
  }
2884
2891
  /**
2885
2892
  * Builds the centered content viewport for the renderer.
@@ -2987,7 +2994,8 @@ function buildFrameCells(prompt, agentName, state, topStars, bottomStars, sideSt
2987
2994
  ]);
2988
2995
  }
2989
2996
  for (let y = 0; y < bottomHeight; y++) frame.push(renderStarLineCells(bottomStars, terminalWidth, y, now));
2990
- frame.push(renderResumeHintCells(terminalWidth));
2997
+ const isDone = state.status === "aborted";
2998
+ frame.push(renderResumeHintCells(terminalWidth, isDone));
2991
2999
  frame.push(emptyCells(terminalWidth));
2992
3000
  return frame;
2993
3001
  }
@@ -3298,7 +3306,7 @@ program.name("gnhf").description("Before I go to bed, I tell my agents: good nig
3298
3306
  process$1.on("SIGINT", handleSigInt);
3299
3307
  process$1.on("SIGTERM", handleSigTerm);
3300
3308
  const orchestratorPromise = orchestrator.start().finally(() => {
3301
- renderer.stop();
3309
+ if (!(orchestrator.getState().status === "aborted" && process$1.stdin.isTTY)) renderer.stop();
3302
3310
  }).catch((err) => {
3303
3311
  exitAltScreen();
3304
3312
  die(err instanceof Error ? err.message : String(err));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gnhf",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Before I go to bed, I tell my agents: good night, have fun",
5
5
  "type": "module",
6
6
  "bin": {