Skip to content

The framework never commits on an agent's or the user's behalf (#1638) - #1724

Merged
suleimansh merged 1 commit into
mainfrom
1638-remove-the-safety-commit
Aug 27, 2026
Merged

The framework never commits on an agent's or the user's behalf (#1638)#1724
suleimansh merged 1 commit into
mainfrom
1638-remove-the-safety-commit

Conversation

@suleimansh

Copy link
Copy Markdown
Contributor

Closes #1638. Rom's call on the issue: remove the [The Framework] uncommitted changes feature altogether. Replaces #1722 (closed).

What goes

The sweep was made in four places; all four are gone, and nothing replaces them with another commit:

  1. Activation (install.ts) — no longer commits the user's dirty tree first. The install commit adds only .the-framework/ (git add .the-framework, never add -A); whatever the user has uncommitted stays theirs.
  2. Teardown (worktrees.tsstore/worktree.ts) — commitPendingWork (with its Trivial run's work is stranded: agent skipped committing, handoff says "session committed nothing", safety commit lands only after the publish decision (#860 redux) #1376 retry) is deleted. A checkout holding uncommitted work is reported dirty by worktreeClean and kept: session <id> has uncommitted work; its worktree was kept. A tree git cannot read is kept the same way.
  3. Auto-handoff at session end (cli.ts) — no commit before the push; the commit-failed skip reason goes with it (events.ts, terminal.ts). What is published is what the agent committed.
  4. Push / Open PR (dashboard-rpc/control.ts) — commitAgentWork is deleted; both actions push the branch as the agent left it, still under the agent lock (the push race with teardown is unchanged).

What replaces it

The agent commits its own work. Detached runs were already told so; now the system prompt's branch step says it for every run: do all the work in that branch, and commit it there as you go: The Framework publishes only what you committed, and never commits for you.

The trade, stated plainly: an agent that ends without committing leaves its work uncommitted in its worktree — never destroyed, named on its page (pendingFiles is unchanged), but not published and on disk until a person commits or deletes it. The framework used to rescue that silently; that rescue is what put 7,632 cache files on main.

Verified

Full suite green (1643 node + 864 dashboard). Broken on purpose in the compiled output: "teardown never keeps a dirty checkout" and "install adds -A" turn 6 tests red across worktrees, merged-worktrees, agent-addressing and install; restored, 58/58.

Specs (please read through)

  • install.SPEC.md — activation is one commit holding only The Framework's files; the user's uncommitted work is left as it is.
  • store/worktree.SPEC.md — "Teardown commits before it deletes" → "A checkout is read, never committed", with the rationale (the cache incident).
  • worktrees.SPEC.md — the reclaim rule: kept while dirty, pushed when clean, removed once the remote has it.
  • cli.SPEC.md, dashboard-rpc/control.SPEC.md, dashboard/agent-handoff.SPEC.md, agent-locks.SPEC.md, merged-worktrees.SPEC.md — the sentences that said "commits what the agent left" now say "publishes what the agent committed".
  • prompts/system_prompt.SPEC.md — the branch step includes committing.
  • FEATURES-SPEC.md — "Commit what the agent left uncommitted" → "Only what the agent committed is published — nothing is ever committed on the agent's or your behalf".
  • Test specs updated to match (install, store/worktree, worktrees, merged-worktrees, agent-handoff, dashboard-rpc/agent-addressing).

🤖 curated · Fable 5, effort high

@suleimansh

Copy link
Copy Markdown
Contributor Author

Why the prompt line changed (for the read-through)

prompts/system_prompt.md, branch step:

-2. Create a new branch `tf-<SESSION_NAME>` and `$ git checkout` it — do all the work in that branch
+2. Create a new branch `tf-<SESSION_NAME>` and `$ git checkout` it — do all the work in that branch, and commit it there as you go: The Framework publishes only what you committed, and never commits for you

prompts/system_prompt.SPEC.md, TL;DR:

-- **Name the session, then branch** - before the first change the agent invents a session name, creates and checks out `tf-<session name>`, and reports the name back.
+- **Name the session, then branch** - before the first change the agent invents a session name, creates and checks out `tf-<session name>`, commits its work there as it goes, and reports the name back.

Why: until this PR the framework committed whatever the agent left uncommitted — at teardown, at handoff, on Push/Open PR — so the prompt never had to ask the agent to commit. That sweep is what put 7,632 cache files on main (#1632), and #1638 removes it. With nothing committing on the agent's behalf, the agent has to commit its own work or it never gets published; detached runs were already told this, now every run is. The spec line follows the prompt.

@suleimansh

Copy link
Copy Markdown
Contributor Author

@brillout merging — happy to adjust anything.

@suleimansh
suleimansh merged commit e36525a into main Aug 27, 2026
2 checks passed
@suleimansh
suleimansh deleted the 1638-remove-the-safety-commit branch August 27, 2026 16:24
suleimansh added a commit that referenced this pull request Aug 27, 2026
- The legacy the-framework/ prefix goes: agentBranchFor guesses tf-, the
  scratch sweep and isAgentBranch know one spelling, and the package's
  public API carries no compat layer (repo MEMORY.md: zero migration code).
- The framework's own build/dev/typecheck/test scripts build the package
  first, so a fresh clone works without a root build; the package sets
  publishConfig.access public.
- reclaimWorktree reads the tree once; the refusal union says which members
  carry a branch; git branch -D/-m/<new> run on the write budget.
- cli-exec keeps only what gh uses: a flat budget, no maxBuffer, no
  isCliTimeout; the daemon test times out with the package's error.
- The branch-links pass is one line at its call site; the barrel exports
  what has an importer; the framework proves it wires birthBranch and
  mayPush into the rule.
- SPECs: root and packages/ name the new package; index.SPEC.md; worktree,
  cli-exec and agent-handoff wording caught up with #1724 and this lift.
suleimansh added a commit that referenced this pull request Aug 27, 2026
* Branch management lives in its own package (#1725)

The git side of an agent's checkout — the naming conventions and the
.the-framework/branches/ layout, the git runner with its per-subcommand
time budgets, creating/attaching/listing/renaming/removing a worktree,
sharing the parent's dependency trees into it, the branch-name links, and
the retention rule under which a checkout is reclaimed — moves out of the
framework into packages/branch-management, published as
@superskill/branch-management. Step 1 of #1725: a lift with no behaviour
change; the framework imports the package as a workspace dependency.

What the framework keeps is the agent's side: its record (may the branch be
pushed, what did a cloud hand-off already push), the teardown and the sweep,
the dashboard's list and buttons, and how each refusal is worded. The
package's reclaimWorktree takes those as options and returns a reason code.

Also folded in: pushAgentBranch/gitReason (agent-handoff) were the same
push the rule needs, so there is one pushBranch now, in the package.

* Review fixes for the branch-management lift (#1725)

- The legacy the-framework/ prefix goes: agentBranchFor guesses tf-, the
  scratch sweep and isAgentBranch know one spelling, and the package's
  public API carries no compat layer (repo MEMORY.md: zero migration code).
- The framework's own build/dev/typecheck/test scripts build the package
  first, so a fresh clone works without a root build; the package sets
  publishConfig.access public.
- reclaimWorktree reads the tree once; the refusal union says which members
  carry a branch; git branch -D/-m/<new> run on the write budget.
- cli-exec keeps only what gh uses: a flat budget, no maxBuffer, no
  isCliTimeout; the daemon test times out with the package's error.
- The branch-links pass is one line at its call site; the barrel exports
  what has an importer; the framework proves it wires birthBranch and
  mayPush into the rule.
- SPECs: root and packages/ name the new package; index.SPEC.md; worktree,
  cli-exec and agent-handoff wording caught up with #1724 and this lift.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The catch-all safety commit will commit anything: 7,632 cache files went to main unnoticed

1 participant