feat: CEO Phase 2 — propose work as issues for the board to greenlight #247
No reviewers
Labels
No labels
Agent
Compat/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No assignees
2 participants
Notifications
Total time spent: 3 minutes 46 seconds
Due date
igor
3 minutes 46 seconds
No due date set.
Dependencies
No dependencies set
Reference
joshtronic/igor!247
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/ceo-agency"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What this adds
CEO Phase 2 — propose work as issues you greenlight (your two calls: proposals-not-auto-label, folded into the weekly digest).
The weekly digest's same model call may now append up to two
===ISSUE===proposal blocks — the actionable form of the recommendations it already makes. The harness files them as UNLABELED issues assigned to you, each stamped with a marker. They become real work only when you greenlight them (add theAgentlabel + unassign). So:Validated live against porksicle
One real model call produced 2 priority-aligned proposals, parsed cleanly:
feat(seo): related-games links on every game page— priority #1 (SEO)feat(quality): automated per-game smoke test— priority #2 (quality)…each with a Priority / Why-now / Scope / acceptance body. These are the actionable form of what the Phase-1 digest recommended.
Tests ship with it this time
bin/test-ceo.shgains proposal-parse coverage (0/1/2 blocks, malformed-skipped, digest-body-excludes-issues).check-syncruns them; all green;bash -nclean.Not in this phase (deliberate, per "start tight")
No auto-Agent-label, no daily steering, no mandate redlines, no direct doc-edits. Those graduate as separate human-gated steps.
🤖 Review —
COMMENT(automated)CI for
cc38d8d3: successSummary: Adds "CEO Phase 2" — the weekly digest model call may append up to two
===ISSUE===proposal blocks, which the harness parses (_ceo_parse_issues) and files as unlabeled issues assigned toFORGEJO_REVIEWER, throttled to one batch at a time. Parsing is well-tested; the change is focused, in scope (~110 lines), touches no CI config, and the checklist matches the diff. My reservations are about the untested integration path and one variable I can't see, not a proven defect — hence COMMENT, not APPROVE.Honest-checklist / scope check (passes):
bin/test-ceo.sh(0/1/2 blocks, malformed-skipped, digest-body-excludes-issues) is genuinely present and the expectations trace correctly against the parser.CLAUDE.mdandceo-digest-directive.mdaccurately describe the implemented throttle (ceo_open_proposals_count == 0), theFORGEJO_REVIEWERassignment, and the marker. No doc/code drift._ceo_trim_blanksextraction is a justified refactor (shared by digest + proposal bodies), not a drive-by..forgejo//.github/workflows/changes. Payloads are built withjq -n --arg, so no JSON/shell injection. CI issuccess.Things I want the human to confirm (why I'm not approving):
$parsedis referenced but not defined in the diff (bin/tick.sh~line 2080:proposals=$(jq -c '.issues // []' <<<"$parsed")). The surrounding$subject/$body/$htmlare clearly already in scope, so this is probably the right name, but ifdo_ceo_tickactually names that variable something else, the failure is silent:jqon empty input →nprop=0→ proposals never filed, digest still sends. Please verify the variable name matches whereceo_parse_response's output is captured. (The "validated live against porksicle, filed 2 proposals" claim implies it's correct, but I can't see it.)do_ceo_tickhas no automated coverage. The new tests exerciseceo_parse_response/_ceo_parse_issuesonly; the throttle gate, the file loop, andceo_file_proposal/ceo_open_proposals_countrely entirely on the manual live run. That's understandable (they're network calls), but it means a regression in that block won't be caught bycheck-sync.Minor observations (non-blocking):
_ceo_parse_issues+ the tick loop will file every===ISSUE===block the model emits. A misbehaving/poisoned model producing 5 blocks files 5 unlabeled issues (the throttle then stops the next batch). The human gate bounds the blast radius, but consider clamping to 2 harness-side rather than trusting model restraint.ceo_file_proposalsuccess depends on_fjreturning non-zero on HTTP 4xx/5xx._fj POST ... >/dev/null 2>&1is used to incrementfiled; if_fjswallows error status codes, a failed POST would be logged as a successful file. Worth a glance at_fj's error semantics (not in this diff).RS = "===ISSUE==="in_ceo_parse_issuesworks on gawk/mawk but is a non-POSIX extension; CI green confirms it works in your environment, just noting it's host-awk-dependent if deployment hosts differ.No correctness or security defect I can point to concretely — the parser logic is sound and matches its tests. Holding at COMMENT so a human can confirm the
$parsedbinding and eyeball the untested filing path before merge.Independent review by the harness on
claude-opus-4-8. The human reviewer is requested once Igor has reviewed; a human still merges.🤖 Review —
COMMENT(automated)CI for
a6136bca: successAdds CEO "Phase 2": the weekly-digest model call may append up to two
===ISSUE===proposal blocks, which the harness files as unlabeled issues assigned to the human, gated by a throttle. Clean, focused, well-tested at the unit level, security gate intact, no CI-config changes. My only reservation is that the behavior-changing integration intick.shisn't covered by the shown automated tests and one variable can't be confirmed from the diff — hence COMMENT rather than APPROVE.What's good
_ceo_trim_blanksextraction that's now shared by both parse paths.FORGEJO_REVIEWER, so they can't become agent work without a human adding theAgentlabel. No code-execution path from model output.jq --arginto the payload; the backtick in theceo_file_proposalblurb is inside single quotes so it's literal, not command substitution..forgejo//.github/workflows/changes.Reservations a human should weigh
tick.shintegration is unverified by the diff. The new block readsproposals=$(jq -c '.issues // []' <<<"$parsed"), but$parsedis never shown being assigned in the diff — it's assumed to be the parsed-response var that also feeds$subject/$body. If that var is named differently, proposals silently never file (bash -nand the shown tests won't catch this, since none exercisedo_ceo_tick). The "validated live against porksicle" note suggests it works end-to-end, but that's the author's word, not something I can confirm. Please confirm$parsedis correct / the wiring actually fires.ceo_open_proposals_countcounts any open issue carryingCEO_PROPOSAL_MARKER. The marker is never removed on greenlight (the body instructs "addAgentlabel and unassign" only), so a greenlit, in-progress proposal still counts as "open" and blocks the next batch until it's closed. That errs safe (no flooding), but it's not just "un-triaged" ones gating — confirm that's intended._ceo_parse_issuesrelies on multi-charRSregex semantics (awk 'BEGIN { RS = "===ISSUE===" }'). gawk treats this as a regex (works;=is literal), but BWK awk / older mawk use only the firstRSchar, which would split on every=and corrupt parsing. CI green confirms the CI environment is fine, but it's non-portable if operator hosts ship a different awk. A note/guard would harden it.Minor
ceo_open_proposals_countuseslimit=50with no pagination; on a repo with >50 open issues a proposal could be missed and a new batch filed prematurely. Acceptable edge case for now.None of these are clear defects I can pin down, but the untested integration path plus the unverifiable
$parsedreference are exactly the kind of thing I'd want a human to glance at before merge.Independent review by the harness on
claude-opus-4-8. The human reviewer is requested once Igor has reviewed; a human still merges.