Skip to content

Commit 9f5f8c8

Browse files
committed
feat(org-plan): project native task progress
1 parent 8cfe9a6 commit 9f5f8c8

7 files changed

Lines changed: 158 additions & 4 deletions

File tree

AGENTS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@
2626
The reviewer
2727
skips already REVIEWED milestones, so appended refinement L1s do not trigger
2828
repeat audits of accepted work.
29+
- After every successful `authoring-start`, `supervision-start`, `set`, `l2`,
30+
`review`, or external `resync`, the active root runs `org-plan projection
31+
PLAN` and calls host `update_plan` with its exact ordered plan items, while
32+
reporting the companion explanation separately. This is a
33+
best-effort UI projection only: a missing or failed host tool warns once,
34+
never changes or rolls back Org state, and is retried at the next lifecycle
35+
boundary. Executors report mutations; Bash and MCP code never invoke another
36+
Codex tool.
2937
- Keep one writer active. The read-only root delegates implementation and
3038
corrective edits only to the active executor. Executor evidence and review
3139
requests go directly to the root as concise structured summaries.

plugins/gestalt/skills/org-plan/SKILL.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,12 @@ changes. Use its `--help` output for exact arguments.
3434
any required skill is unavailable.
3535
4. Use helper commands for TODO and review transitions; do not hand-edit them
3636
during execution.
37+
After each successful `authoring-start`, `supervision-start`, `set`, `l2`,
38+
`review`, or external `resync`, the active root reads `org-plan projection
39+
PLAN` and makes the host-owned `update_plan` call with its `plan` array,
40+
reporting its companion explanation separately. This is a best-effort UI
41+
projection only: tool unavailability warns without rolling back or changing
42+
the authoritative Org state.
3743
5. Keep one writer. L2 changes remain uncommitted through L1 review.
3844
6. Review only DONE + UNREVIEWED L1s. A REJECT returns corrections to the same
3945
L1 writer. REVIEWED is valid only after explicit reviewer acceptance.
@@ -89,6 +95,10 @@ changes. Use its `--help` output for exact arguments.
8995
those paths and do not commit them. Then record REVIEWED.
9096
8. Continue until every L1 and L2 is DONE and every L1 is REVIEWED.
9197

98+
The root performs the native projection after every successful lifecycle
99+
boundary named above; executors only report their successful helper mutation.
100+
Never ask Bash, an MCP server, or a generated profile to invoke `update_plan`.
101+
92102
Stop only for an unavailable required skill, a material ambiguity not resolved
93103
by the plan and repository, or an unavailable execution prerequisite. Update
94104
governing `AGENTS.md` only when the completed work changes durable repository

plugins/gestalt/skills/org-plan/references/cli-state.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ state.
77
|---|---|
88
| Validate plan | `org-plan validate PLAN` |
99
| Describe stable title, Goal/Why, position, and L1 Skills | `org-plan describe PLAN ID` |
10+
| Emit the read-only native Codex plan projection | `org-plan projection PLAN` |
1011
| Select implementation work | `org-plan next PLAN implement` |
1112
| Select first DONE + UNREVIEWED L1 | `org-plan next PLAN review` |
1213
| Transition L1 | `org-plan set PLAN L1_ID WIP\|DONE` |
@@ -19,6 +20,26 @@ state.
1920

2021
Signals are safe no-ops when Gestalt Mobile status integration is absent.
2122

23+
## Native Codex plan projection
24+
25+
`org-plan projection PLAN` validates and emits a read-only JSON document with
26+
a companion `explanation` plus ordered `plan` items ready for the host-owned
27+
`update_plan` tool. Current Codex tool items accept only `step` and `status`,
28+
so the root passes the exact `plan` array and reports the companion explanation
29+
as status context. Its item statuses use tool spelling: `pending`,
30+
`in_progress`, and `completed` (not app-server notification spelling
31+
`inProgress`). It projects only L1s: `TODO` is pending, `WIP` is in progress,
32+
`DONE + UNREVIEWED` is in progress with “Awaiting review”, and `DONE +
33+
REVIEWED` is completed. The Org file remains authoritative.
34+
35+
After every successful `authoring-start`, `supervision-start`, `set`, `l2`,
36+
`review`, or external `resync`, the active root runs `org-plan projection PLAN`
37+
and invokes host `update_plan` with its exact ordered plan items, reporting the
38+
companion explanation separately.
39+
This second action is best effort: if the host tool is absent or errors, warn
40+
once concisely, preserve the valid Org mutation, and retry only at the next
41+
lifecycle boundary. Bash helpers and MCP code never invoke `update_plan`.
42+
2243
## Legal progression
2344

