@pmelab/gtd 1.5.3 → 1.5.5

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/README.md CHANGED
@@ -442,12 +442,17 @@ loop before the next one starts.
442
442
  (`gtd: done`) → **Squashing** → **Idle**. The Squashing agent authors a
443
443
  conventional-commits message from the full process diff and squashes all
444
444
  intermediate `gtd: *` commits into one with `git reset --soft <base>` +
445
- `git commit`, then **gtd STOPs**. Post-squash review does not fire
446
- automatically it fires only on the next manual `gtd` run (when the squash
447
- commit is the boundary HEAD and a reviewable diff exists). Squashing fires
448
- when the tree has no unrelated code dirty a lone untracked `SQUASH_MSG.md`
449
- is tolerated and deleted before the squash commit. If unrelated code is dirty
450
- at `gtd: done`, gtd routes to **New Feature** instead. Set `squash: false` in
445
+ `git commit`, then **gtd STOPs**. The base is the parent of the current
446
+ cycle's start marker **nearest to HEAD** (the last `gtd: new task`; for
447
+ legacy cycles the last contiguous `gtd: grilling` run), and on a feature
448
+ branch it never reaches below the merge-base with the default branch stray
449
+ markers left behind by older squashes can never drag the squash into
450
+ previously shipped features. Post-squash review does not fire automatically
451
+ it fires only on the next manual `gtd` run (when the squash commit is the
452
+ boundary HEAD and a reviewable diff exists). Squashing fires when the tree
453
+ has no unrelated code dirty — a lone untracked `SQUASH_MSG.md` is tolerated
454
+ and deleted before the squash commit. If unrelated code is dirty at
455
+ `gtd: done`, gtd routes to **New Feature** instead. Set `squash: false` in
451
456
  `.gtdrc` to skip squashing and go straight to Idle. Checking off REVIEW.md
452
457
  checkboxes (`- [ ]` → `- [x]`) also counts as approval and routes to **Done**
453
458
  — they are navigation aids, not feedback. Only **non-checkbox** edits (code
@@ -367877,7 +367877,16 @@ var makeGitImpl = (executor, root2) => {
367877
367877
  }),
367878
367878
  commitAllWithPrefix: (prefix) => Effect_exports.gen(function* () {
367879
367879
  yield* exec2("git", "add", "-A");
367880
- yield* exec2("git", "commit", "--allow-empty", "-m", prefix);
367880
+ yield* exec2("git", "commit", "--allow-empty", "-m", prefix).pipe(
367881
+ Effect_exports.catchAll(
367882
+ (error) => (
367883
+ // Hooks like lint-staged block empty commits even with --allow-empty.
367884
+ // gtd's workflow commits have nothing for code-quality hooks to validate,
367885
+ // so retry without the pre-commit hook when that guard fires.
367886
+ error.message.includes("empty git commit") ? exec2("git", "commit", "--allow-empty", "--no-verify", "-m", prefix) : Effect_exports.fail(error)
367887
+ )
367888
+ )
367889
+ );
367881
367890
  }).pipe(Effect_exports.asVoid),
367882
367891
  softResetTo: (ref) => exec2("git", "reset", "--soft", ref).pipe(Effect_exports.asVoid)
367883
367892
  };
@@ -388091,29 +388100,37 @@ var gatherEvents = () => (
388091
388100
  let squashBase;
388092
388101
  let squashDiff;
388093
388102
  if (hasCommits && lastCommitSubject === DONE_SUBJECT && config2.squash) {
388094
- const allHistoryForSquash = Option_exports.isNone(base) ? history : yield* git.commitHistory();
388095
- const lastDoneIdxForSquash = (() => {
388096
- let idx = -1;
388097
- for (let i = 0; i < allHistoryForSquash.length; i++) {
388098
- const subject = (allHistoryForSquash[i].message.split("\n")[0] ?? "").trim();
388099
- if (subject === DONE_SUBJECT) idx = i;
388103
+ const squashHistory = history;
388104
+ const subjectOf = (c7) => (c7.message.split("\n")[0] ?? "").trim();
388105
+ let lastDoneIdxForSquash = -1;
388106
+ let prevDoneIdx = -1;
388107
+ for (let i = 0; i < squashHistory.length; i++) {
388108
+ if (subjectOf(squashHistory[i]) === DONE_SUBJECT) {
388109
+ prevDoneIdx = lastDoneIdxForSquash;
388110
+ lastDoneIdxForSquash = i;
388100
388111
  }
388101
- return idx;
388102
- })();
388112
+ }
388103
388113
  if (lastDoneIdxForSquash !== -1) {
388104
- let prevDoneIdx = -1;
388105
- for (let i = 0; i < lastDoneIdxForSquash; i++) {
388106
- const subject = (allHistoryForSquash[i].message.split("\n")[0] ?? "").trim();
388107
- if (subject === DONE_SUBJECT) prevDoneIdx = i;
388108
- }
388109
- const squashCycle = allHistoryForSquash.slice(prevDoneIdx + 1, lastDoneIdxForSquash + 1);
388110
- const squashNewTask = squashCycle.find(
388111
- (c7) => (c7.message.split("\n")[0] ?? "").trim() === NEW_TASK_SUBJECT
388112
- );
388113
- const squashGrilling = squashCycle.find(
388114
- (c7) => (c7.message.split("\n")[0] ?? "").trim() === GRILLING_SUBJECT
388115
- );
388116
- const squashStart = squashNewTask ?? squashGrilling;
388114
+ const squashCycle = squashHistory.slice(prevDoneIdx + 1, lastDoneIdxForSquash + 1);
388115
+ let startIdx = -1;
388116
+ for (let i = squashCycle.length - 1; i >= 0; i--) {
388117
+ if (subjectOf(squashCycle[i]) === NEW_TASK_SUBJECT) {
388118
+ startIdx = i;
388119
+ break;
388120
+ }
388121
+ }
388122
+ if (startIdx === -1) {
388123
+ for (let i = squashCycle.length - 1; i >= 0; i--) {
388124
+ if (subjectOf(squashCycle[i]) === GRILLING_SUBJECT) {
388125
+ startIdx = i;
388126
+ while (startIdx > 0 && subjectOf(squashCycle[startIdx - 1]) === GRILLING_SUBJECT) {
388127
+ startIdx--;
388128
+ }
388129
+ break;
388130
+ }
388131
+ }
388132
+ }
388133
+ const squashStart = startIdx === -1 ? void 0 : squashCycle[startIdx];
388117
388134
  if (squashStart !== void 0) {
388118
388135
  const squashStartParent = yield* git.resolveRef(`${squashStart.hash}~1`).pipe(Effect_exports.catchAll(() => Effect_exports.succeed(EMPTY_TREE)));
388119
388136
  const candidateDiff = yield* git.diffRef(squashStartParent).pipe(Effect_exports.catchAll(() => Effect_exports.succeed("")));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmelab/gtd",
3
- "version": "1.5.3",
3
+ "version": "1.5.5",
4
4
  "private": false,
5
5
  "description": "Git-aware CLI that emits the next prompt for an autonomous coding agent based on the current repository state",
6
6
  "bin": {