feat: script Forgejo writes; fj-worker becomes recovery-only #9

Merged
jerome merged 10 commits from feat/fj-write-script into main 2026-06-26 12:27:58 +03:00
Owner

Goal: Make routine Forgejo writes fast, visible, and never-silent by scripting them (a new fj_write.py mirroring fj_read.py), instead of routing every write through the fj-worker Sonnet subagent. The only model left in the loop -- the recovery fallback -- runs on the cheap Haiku tier.

Value: med
Effort: half-day


Why

The #8 refactor routed ALL fj writes through an isolated Sonnet subagent. That makes writes:

  1. Slow -- cold-start + ~300-line reference load + inference per op.
  2. Opaque -- isolated context, so no live progress, just a spinner.
  3. Sometimes silent on success -- the worker is told to be terse and occasionally returns nothing.

Reads do not have these problems because #8 scripted them: fj_read.py runs in the main context, deterministic, prints verbatim output immediately. Writes never got the same treatment. This task gives writes the same scripted path, and demotes fj-worker to an error-recovery-only fallback.

Measured: fj_read.py is ~0.33s and the fj binary ~0.13s. The deterministic calls were never the bottleneck -- any model in the loop is. So the design is: deterministic script (or fj binary) for every read/write, and the one remaining model (recovery) on the cheap tier.


