okstra 0.177.0 → 0.178.0

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.
Files changed (41) hide show
  1. package/dist/commands/execute/team.mjs +14 -4
  2. package/dist/commands/execute/team.mjs.map +1 -1
  3. package/dist/commands/lifecycle/install.mjs +0 -1
  4. package/dist/commands/lifecycle/install.mjs.map +1 -1
  5. package/docs/architecture.md +3 -3
  6. package/docs/cli.md +1 -1
  7. package/docs/project-structure-overview.md +2 -2
  8. package/package.json +1 -1
  9. package/runtime/BUILD.json +2 -2
  10. package/runtime/agents/workers/report-writer-worker.md +1 -1
  11. package/runtime/bin/okstra-compact-reminder.sh +2 -2
  12. package/runtime/bin/okstra-render-report-views.py +13 -10
  13. package/runtime/prompts/lead/okstra-lead-contract.md +2 -2
  14. package/runtime/prompts/lead/report-writer.md +5 -1
  15. package/runtime/prompts/profiles/_common-contract.md +1 -1
  16. package/runtime/python/okstra_ctl/adapters/hosts/claude-code/relay.md +5 -6
  17. package/runtime/python/okstra_ctl/adapters/providers/antigravity/adapter.py +23 -1
  18. package/runtime/python/okstra_ctl/agent_invocation.py +17 -0
  19. package/runtime/python/okstra_ctl/agent_prompt_cli.py +13 -0
  20. package/runtime/python/okstra_ctl/dispatch_core.py +96 -17
  21. package/runtime/python/okstra_ctl/dispatch_state.py +57 -0
  22. package/runtime/python/okstra_ctl/model_cli.py +11 -2
  23. package/runtime/python/okstra_ctl/model_discovery.py +12 -0
  24. package/runtime/python/okstra_ctl/pane_reclaim.py +49 -43
  25. package/runtime/python/okstra_ctl/render.py +53 -0
  26. package/runtime/python/okstra_ctl/report_html/render.py +7 -4
  27. package/runtime/python/okstra_ctl/report_views.py +35 -0
  28. package/runtime/python/okstra_ctl/run.py +88 -2
  29. package/runtime/python/okstra_ctl/team.py +84 -14
  30. package/runtime/python/okstra_ctl/tmux.py +2 -3
  31. package/runtime/python/okstra_ctl/user_response.py +20 -4
  32. package/runtime/python/okstra_ctl/worker_runner.py +2 -2
  33. package/runtime/python/okstra_ctl/write_policy.py +9 -1
  34. package/runtime/schemas/final-report-v2.0.schema.json +24 -1
  35. package/runtime/skills/okstra-run/SKILL.md +3 -3
  36. package/runtime/templates/reports/final-report-v2.template.md +2 -1
  37. package/runtime/templates/reports/html/base.template.html +1 -2
  38. package/runtime/validators/validate-report-views.py +30 -17
  39. package/runtime/validators/validate-run.py +256 -78
  40. package/runtime/validators/validate_session_conformance.py +1 -1
  41. package/runtime/bin/okstra-trace-cleanup.sh +0 -185