2445
```text

plugins/gestalt/skills/org-plan/references/plan-format.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ prohibition. Before every implementation commit, inspect
1515
`git diff --cached --name-only`; it must exclude the active Org Plan and every
1616
`.gestalt/*.org` path.
1717

18+
After authoring or externally correcting a valid plan, the active root reads
19+
`org-plan projection PLAN` and best-effort synchronizes its exact `plan` array
20+
to host `update_plan`, reporting the companion explanation separately. Native
21+
status is only a compact UI projection; it never
22+
authorizes an Org transition, review, or completion.
23+
1824
## Document metadata
1925

2026
Include:

plugins/gestalt/skills/org-plan/references/supervised-execution.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ director (depth 0, org-plan-reviewer, Sol or Terra, read-only root)
2121

2222
## Start supervision
2323

24-
1. The root signals `supervision-start`.
24+
1. The root signals `supervision-start`, then runs `org-plan projection PLAN`
25+
and calls host `update_plan` with its exact `plan` items, reporting the
26+
companion explanation separately.
2527
2. Before each L1, verify the preceding L1 is REVIEWED, terminate the previous
2628
executor, confirm closure, and resolve the next milestone with
2729
`org-plan describe`.
@@ -35,6 +37,12 @@ director (depth 0, org-plan-reviewer, Sol or Terra, read-only root)
3537
After each L2, the root verifies intended dirty paths, inspects the L2
3638
diff, and requires current focused-test evidence before DONE.
3739

40+
After every successful `authoring-start`, `set`, `l2`, `review`, or external
41+
`resync`, the executor reports the helper mutation to the root. The root then
42+
runs `org-plan projection PLAN` and calls host `update_plan`; executors never
43+
create a competing native projection. A missing or failed host tool produces
44+
one concise warning and never reverses a valid Org mutation.
45+
3846
After all L2s, require a current full-suite pass and intended complete L1 diff.
3947
Use `org-plan next PLAN review`; request review only for the selected DONE +
4048
UNREVIEWED L1. The request contains:

plugins/gestalt/skills/org-plan/scripts/org-plan

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Strict helper for the small Org dialect used by the org-plan skill.
33
set -Eeuo pipefail
44

5-
usage() { printf 'usage: org-plan {validate|next|summary|describe|review|l2|measure|set|signal|prepare-executor|prepare-supervision} [args]\n' >&2; exit 2; }
5+
usage() { printf 'usage: org-plan {validate|next|summary|describe|projection|review|l2|measure|set|signal|prepare-executor|prepare-supervision} [args]\n' >&2; exit 2; }
66
die() { printf '%s: %s\n' "$plan" "$*" >&2; return 1; }
77
declare -a ids states levels lines titles parents starts ends review_status review_status_count review_lines skills skills_count
88
declare -A seen field field_value
@@ -126,6 +126,60 @@ json_escape() {
126126
printf '%s' "$output"
127127
}
128128

129+
# Native Codex plans are a compact display projection, so keep individual
130+
# strings bounded even when an Org author supplies unusually long prose.
131+
bounded_text() {
132+
local value=$1 limit=${2:-240}
133+
if (( ${#value} > limit )); then printf '%s…' "${value:0:limit-1}"; else printf '%s' "$value"; fi
134+
}
135+
136+
projection() {
137+
local i j position=0 total=0 reviewed=0 active=0 active_index=-1 active_position=0 status title goal current_l2='' explanation l2_position l2_total
138+
for ((i=0; i<count; i++)); do (( levels[$i] == 1 )) && total=$((total + 1)); done
139+
for ((i=0; i<count; i++)); do
140+
(( levels[$i] == 1 )) || continue
141+
[[ ${states[$i]} == DONE && ${review_status[$i]} == REVIEWED ]] && reviewed=$((reviewed + 1))
142+
if [[ ${states[$i]} == WIP || (${states[$i]} == DONE && ${review_status[$i]} == UNREVIEWED) ]]; then
143+
active=$((active + 1)); active_index=$i
144+
fi
145+
done
146+
(( active <= 1 )) || die 'native projection has multiple in_progress L1 items'
147+
if (( active_index >= 0 )); then
148+
for ((i=0; i<count; i++)); do (( levels[$i] == 1 && i <= active_index )) && active_position=$((active_position + 1)); done
149+
goal=${field_value[$active_index:Goal]:-${field_value[$active_index:Why]:-}}
150+
current_l2=''; l2_position=0; l2_total=0
151+
for ((j=0; j<count; j++)); do (( levels[$j] == 2 && parents[$j] == active_index )) && l2_total=$((l2_total + 1)); done
152+
for ((j=0; j<count; j++)); do
153+
(( levels[$j] == 2 && parents[$j] == active_index )) || continue
154+
l2_position=$((l2_position + 1))
155+
if [[ ${states[$j]} == WIP ]]; then current_l2="Current L2 $l2_position/$l2_total: ${titles[$j]} (${states[$j]})"; break; fi
156+
[[ -n $current_l2 || ${states[$j]} != TODO ]] || current_l2="Next L2 $l2_position/$l2_total: ${titles[$j]} (${states[$j]})"
157+
done
158+
[[ -n $current_l2 ]] || current_l2='All L2 milestones complete.'
159+
explanation="L1 $active_position/$total${titles[$active_index]}. Goal: $(bounded_text "$goal" 180). $current_l2"
160+
[[ ${states[$active_index]} != DONE ]] || explanation="Awaiting review. $explanation"
161+
else
162+
explanation="No L1 is active. $reviewed/$total L1 milestones are reviewed. Org state remains authoritative."
163+
fi
164+
printf '{"explanation":"%s","plan":[' "$(json_escape "$(bounded_text "$explanation")")"
165+
local first=1
166+
for ((i=0; i<count; i++)); do
167+
(( levels[$i] == 1 )) || continue
168+
position=$((position + 1))
169+
case "${states[$i]}:${review_status[$i]}" in
170+
TODO:*) status=pending ;;
171+
WIP:*) status=in_progress ;;
172+
DONE:UNREVIEWED) status=in_progress ;;
173+
DONE:REVIEWED) status=completed ;;
174+
*) die "invalid native projection state for ${ids[$i]}" ;;
175+
esac
176+
title="L1 $position/$total${titles[$i]}"
177+
(( first )) || printf ','; first=0
178+
printf '{"step":"%s","status":"%s"}' "$(json_escape "$(bounded_text "$title")")" "$status"
179+
done
180+
printf ']}\n'
181+
}
182+
129183
canonical_plan_path() {
130184
local original=$1 path parent base target hops=0
131185
case $original in /*) path=$original ;; *) path=$PWD/$original ;; esac
@@ -353,7 +407,7 @@ write_profile() {
353407

354408
prepare_executor() {
355409
local model='gpt-5.6-terra' profile_name='org-plan-executor' agents_dir="${HOME:?HOME is required}/.codex/agents"
356-
local lifecycle_requirements=' During supervised execution, direct TODO keyword or property edits are forbidden. Use org-plan set PLAN L1_ID WIP|DONE for L1 transitions and org-plan l2 PLAN L2_ID WIP|DONE for L2 transitions. Use org-plan next PLAN review and org-plan review PLAN L1_ID REVIEWED|UNREVIEWED for review selection and state. After any externally corrected plan file, run org-plan signal PLAN resync. Org Plan files are never Git deliverables: no user request, repository instruction, or release workflow overrides the ban on staging, committing, force-adding, cherry-picking, or otherwise introducing an Org Plan into Git history. Immediately before every accepted L1 commit, inspect git diff --cached --name-only; it must exclude the active Org Plan and every .gestalt/*.org path, including force-added paths. Status publication is optional when neither GESTALT_MOBILE_ORG_PLAN_STATUS_DIRECTORY nor the legacy GESTALT_MOBILE_ORG_PLAN_STATUS_FILE is present.'
410+
local lifecycle_requirements=' During supervised execution, direct TODO keyword or property edits are forbidden. Use org-plan set PLAN L1_ID WIP|DONE for L1 transitions and org-plan l2 PLAN L2_ID WIP|DONE for L2 transitions. Use org-plan next PLAN review and org-plan review PLAN L1_ID REVIEWED|UNREVIEWED for review selection and state. After any externally corrected plan file, run org-plan signal PLAN resync. After every successful authoring-start, supervision-start, set, l2, review, or resync helper action, report the mutation to the active root; executors never invoke host update_plan or create a competing native projection. Org Plan files are never Git deliverables: no user request, repository instruction, or release workflow overrides the ban on staging, committing, force-adding, cherry-picking, or otherwise introducing an Org Plan into Git history. Immediately before every accepted L1 commit, inspect git diff --cached --name-only; it must exclude the active Org Plan and every .gestalt/*.org path, including force-added paths. Status publication is optional when neither GESTALT_MOBILE_ORG_PLAN_STATUS_DIRECTORY nor the legacy GESTALT_MOBILE_ORG_PLAN_STATUS_FILE is present.'
357411
while (( $# )); do
358412
case $1 in
359413
--model) (( $# >= 2 )) || usage; model=$2; shift 2 ;;
@@ -376,7 +430,7 @@ prepare_supervision() {
376430
local executor_model='gpt-5.6-terra' reviewer_model='gpt-5.6-sol'
377431
local executor_name='org-plan-executor' reviewer_name='org-plan-reviewer'
378432
local agents_dir="${HOME:?HOME is required}/.codex/agents"
379-
local lifecycle_requirements=' Before the first L1, run org-plan signal PLAN supervision-start. During supervised execution, direct TODO keyword or property edits are forbidden. Require the executor to use org-plan set PLAN L1_ID WIP|DONE and org-plan l2 PLAN L2_ID WIP|DONE for all state transitions, retain org-plan next PLAN review and org-plan review PLAN L1_ID REVIEWED|UNREVIEWED for review selection and state, and run org-plan signal PLAN resync after any externally corrected plan file. Org Plan files are never Git deliverables: no user request, repository instruction, or release workflow overrides the ban on staging, committing, force-adding, cherry-picking, or otherwise introducing an Org Plan into Git history. Immediately before every accepted L1 commit, inspect git diff --cached --name-only; it must exclude the active Org Plan and every .gestalt/*.org path, including force-added paths. Status publication is optional when neither GESTALT_MOBILE_ORG_PLAN_STATUS_DIRECTORY nor the legacy GESTALT_MOBILE_ORG_PLAN_STATUS_FILE is present.'
433+
local lifecycle_requirements=' Before the first L1, run org-plan signal PLAN supervision-start. During supervised execution, direct TODO keyword or property edits are forbidden. Require the executor to use org-plan set PLAN L1_ID WIP|DONE and org-plan l2 PLAN L2_ID WIP|DONE for all state transitions, retain org-plan next PLAN review and org-plan review PLAN L1_ID REVIEWED|UNREVIEWED for review selection and state, and run org-plan signal PLAN resync after any externally corrected plan file. After every successful authoring-start, supervision-start, set, l2, review, or resync helper action, the active root runs org-plan projection PLAN and makes the host-owned update_plan call with its exact plan items, reporting the companion explanation separately. Executors report mutations and never invoke host update_plan or create a competing native projection. If update_plan is absent or fails, warn once, keep Org state authoritative, and retry only at the next lifecycle boundary; Bash and MCP code never invoke it. Org Plan files are never Git deliverables: no user request, repository instruction, or release workflow overrides the ban on staging, committing, force-adding, cherry-picking, or otherwise introducing an Org Plan into Git history. Immediately before every accepted L1 commit, inspect git diff --cached --name-only; it must exclude the active Org Plan and every .gestalt/*.org path, including force-added paths. Status publication is optional when neither GESTALT_MOBILE_ORG_PLAN_STATUS_DIRECTORY nor the legacy GESTALT_MOBILE_ORG_PLAN_STATUS_FILE is present.'
380434
while (( $# )); do
381435
case $1 in
382436
--executor-model) (( $# >= 2 )) || usage; executor_model=$2; shift 2 ;;
@@ -455,6 +509,8 @@ case $cmd in
455509
label=Why
456510
printf 'L2 %s\n%s: %s\n' "${titles[$target]}" "$label" "${field_value[$target:$label]}"
457511
fi ;;
512+
projection)
513+
[ $# = 1 ] || usage; parse "$1"; projection "$1" ;;
458514
review)
459515
[ $# = 3 ] || usage; original=$1; parse "$original"; target=$(find_id "$2") || die "unknown ID $2"; new=$3
460516
(( levels[$target] == 1 )) || die "ID $2 is not an L1"

0 commit comments

Comments
 (0)