Steps

  • Add fj_write.py to plugins/forgejo-cli/skills/forgejo-cli/scripts/, mirroring fj_read.py conventions: stdlib-only, host/repo inferred from cwd origin, token from keys.json (XDG + macOS paths), exit codes 0/2/3/4 plus one new code for "mutation failed -> escalate to worker".
  • Implement the hybrid mutation model: shell out to fj for ops it does well (comment, label, title, body, merge, close, create) with correctly-constructed argv; use REST POST (stored token) for the review-write gap fj cannot do (approve / request-changes); verify results via a REST read (reuse fj_read's gather helpers).
  • Implement the command surface (see Notes) with argparse subcommands.
  • Always print the resulting state on success -- never exit silent (re-read via REST and print what changed).
  • Add --dry-run that prints the exact fj argv / REST call without executing (safety valve + the manual verification hook).
  • Build the catch-up dance into pr-merge: git fetch && git merge <base> && git push before fj pr merge (the #1 cause of Forgejo's generic 405); on a remaining 405, print the verbatim error + known causes + "escalate to fj-worker".
  • Rewrite the write half of plugins/forgejo-cli/skills/forgejo-cli/SKILL.md into three named paths in priority order: Reads -> fj_read.py (unchanged); Writes -> fj_write.py (new section: command surface, --body-file convention, note that it always prints state so the caller acts on stdout, no worker round-trip); Recovery -> dispatch fj-worker ONLY on non-zero exit, handing it the verbatim error.
  • Rewrite only the operating-contract intro of plugins/forgejo-cli/agents/fj-worker.md to the fallback framing; keep the full reference (it stays the canonical source + recovery knowledge). Add a one-line pointer from fj_write.py back to fj-worker.md.
  • Rewire the task suites (task + taskpy): the Forgejo branch of every PR/issue read/write stops spelling out inline fj ... and defers to the forgejo-cli skill (which owns both scripts). The GitHub gh ... branch stays inline. Files: task/skills/task-new, task-orchestrate (SKILL + test-fix-loop.md), task-implement (flow.md + worktree-and-branches.md), task-review, and the taskpy mirrors of each.
  • Follow-up (R1): pin the fj-worker recovery agent to Haiku (was Sonnet). Routine reads/writes are deterministic sub-second script calls, so the only model in the loop is the recovery fallback -- it does not need a frontier tier. (fj-worker.md frontmatter + description; SKILL.md recovery note.)
  • Follow-up (R2): state "commit + push before ticking a PR-body checkbox" as a hard invariant everywhere a box is flipped -- task/taskpy implement Step 5/5a, orchestrate Step 3 (reordered so push precedes the tick), each test-fix-loop.md, plus matching Common Mistakes rows. The remote body must only ever show - [x] for work already on the branch.
  • Follow-up (R3): finish the rewiring the original file list missed -- the implement skills (task-implement + taskpy-implement SKILL.md) still ticked boxes via inline fj pr edit body; route their inline fj PR/issue writes through fj_write.py and their reads through fj_read.py (GitHub gh branches stay inline).

Notes

Command surface:

fj_write.py [--repo owner/repo] [--host h] [--dry-run] <command> ...
  pr-comment  N (--body-file PATH | --body TEXT)
  pr-label    N [--add L ...] [--remove L ...]
  pr-title    N "<new title>"            # also resyncs the WIP draft flag
  pr-body     N --body-file PATH
  pr-merge    N [--squash(default)|--merge|--rebase] [--delete] [--no-catchup]
  pr-close    N [--message TEXT]
  pr-create   --base main --head BR --title T (--body-file PATH | --body TEXT)
  pr-review   N (--approve | --request-changes | --comment) [--body-file PATH]
  issue-comment/-label/-title/-body/-close/-create ...   # same shapes

Net effect on the three complaints: routine writes lose the subagent entirely -> fast; run in the main context -> live progress; always print resulting state -> no more silent success. The subagent appears only when something actually went wrong -- exactly when an isolated, careful diagnosis is wanted, and now on the cheap Haiku tier.

Why hybrid (shell-out + REST) rather than pure-REST or pure-shell: fj_read.py already proved REST-direct works (it had to, since fj cannot show reviews). For writes, fj is battle-tested for the mutations it supports, so shell out to it and let the script encapsulate the CLI footguns (positional title, --title ignored, additive label flags, draft-flag resync). REST is reserved for the one gap fj has no subcommand for: formal reviews (approve / request-changes). Result verification uses REST reads because fj pr status is broken and CLI output is not machine-stable.

Mid-flight spec changes (folded in): after the first 8 Steps landed, the user added R1-R3 above. R1+R2 are direct requests (cheap recovery model; the commit+push-before-tick rule). R3 is a consistency gap found while applying R2 -- the implement SKILLs were outside the original rewiring file list but still ran inline fj writes. See the dated PR comment for the why.

Out of scope (conscious cuts):

  • No gh_write.py -- GitHub is not the problem; gh is well-behaved.
  • No test framework -- matches the repo's posture (stdlib scripts, no CI tests); --dry-run is the verification hook.
  • No new fj capabilities beyond the listed surface.
**Goal:** Make routine Forgejo writes fast, visible, and never-silent by scripting them (a new `fj_write.py` mirroring `fj_read.py`), instead of routing every write through the `fj-worker` Sonnet subagent. The only model left in the loop -- the recovery fallback -- runs on the cheap Haiku tier. **Value:** med **Effort:** half-day --- ## Why The #8 refactor routed ALL `fj` writes through an isolated Sonnet subagent. That makes writes: 1. Slow -- cold-start + ~300-line reference load + inference per op. 2. Opaque -- isolated context, so no live progress, just a spinner. 3. Sometimes silent on success -- the worker is told to be terse and occasionally returns nothing. Reads do not have these problems because #8 scripted them: `fj_read.py` runs in the main context, deterministic, prints verbatim output immediately. Writes never got the same treatment. This task gives writes the same scripted path, and demotes `fj-worker` to an error-recovery-only fallback. Measured: `fj_read.py` is ~0.33s and the `fj` binary ~0.13s. The deterministic calls were never the bottleneck -- any model in the loop is. So the design is: deterministic script (or `fj` binary) for every read/write, and the one remaining model (recovery) on the cheap tier. --- ## Steps - [x] Add `fj_write.py` to `plugins/forgejo-cli/skills/forgejo-cli/scripts/`, mirroring `fj_read.py` conventions: stdlib-only, host/repo inferred from cwd `origin`, token from `keys.json` (XDG + macOS paths), exit codes `0/2/3/4` plus one new code for "mutation failed -> escalate to worker". - [x] Implement the hybrid mutation model: shell out to `fj` for ops it does well (comment, label, title, body, merge, close, create) with correctly-constructed argv; use REST `POST` (stored token) for the review-write gap `fj` cannot do (approve / request-changes); verify results via a REST read (reuse `fj_read`'s gather helpers). - [x] Implement the command surface (see Notes) with argparse subcommands. - [x] Always print the resulting state on success -- never exit silent (re-read via REST and print what changed). - [x] Add `--dry-run` that prints the exact `fj` argv / REST call without executing (safety valve + the manual verification hook). - [x] Build the catch-up dance into `pr-merge`: `git fetch && git merge <base> && git push` before `fj pr merge` (the #1 cause of Forgejo's generic 405); on a remaining 405, print the verbatim error + known causes + "escalate to fj-worker". - [x] Rewrite the write half of `plugins/forgejo-cli/skills/forgejo-cli/SKILL.md` into three named paths in priority order: Reads -> `fj_read.py` (unchanged); Writes -> `fj_write.py` (new section: command surface, `--body-file` convention, note that it always prints state so the caller acts on stdout, no worker round-trip); Recovery -> dispatch `fj-worker` ONLY on non-zero exit, handing it the verbatim error. - [x] Rewrite only the operating-contract intro of `plugins/forgejo-cli/agents/fj-worker.md` to the fallback framing; keep the full reference (it stays the canonical source + recovery knowledge). Add a one-line pointer from `fj_write.py` back to `fj-worker.md`. - [x] Rewire the task suites (`task` + `taskpy`): the Forgejo branch of every PR/issue read/write stops spelling out inline `fj ...` and defers to the forgejo-cli skill (which owns both scripts). The GitHub `gh ...` branch stays inline. Files: `task/skills/task-new`, `task-orchestrate` (SKILL + `test-fix-loop.md`), `task-implement` (`flow.md` + `worktree-and-branches.md`), `task-review`, and the `taskpy` mirrors of each. - [x] Follow-up (R1): pin the `fj-worker` recovery agent to Haiku (was Sonnet). Routine reads/writes are deterministic sub-second script calls, so the only model in the loop is the recovery fallback -- it does not need a frontier tier. (`fj-worker.md` frontmatter + description; SKILL.md recovery note.) - [x] Follow-up (R2): state "commit + push before ticking a PR-body checkbox" as a hard invariant everywhere a box is flipped -- `task`/`taskpy` implement Step 5/5a, orchestrate Step 3 (reordered so push precedes the tick), each `test-fix-loop.md`, plus matching Common Mistakes rows. The remote body must only ever show `- [x]` for work already on the branch. - [x] Follow-up (R3): finish the rewiring the original file list missed -- the implement skills (`task-implement` + `taskpy-implement` SKILL.md) still ticked boxes via inline `fj pr edit body`; route their inline `fj` PR/issue writes through `fj_write.py` and their reads through `fj_read.py` (GitHub `gh` branches stay inline). --- ## Notes **Command surface:** ``` fj_write.py [--repo owner/repo] [--host h] [--dry-run] <command> ... pr-comment N (--body-file PATH | --body TEXT) pr-label N [--add L ...] [--remove L ...] pr-title N "<new title>" # also resyncs the WIP draft flag pr-body N --body-file PATH pr-merge N [--squash(default)|--merge|--rebase] [--delete] [--no-catchup] pr-close N [--message TEXT] pr-create --base main --head BR --title T (--body-file PATH | --body TEXT) pr-review N (--approve | --request-changes | --comment) [--body-file PATH] issue-comment/-label/-title/-body/-close/-create ... # same shapes ``` **Net effect on the three complaints:** routine writes lose the subagent entirely -> fast; run in the main context -> live progress; always print resulting state -> no more silent success. The subagent appears only when something actually went wrong -- exactly when an isolated, careful diagnosis is wanted, and now on the cheap Haiku tier. **Why hybrid (shell-out + REST) rather than pure-REST or pure-shell:** `fj_read.py` already proved REST-direct works (it had to, since `fj` cannot show reviews). For writes, `fj` is battle-tested for the mutations it supports, so shell out to it and let the script encapsulate the CLI footguns (positional title, `--title` ignored, additive label flags, draft-flag resync). REST is reserved for the one gap `fj` has no subcommand for: formal reviews (approve / request-changes). Result verification uses REST reads because `fj pr status` is broken and CLI output is not machine-stable. **Mid-flight spec changes (folded in):** after the first 8 Steps landed, the user added R1-R3 above. R1+R2 are direct requests (cheap recovery model; the commit+push-before-tick rule). R3 is a consistency gap found while applying R2 -- the implement SKILLs were outside the original rewiring file list but still ran inline `fj` writes. See the dated PR comment for the why. **Out of scope (conscious cuts):** - No `gh_write.py` -- GitHub is not the problem; `gh` is well-behaved. - No test framework -- matches the repo's posture (stdlib scripts, no CI tests); `--dry-run` is the verification hook. - No new `fj` capabilities beyond the listed surface.
feat: scaffold fj_write.py write-scripting
All checks were successful
gitleaks / gitleaks (pull_request) Successful in 4s
4688b80706
Author
Owner

Resolver started. Worktree /Users/jeromechiche/Documents/skills/.worktrees/fj-write-script (branch feat/fj-write-script). Note: repo has no task:active label, so the active-pass marker is skipped this pass.

Resolver started. Worktree /Users/jeromechiche/Documents/skills/.worktrees/fj-write-script (branch feat/fj-write-script). Note: repo has no task:active label, so the active-pass marker is skipped this pass.
Mirror fj_read.py: stdlib-only, host/repo inferred from cwd origin,
token from keys.json, fail()/exit-code scheme. Hybrid mutation model --
shell out to fj for comment/label/title/body/merge/close/create with
correctly-built argv (positional title, additive label flags, WIP draft
resync); REST POST for the review-write gap fj cannot do (approve /
request-changes). Always re-reads via REST and prints the resulting
state so the caller never gets a silent success. --dry-run prints the
exact argv / REST call without running. pr-merge does the git catch-up
(fetch + merge base + push) before merging to kill the most common 405.
Exit codes 0/2/3/4 plus 5 for mutation-failed -> escalate to fj-worker.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrite the skill into three named paths in priority order: Reads ->
fj_read.py, Writes -> fj_write.py (new section with the command surface,
--body-file convention, and the always-prints-state contract so the
caller acts on stdout), Recovery -> dispatch fj-worker only on a non-zero
script exit, handing it the verbatim error. Update the frontmatter
description to match the script-first model.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrite only the operating-contract intro: the worker is dispatched on a
non-zero script exit or for the long tail with no script surface, and the
task usually carries the verbatim error a script printed. Keep the full
fj reference below intact -- it stays the canonical source + recovery
knowledge. The fj_write.py -> fj-worker.md back-pointer lives in the
script's docstring and its 405 escalation message.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs: defer task suite Forgejo branches to the forgejo-cli skill
All checks were successful
gitleaks / gitleaks (pull_request) Successful in 4s
11af72006a
Across both task suites (task + taskpy), the Forgejo branch of every
PR/issue read/write stops spelling out inline fj commands and defers to
the forgejo-cli skill, which owns fj_read.py (reads) and fj_write.py
(writes). The GitHub gh branches stay inline -- gh is well-behaved.
Touches task-new, task-orchestrate (SKILL + test-fix-loop), task-implement
(flow + worktree-and-branches), task-review, and the taskpy mirrors of
each. The fj whoami / fj auth add-key forge-detection and auth checks stay
literal -- those are not PR/issue ops.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Owner

2026-06-26 -- resolver pass on feat/fj-write-script at 11af720.

  • Steps done: all 8. Landed as 4 logical commits:
    • feat: script Forgejo writes with fj_write.py (stdlib, hybrid shell-out + REST, full command surface, verify-and-print, --dry-run, catch-up-before-merge, exit codes 0/2/3/4 + 5 for mutation-failed -> escalate). chmod +x to match fj_read.py.
    • docs: rewrite the write half of forgejo-cli/SKILL.md into three named paths (Reads -> fj_read.py, Writes -> fj_write.py, Recovery -> fj-worker only on non-zero exit).
    • docs: reframe fj-worker.md's operating-contract intro to the recovery-path framing (full reference kept). The fj_write.py -> fj-worker.md back-pointer lives in the script docstring + its 405 escalation message.
    • docs: defer the task + taskpy suites' Forgejo PR/issue read/write branches to the forgejo-cli skill; gh branches stay inline.
  • Deferred to /task-orchestrate: none of the spec's Steps are install/test/verify (no test framework in this repo by design). Verification hook is fj_write.py --dry-run; the orchestrator can exercise it.
  • Notes / surprises:
    • fj_read.py (and therefore fj_write.py's REST verify/POST paths) fails against forge.chichefam.com from system python3 with SSL: CERTIFICATE_VERIFY_FAILED (no CA bundle on the default interpreter); the fj binary itself works. fj_write.py mirrors fj_read.py exactly, so it inherits the same REST behavior rather than diverging -- worth confirming the host cert / python CA setup during verification, since the REST POST (pr-review) and the verify-after-write re-read depend on it. The shell-out mutations (comment/label/title/body/merge/close/create) are unaffected.
    • The repo has no task:active label, so this pass skipped the active-pass label marker (surfaced in the started comment). One-time web-UI setup if that marker is wanted.
    • task-implement/SKILL.md (and taskpy-implement/SKILL.md) were intentionally left out of the rewiring per the spec's file list -- only flow.md + worktree-and-branches.md are in scope there.
2026-06-26 -- resolver pass on feat/fj-write-script at 11af720. - Steps done: all 8. Landed as 4 logical commits: - feat: script Forgejo writes with fj_write.py (stdlib, hybrid shell-out + REST, full command surface, verify-and-print, --dry-run, catch-up-before-merge, exit codes 0/2/3/4 + 5 for mutation-failed -> escalate). chmod +x to match fj_read.py. - docs: rewrite the write half of forgejo-cli/SKILL.md into three named paths (Reads -> fj_read.py, Writes -> fj_write.py, Recovery -> fj-worker only on non-zero exit). - docs: reframe fj-worker.md's operating-contract intro to the recovery-path framing (full reference kept). The fj_write.py -> fj-worker.md back-pointer lives in the script docstring + its 405 escalation message. - docs: defer the task + taskpy suites' Forgejo PR/issue read/write branches to the forgejo-cli skill; gh branches stay inline. - Deferred to /task-orchestrate: none of the spec's Steps are install/test/verify (no test framework in this repo by design). Verification hook is fj_write.py --dry-run; the orchestrator can exercise it. - Notes / surprises: - fj_read.py (and therefore fj_write.py's REST verify/POST paths) fails against forge.chichefam.com from system python3 with SSL: CERTIFICATE_VERIFY_FAILED (no CA bundle on the default interpreter); the fj binary itself works. fj_write.py mirrors fj_read.py exactly, so it inherits the same REST behavior rather than diverging -- worth confirming the host cert / python CA setup during verification, since the REST POST (pr-review) and the verify-after-write re-read depend on it. The shell-out mutations (comment/label/title/body/merge/close/create) are unaffected. - The repo has no task:active label, so this pass skipped the active-pass label marker (surfaced in the started comment). One-time web-UI setup if that marker is wanted. - task-implement/SKILL.md (and taskpy-implement/SKILL.md) were intentionally left out of the rewiring per the spec's file list -- only flow.md + worktree-and-branches.md are in scope there.
perf: run fj-worker recovery on Haiku instead of Sonnet
All checks were successful
gitleaks / gitleaks (pull_request) Successful in 4s
827d7c5ead
Routine fj reads/writes are deterministic sub-second script calls (no model). The fj-worker subagent is the recovery-only fallback, so it does not need a frontier model -- pin it to the cheap Haiku tier.
Encode a hard invariant in the orchestrate suites (task + taskpy): never
flip a box to - [x] until the work it represents is committed AND pushed
to the branch -- the remote PR body must only ever show - [x] for work
actually on the remote branch. Order is always edit -> (format) ->
commit -> push -> then tick; a pure verification tick (a passing
test/smoke run with no code edit) is the only kind that may precede a
push. Reorder Step 3 "Wrap up" so push precedes the checkbox tick, fold
the invariant into the test-fix-loop step-completion bookkeeping, and add
a Common Mistakes row. The implement-suite half of this invariant lands in
the same change-set as the write-rerouting commit, since both touch the
implement SKILL files.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs: route implement-skill Forgejo writes through fj_write.py
All checks were successful
gitleaks / gitleaks (pull_request) Successful in 4s
86a50307ad
Finish the suite-wide rewiring the earlier pass left to the implement
SKILL files: every inline Forgejo PR/issue WRITE (label, comment, body,
create) now defers to the forgejo-cli skill's fj_write.py, and the
remaining inline READS point at fj_read.py, matching the pattern the other
suite files already use. GitHub gh branches stay inline. Also carries the
implement-side commit+push-before-tick invariant (Step 5 + 5a lead, Quick
Reference row, Common Mistakes row), inseparable from the 5a write-reroute
since both edit the same checkbox-tick block.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
docs: use ASCII <= in task-implement picker note
All checks were successful
gitleaks / gitleaks (pull_request) Successful in 4s
ae1d866c59
Author
Owner

2026-06-26 -- spec amended mid-flight (R1-R3), all folded into the body.

R1 (user request). The deterministic paths are sub-second (fj_read.py ~0.33s, fj binary ~0.13s) -- the only slow path is ever a model. So fj-worker is pinned to Haiku (was Sonnet): it is the recovery-only fallback and does not need a frontier tier. Routine reads/writes stay deterministic script calls with no model in the loop.

R2 (user request). "Commit + push before ticking a PR-body checkbox" is now a hard invariant in both task suites (implement Step 5/5a, orchestrate Step 3 reordered so push precedes the tick, each test-fix-loop.md, plus Common Mistakes rows). The remote body must only ever show - [x] for work already on the branch.

R3 (consistency gap found while applying R2). The implement SKILLs (task-implement + taskpy-implement) were outside the original rewiring file list but still ticked boxes via inline fj pr edit body. Their inline fj writes now route through fj_write.py, reads through fj_read.py; gh branches stay inline.

Verification. fj_write.py compiles; the full --dry-run command surface produces correct argv; the exit-code contract (0 ok / 2 usage) holds; and a live fj_write.py pr-body round-trip (this PR's body edit) exercised the shell-out mutation + REST verify end-to-end on this host. This comment was itself posted via fj_write.py pr-comment.

2026-06-26 -- spec amended mid-flight (R1-R3), all folded into the body. **R1 (user request).** The deterministic paths are sub-second (`fj_read.py` ~0.33s, `fj` binary ~0.13s) -- the only slow path is ever a model. So `fj-worker` is pinned to **Haiku** (was Sonnet): it is the recovery-only fallback and does not need a frontier tier. Routine reads/writes stay deterministic script calls with no model in the loop. **R2 (user request).** "Commit + push before ticking a PR-body checkbox" is now a hard invariant in both task suites (implement Step 5/5a, orchestrate Step 3 reordered so push precedes the tick, each `test-fix-loop.md`, plus Common Mistakes rows). The remote body must only ever show `- [x]` for work already on the branch. **R3 (consistency gap found while applying R2).** The implement SKILLs (`task-implement` + `taskpy-implement`) were outside the original rewiring file list but still ticked boxes via inline `fj pr edit body`. Their inline `fj` writes now route through `fj_write.py`, reads through `fj_read.py`; `gh` branches stay inline. **Verification.** `fj_write.py` compiles; the full `--dry-run` command surface produces correct argv; the exit-code contract (0 ok / 2 usage) holds; and a live `fj_write.py pr-body` round-trip (this PR's body edit) exercised the shell-out mutation + REST verify end-to-end on this host. This comment was itself posted via `fj_write.py pr-comment`.
chore: gitignore __pycache__ from fj_write.py's sibling import
All checks were successful
gitleaks / gitleaks (pull_request) Successful in 4s
5547bb3076
jerome changed title from WIP: feat: script Forgejo writes; fj-worker becomes recovery-only to feat: script Forgejo writes; fj-worker becomes recovery-only 2026-06-26 12:13:31 +03:00
Author
Owner

/task-review verdict: ok

LOC: +976/-419

Scripts the Forgejo write path (fj_write.py) and demotes fj-worker to a Haiku-tier recovery-only fallback, exactly per the Goal. All 11 Steps (1-8 plus the folded-in R1/R2/R3) land in the diff and nothing lands outside them: the new stdlib-only script (compiles clean, full --dry-run surface correct, exit-code contract 0/2/3/4/5 holds), the three-named-path SKILL.md rewrite, the fj-worker.md recovery reframe + model: haiku pin, the task/taskpy rewiring (no inline fj PR/issue write or read verbs remain; gh branches stay inline), and the commit-push-before-tick invariant across both suites. The .gitignore __pycache__/ add and the non-ASCII <= fix are documented intentional hygiene. Branch is current with origin/main. No configured lint/typecheck/test gate exists in this repo by design; the verification evidence is py_compile + the dry-run command surface + two live fj_write.py round-trips.

No findings.

## /task-review verdict: `ok` **LOC:** +976/-419 > Scripts the Forgejo write path (`fj_write.py`) and demotes `fj-worker` to a Haiku-tier recovery-only fallback, exactly per the Goal. All 11 Steps (1-8 plus the folded-in R1/R2/R3) land in the diff and nothing lands outside them: the new stdlib-only script (compiles clean, full `--dry-run` surface correct, exit-code contract 0/2/3/4/5 holds), the three-named-path SKILL.md rewrite, the `fj-worker.md` recovery reframe + `model: haiku` pin, the task/taskpy rewiring (no inline `fj` PR/issue write or read verbs remain; `gh` branches stay inline), and the commit-push-before-tick invariant across both suites. The `.gitignore` `__pycache__/` add and the non-ASCII `<=` fix are documented intentional hygiene. Branch is current with `origin/main`. No configured lint/typecheck/test gate exists in this repo by design; the verification evidence is py_compile + the dry-run command surface + two live `fj_write.py` round-trips. _No findings._
jerome merged commit 22a790c665 into main 2026-06-26 12:27:58 +03:00
Sign in to join this conversation.
No reviewers
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
public/chiche-plugins!9
No description provided.