@@ -1,185 +0,0 @@
1
- #!/usr/bin/env bash
2
- #
3
- # okstra-trace-cleanup.sh — close the harness-owned worker panes of an okstra run.
4
- #
5
- # The panes this closes are the teammate panes the HARNESS splits for dispatched
6
- # worker agents. okstra does not create them and cannot tag them, so they are
7
- # found by a title allowlist scoped to the lead's window. They accumulate until
8
- # the pane budget runs out, and `shutdown_request` only idles the agent without
9
- # freeing its pane — this script is the only thing that closes them, which is why
10
- # the lead calls it at every round boundary and before every user gate.
11
- #
12
- # Two tag-driven paths used to live here and both are gone:
13
- #
14
- # - Worker-compute panes of the `tmux-pane` dispatch backend, tagged
15
- # `@okstra_worker_run`. That backend was removed — a worker now gets a cmux
16
- # surface or a cli-wrapper subprocess, and neither is a tmux pane okstra owns.
17
- # - Trace panes, tagged `@okstra_trace_run` / `@okstra_status`, which the
18
- # provider wrappers used to split as `tail -F` siblings. The wrappers became
19
- # four-line entrypoints and worker progress renders into the worker's own
20
- # pane, so nothing had spawned a trace pane for some time.
21
- #
22
- # With both writers gone the tag scan matched nothing, so it was removed along
23
- # with the two modes that existed only to drive it (`--reap`, which the SessionEnd
24
- # hook called, and `--reclaim-completed`, which `okstra-subagent-reclaim.sh` drove
25
- # from SubagentStop / TaskCompleted). Those hooks are gone from the seeded
26
- # settings too.
27
- #
28
- # Invocation:
29
- #
30
- # --run-dir <RUN_DIR> Closes the run's worker-agent panes (`claude-worker` /
31
- # `codex-worker` / `antigravity-worker` /
32
- # `report-writer-worker` and the FleetView teammate
33
- # prefixes), scoped to the LEAD's WINDOW. The lead pane is
34
- # read from `<RUN_DIR>/state/lead-pane.id` (recorded once
35
- # by the lead in its own foreground pane — reliable even
36
- # though Claude Code's Bash tool strips `$TMUX` /
37
- # `$TMUX_PANE`); it scopes the scan and is NEVER killed.
38
- # Window scope keeps a second lead running in another
39
- # window of the same session out of range.
40
- #
41
- # `--list` (alias `--dry-run`) prints `<pane_id>\t<pane_title>` per pane instead
42
- # of killing.
43
- #
44
- # `--keep <substr>` (repeatable) spares any pane whose current title contains
45
- # <substr>, in both the kill and the list set. Used to preserve an in-flight
46
- # report-writer at a round boundary.
47
- #
48
- # Failures are tolerated silently — a stale pane id, no tmux, or a locked tmux
49
- # client must never prevent Claude from exiting cleanly.
50
-
51
- set -u
52
-
53
- # Caller-pane resolution helper (okstra_resolve_caller_pane) — see
54
- # lib/okstra/tmux-pane.sh. Used as the lead-pane fallback below so a missing /
55
- # stale lead-pane.id resolves to the pane THIS process actually runs in (via
56
- # ancestor-PID ↔ tmux pane_pid matching), never a foreign active-client pane.
57
- # Bin-sibling path in repo + installed layouts; degrade silently if absent.
58
- _clean_script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
59
- [ -r "$_clean_script_dir/lib/okstra/tmux-pane.sh" ] && . "$_clean_script_dir/lib/okstra/tmux-pane.sh"
60
-
61
- MODE="kill" # kill | list
62
- run_dir=""
63
- KEEP_PATTERNS=() # --keep <substr>: panes whose title contains substr are spared from kill/list
64
- while [[ $# -gt 0 ]]; do
65
- case "$1" in
66
- --list|--dry-run) MODE="list" ;;
67
- --run-dir) shift; run_dir="${1-}" ;;
68
- --run-dir=*) run_dir="${1#--run-dir=}" ;;
69
- --keep) shift; KEEP_PATTERNS+=("${1-}") ;;
70
- --keep=*) KEEP_PATTERNS+=("${1#--keep=}") ;;
71
- -h|--help)
72
- cat <<'USAGE'
73
- usage: okstra-trace-cleanup.sh --run-dir <RUN_DIR> [--list] [--keep <substr>]...
74
-
75
- --run-dir okstra run directory; closes that run's worker-agent panes.
76
- --list print "<pane_id>\t<pane_title>" per pane; no kill.
77
- --dry-run alias for --list.
78
- --keep <substr> exclude any pane whose title contains <substr> from the
79
- kill/list set (repeatable). Used to spare an in-flight
80
- report-writer at a round boundary.
81
- USAGE
82
- exit 0 ;;
83
- *)
84
- printf 'okstra-trace-cleanup.sh: unknown option: %s\n' "$1" >&2
85
- exit 2 ;;
86
- esac
87
- shift
88
- done
89
-
90
- if [[ -z "$run_dir" ]]; then
91
- printf 'okstra-trace-cleanup.sh: --run-dir <RUN_DIR> is required\n' >&2
92
- exit 2
93
- fi
94
-
95
- # Lead pane. Prefer the value the lead recorded in its own foreground pane; fall
96
- # back to the active-pane probe. Rejected if the recorded pane is gone.
97
- lead_pane=""
98
- lead_pane_file="$run_dir/state/lead-pane.id"
99
- [[ -r "$lead_pane_file" ]] && lead_pane="$(head -n1 "$lead_pane_file" 2>/dev/null || true)"
100
- if [[ -z "$lead_pane" ]] || ! tmux display-message -p -t "$lead_pane" '#{pane_id}' >/dev/null 2>&1; then
101
- if type okstra_resolve_caller_pane >/dev/null 2>&1; then
102
- lead_pane="$(okstra_resolve_caller_pane 2>/dev/null || true)"
103
- else
104
- lead_pane="$(tmux display-message -p '#{pane_id}' 2>/dev/null || true)"
105
- fi
106
- fi
107
-
108
- _title_in_okstra_scope() {
109
- local title="$1"
110
- case "$title" in
111
- # Claude/FleetView teammate panes may carry the task title instead of the
112
- # worker id. These glyph prefixes are the only stable tmux-side signal.
113
- "✳ "*|"⠂ "*)
114
- return 0 ;;
115
- *claude-worker*|*claude-executor*|*claude-verifier*)
116
- return 0 ;;
117
- *codex-worker*|*codex-executor*|*codex-verifier*)
118
- return 0 ;;
119
- *agy-worker*|*agy-executor*|*agy-verifier*)
120
- return 0 ;;
121
- *antigravity-worker*|*antigravity-executor*|*antigravity-verifier*)
122
- return 0 ;;
123
- *report-writer-worker*|*report-writer*)
124
- return 0 ;;
125
- esac
126
- return 1
127
- }
128
-
129
- # A collected pane whose current title contains any --keep substring is spared.
130
- _keep_excluded() {
131
- local pid="$1" title pat
132
- (( ${#KEEP_PATTERNS[@]} )) || return 1
133
- title=$(tmux display-message -p -t "$pid" '#{pane_title}' 2>/dev/null || true)
134
- for pat in "${KEEP_PATTERNS[@]}"; do
135
- [[ -n "$pat" && "$title" == *"$pat"* ]] && return 0
136
- done
137
- return 1
138
- }
139
-
140
- collect_okstra_panes() {
141
- local -a panes=()
142
- local pid title
143
-
144
- # Title-allowlisted worker-agent panes in the lead's WINDOW. `list-panes -t
145
- # <pane>` (no `-s`, no `-a`) resolves the window containing that pane and lists
146
- # only that window's panes. Split-pane teammates always land in the lead's
147
- # window, so this catches all of THIS run's worker panes while a second okstra
148
- # lead in another window of the same tmux session is left untouched. Skipped
149
- # when the lead pane is unknown.
150
- [[ -n "$lead_pane" ]] || return 0
151
- while IFS=$'\t' read -r pid title; do
152
- [[ -n "$pid" ]] || continue
153
- [[ "$pid" == "$lead_pane" ]] && continue
154
- if _title_in_okstra_scope "$title"; then
155
- panes+=("$pid")
156
- fi
157
- done < <(tmux list-panes -t "$lead_pane" \
158
- -F '#{pane_id}'$'\t''#{pane_title}' 2>/dev/null || true)
159
-
160
- # Drop any pane a --keep pattern spares (in-flight report-writer).
161
- if (( ${#panes[@]} )); then
162
- printf '%s\n' "${panes[@]}" | awk 'NF && !seen[$0]++' | while IFS= read -r _pid; do
163
- _keep_excluded "$_pid" && continue
164
- printf '%s\n' "$_pid"
165
- done
166
- fi
167
- }
168
-
169
- if [[ "$MODE" == "list" ]]; then
170
- while IFS= read -r pane_id; do
171
- [[ -n "$pane_id" ]] || continue
172
- # `display-message -p` resolves a *live* pane's title; for stale ids tmux
173
- # exits non-zero — fall back to an empty title rather than failing.
174
- title=$(tmux display-message -p -t "$pane_id" '#{pane_title}' 2>/dev/null || true)
175
- printf '%s\t%s\n' "$pane_id" "$title"
176
- done < <(collect_okstra_panes)
177
- exit 0
178
- fi
179
-
180
- while IFS= read -r pane_id; do
181
- [[ -n "$pane_id" ]] || continue
182
- tmux kill-pane -t "$pane_id" 2>/dev/null || true
183
- done < <(collect_okstra_panes)
184
-
185
- exit 0