Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
231 commits
Select commit Hold shift + click to select a range
d1d4ee7
feat(ci): add --compare-checkpoint to ci-status-only script
oldrepublicwizard May 24, 2026
943ae2d
test(ci): add unit tests for checkpoint compare parsing
oldrepublicwizard May 24, 2026
77779a7
feat(ci): add --exit-on-defer for unchanged checkpoint
oldrepublicwizard May 24, 2026
79224ad
docs(testing): document agent defer check in closeout doc
oldrepublicwizard May 24, 2026
e761c4f
feat(ci): add --monitor-preflight shorthand for defer check
oldrepublicwizard May 24, 2026
4598ba7
feat(ci): add --strict-defer-exit for LFG monitoring gate
oldrepublicwizard May 24, 2026
e4beac6
feat(ci): detect verify sha drift and refresh dispatch
oldrepublicwizard May 24, 2026
c6091c4
fix(ci): print checkpoint bug and emit snippet helper
oldrepublicwizard May 25, 2026
929a87c
feat(ci): fc docs-only stale benign and checkpoint validate
oldrepublicwizard May 25, 2026
d9c9f8e
docs(agents): document validate-checkpoint-doc and fc_sha_stale_benign
oldrepublicwizard May 25, 2026
46f2439
feat(ci): enrich preflight doc validation and checkpoint snippet
oldrepublicwizard May 25, 2026
01abda2
feat(ci): queue age hints and default preflight snippet
oldrepublicwizard May 25, 2026
3de25bb
feat(ci): apply checkpoint snippet dry-run and write
oldrepublicwizard May 25, 2026
456c9c1
feat(ci): extend apply to plan020 table and proceed reason
oldrepublicwizard May 25, 2026
8e9b228
feat(ci): auto apply docs on proceed and lfg_proceed signal
oldrepublicwizard May 25, 2026
040adf0
feat(ci): add dispatch-on-proceed gh workflow helpers
oldrepublicwizard May 25, 2026
447dc3b
feat(ci): add include-proceed-actions and post-dispatch doc sync
oldrepublicwizard May 25, 2026
aafa396
feat(ci): add lfg-refresh alias and dispatch poll retry
oldrepublicwizard May 27, 2026
80b8fce
fix(ci): resolve check-file-size permissions and devskim false positives
oldrepublicwizard May 27, 2026
0f141ef
feat(ci): add lfg-refresh dry-run and noop guardrails
oldrepublicwizard May 27, 2026
7983102
feat(ci): add lfg-preflight shorthand and proceed hints
oldrepublicwizard May 27, 2026
29bf625
feat(ci): add lfg-gate, lfg-closeout, and agent loop docs (079-080)
oldrepublicwizard May 27, 2026
42bc59b
fix(ci): accurate doc patches and closeout proceed hints (081)
oldrepublicwizard May 27, 2026
9c3291f
feat(ci): add monitoring complete gate and git prefetch (082)
oldrepublicwizard May 27, 2026
6af374b
docs(ci): sync plan 020 plan cap to 082
oldrepublicwizard May 27, 2026
50355bd
feat(ci): add prefetch recompare and pr merge readiness (083)
oldrepublicwizard May 27, 2026
ebebedb
fix(ci): improve pr merge readiness rollup and exit codes (084)
oldrepublicwizard May 27, 2026
5b2d0c5
docs(plan): add lfg merge gate and pr watch plan 085
oldrepublicwizard May 27, 2026
99fd2a1
feat(ci): add lfg merge gate and pr check watch (085)
oldrepublicwizard May 27, 2026
4f974c9
docs(ci): document lfg merge gate and pr watch (085)
oldrepublicwizard May 27, 2026
896fdcc
docs(plan): add pr check details and merge watch plan 086
oldrepublicwizard May 27, 2026
283261e
feat(ci): enrich pr check details and add merge watch (086)
oldrepublicwizard May 27, 2026
bb9b0c4
docs(ci): document merge watch and check details (086)
oldrepublicwizard May 27, 2026
3af5516
docs(plan): add merge conflicts and exit code plan 087
oldrepublicwizard May 27, 2026
d1ba3f0
feat(ci): add merge conflict gate and lfg exit code (087)
oldrepublicwizard May 27, 2026
61ee172
docs(ci): document lfg exit code and merge conflicts (087)
oldrepublicwizard May 27, 2026
84b8c54
docs(plan): add exit reason and ci progress plan 088
oldrepublicwizard May 27, 2026
27e94c7
feat(ci): add lfg exit reason and pr ci progress (088)
oldrepublicwizard May 27, 2026
9701555
docs(ci): document exit reason and ci progress (088)
oldrepublicwizard May 27, 2026
098ba29
docs(plan): add statuscontext and unified exit plan 089
oldrepublicwizard May 27, 2026
351fda6
feat(ci): statuscontext rollup and unified lfg exit (089)
oldrepublicwizard May 27, 2026
9ca925a
docs(ci): document statuscontext and unified exit (089)
oldrepublicwizard May 27, 2026
40fd877
docs(plan): add no open pr and exit legend plan 090
oldrepublicwizard May 27, 2026
f4aa6be
feat(ci): no open pr gate and lfg exit legend (090)
oldrepublicwizard May 27, 2026
e3db71f
docs(ci): document no open pr gate and exit legend (090)
oldrepublicwizard May 27, 2026
2e8af3d
docs(plan): add merge actions and pr lifecycle plan 091
oldrepublicwizard May 27, 2026
5e2359f
feat(ci): merge actions and pr lifecycle states (091)
oldrepublicwizard May 27, 2026
39f06f9
docs(ci): document merge actions and pr lifecycle (091)
oldrepublicwizard May 27, 2026
d056a7f
docs(plan): add next failed and in progress plan 092
oldrepublicwizard May 27, 2026
95a0c12
feat(ci): next failed check and in progress priority (092)
oldrepublicwizard May 27, 2026
5a75de9
docs(ci): document next failed and in progress priority (092)
oldrepublicwizard May 27, 2026
efc75b8
docs(ci): add pr watch stall bottleneck plan (093)
oldrepublicwizard May 27, 2026
a748af5
feat(ci): add pr watch stall detection and bottlenecks (093)
oldrepublicwizard May 27, 2026
0dd8b69
test(ci): cover pr watch stall and bottleneck helpers (093)
oldrepublicwizard May 27, 2026
ea62c19
docs(ci): document watch stall polls and bottlenecks (093)
oldrepublicwizard May 27, 2026
2dcc785
docs(ci): add pr queue stall detection plan (094)
oldrepublicwizard May 27, 2026
13f3289
feat(ci): distinguish queue backlog from job hang stalls (094)
oldrepublicwizard May 27, 2026
8746176
test(ci): cover queue vs job watch stall paths (094)
oldrepublicwizard May 27, 2026
80affa6
docs(ci): document queue stall signals and bump cap (094)
oldrepublicwizard May 27, 2026
cc65823
docs(ci): add watch continue queue stall plan (095)
oldrepublicwizard May 27, 2026
bd1dccf
feat(ci): continue watch through queue backlog by default (095)
oldrepublicwizard May 27, 2026
90ed78a
test(ci): cover queue stall continue and timeout paths (095)
oldrepublicwizard May 27, 2026
c78f2cc
docs(ci): document watch continue queue stall behavior (095)
oldrepublicwizard May 27, 2026
35d5a56
docs(ci): add pr watch summary plan (096)
oldrepublicwizard May 27, 2026
5a8c846
feat(ci): add pr watch summary and merge-watch 2h default (096)
oldrepublicwizard May 27, 2026
63b503d
test(ci): cover pr watch summary and timeout defaults (096)
oldrepublicwizard May 27, 2026
5fd0127
docs(ci): document pr watch summary and 2h default (096)
oldrepublicwizard May 27, 2026
5680877
docs(ci): add pr queue age crosscheck plan (097)
oldrepublicwizard May 27, 2026
a667f76
feat(ci): add queue age and pr checks crosscheck (097)
oldrepublicwizard May 27, 2026
02e9661
test(ci): cover queue age and checks crosscheck (097)
oldrepublicwizard May 27, 2026
045467a
docs(ci): document queue age and crosscheck fields (097)
oldrepublicwizard May 27, 2026
0257ab1
docs(ci): add queue backlog severity plan (098)
oldrepublicwizard May 27, 2026
09fcedf
feat(ci): add queue backlog severity and deduped stalls (098)
oldrepublicwizard May 27, 2026
b1e5208
test(ci): cover queue backlog severity and summary (098)
oldrepublicwizard May 27, 2026
bce258c
docs(ci): document queue backlog severe flag (098)
oldrepublicwizard May 27, 2026
563dfd2
docs(ci): add pr ci recommendation plan (099)
oldrepublicwizard May 27, 2026
5b9f54a
feat(ci): add pr ci recommendation and queue notes (099)
oldrepublicwizard May 27, 2026
d3ae04e
test(ci): cover pr ci recommendation helpers (099)
oldrepublicwizard May 27, 2026
6a9bf05
docs(ci): document pr ci recommendation fields (099)
oldrepublicwizard May 27, 2026
d30136f
test(ci): use recent queue timestamp in backlog hint test
oldrepublicwizard May 27, 2026
14ed8de
docs(ci): add lfg exit recommendation plan (100)
oldrepublicwizard May 27, 2026
0d978cb
feat(ci): compound pr ci recommendation in lfg exit reason (100)
oldrepublicwizard May 27, 2026
18c4746
test(ci): cover lfg exit reason recommendation suffix (100)
oldrepublicwizard May 27, 2026
11ece4d
docs(ci): document lfg exit reason recommendation suffix (100)
oldrepublicwizard May 27, 2026
98ec3db
docs(ci): add compact unchanged watch poll plan (101)
oldrepublicwizard May 27, 2026
b7cffd3
feat(ci): compact unchanged pr watch poll stderr (101)
oldrepublicwizard May 27, 2026
1757e27
test(ci): cover compact unchanged watch polls (101)
oldrepublicwizard May 27, 2026
dceee85
docs(ci): document compact unchanged watch polls (101)
oldrepublicwizard May 27, 2026
5293295
docs(ci): add pr checks crosscheck note plan (102)
oldrepublicwizard May 27, 2026
b3816c8
feat(ci): add pr checks crosscheck note for rollup gh delta (102)
oldrepublicwizard May 27, 2026
36f2a58
test(ci): cover pr checks crosscheck note helpers (102)
oldrepublicwizard May 27, 2026
3f75ceb
docs(ci): document pr checks crosscheck note field (102)
oldrepublicwizard May 27, 2026
4e9ea9c
docs(ci): add lfg agent briefing plan (103)
oldrepublicwizard May 27, 2026
68ae6e6
feat(ci): add consolidated lfg agent briefing json (103)
oldrepublicwizard May 27, 2026
f3d591a
test(ci): cover lfg agent briefing helpers (103)
oldrepublicwizard May 27, 2026
7300ffa
docs(ci): document lfg agent briefing field (103)
oldrepublicwizard May 27, 2026
c65abdb
docs(ci): add watch heartbeat polls plan (104)
oldrepublicwizard May 27, 2026
204fd32
feat(ci): add watch heartbeat polls for full stderr refresh (104)
oldrepublicwizard May 27, 2026
1e81a52
test(ci): cover watch heartbeat poll behavior (104)
oldrepublicwizard May 27, 2026
616a2d9
docs(ci): document watch heartbeat polls flag (104)
oldrepublicwizard May 27, 2026
4e30913
docs(ci): add preflight dry-run briefing plan (105)
oldrepublicwizard May 27, 2026
c6df45c
fix(ci): preflight dry-run json and blocked agent briefing (105)
oldrepublicwizard May 27, 2026
63f308c
test(ci): cover blocked refresh agent briefing (105)
oldrepublicwizard May 27, 2026
e19f3ad
docs(ci): document preflight dry-run briefing fix (105)
oldrepublicwizard May 27, 2026
cfb3d3e
docs(ci): add plan 106 ci drift before fc classify gap
oldrepublicwizard May 27, 2026
658d230
fix(ci): prioritize run id drift over fc stale classify gap
oldrepublicwizard May 27, 2026
c0c56eb
docs(ci): document plan 106 drift routing and track cap
oldrepublicwizard May 27, 2026
186fbc9
docs(ci): add plan 107 defer classify gap when fc active
oldrepublicwizard May 27, 2026
9cd3cc4
fix(ci): defer classify fc stale gap while fc run active
oldrepublicwizard May 27, 2026
2781a9a
docs(ci): document plan 107 active fc defer routing
oldrepublicwizard May 27, 2026
9d7c17a
docs(ci): add plan 108 lfg defer reason fc active pending
oldrepublicwizard May 27, 2026
558c74f
fix(ci): add semantic lfg defer reason for fc active pending
oldrepublicwizard May 27, 2026
0e55e23
docs(ci): document plan 108 defer reason semantics
oldrepublicwizard May 27, 2026
6d81c61
docs(ci): add plan 109 gh lookup failure briefing
oldrepublicwizard May 27, 2026
c17f6b9
fix(ci): add agent briefing for gh lookup failures
oldrepublicwizard May 27, 2026
4081f0a
docs(ci): document plan 109 gh unavailable briefing
oldrepublicwizard May 27, 2026
aebfca3
docs(ci): add plan 110 doc snapshot on gh unavailable
oldrepublicwizard May 28, 2026
7f3ac42
fix(ci): add doc checkpoint snapshot when gh unavailable
oldrepublicwizard May 28, 2026
4ecc751
docs(ci): document plan 110 doc snapshot fallback
oldrepublicwizard May 28, 2026
025bd2d
docs(ci): add plan 111 defer closeout until fc terminal
oldrepublicwizard May 28, 2026
caea172
fix(ci): defer closeout until verify and fc runs terminal
oldrepublicwizard May 28, 2026
3ae0b67
docs(ci): document plan 111 closeout defer routing
oldrepublicwizard May 28, 2026
9dd5ae5
docs(ci): add plan 112 defer briefing active run refs
oldrepublicwizard May 28, 2026
fa6871e
fix(ci): add fc run url and id to defer agent briefing
oldrepublicwizard May 28, 2026
627388c
docs(ci): document plan 112 defer briefing run refs
oldrepublicwizard May 28, 2026
b3d4e5c
feat(verify-pypi): add defer monitor commands for fc watch
oldrepublicwizard May 28, 2026
b0fb9de
Merge branch 'master' into feat/ci-status-checkpoint-compare
oldrepublicwizard May 28, 2026
d6404e6
feat(verify-pypi): add lfg preflight watch polling mode
oldrepublicwizard May 28, 2026
1ff4a6a
fix(verify-pypi): wait on active runs during ci drift
oldrepublicwizard May 28, 2026
98a60a2
fix(verify-pypi): route defer fc-active command to preflight-watch
oldrepublicwizard May 28, 2026
fe8dcfe
fix(verify-pypi): add defer sha gap detail and fix preflight retry
oldrepublicwizard May 28, 2026
55e9da4
feat(verify-pypi): add lfg gate-watch and post-terminal commands
oldrepublicwizard May 28, 2026
f6de8fd
fix(verify-pypi): prefer gate-watch as primary defer wait command
oldrepublicwizard May 28, 2026
88df696
fix(verify-pypi): add defer queue context for fc-active path
oldrepublicwizard May 28, 2026
194bce0
fix(verify-pypi): gate-watch poll labels and defer queued stderr
oldrepublicwizard May 28, 2026
d563b08
checkpoint before checking out master
oldrepublicwizard May 28, 2026
ce0a5c0
test(verify-pypi): cover plan 122 defer expected-after-terminal
oldrepublicwizard May 28, 2026
c115cef
fix(verify-pypi): drift expected-after-terminal and primary action
oldrepublicwizard May 28, 2026
45b14da
fix(verify-pypi): defer active_runs and closeout expected-after
oldrepublicwizard May 28, 2026
fab5b54
fix(verify-pypi): enrich strict exit and verify_run stderr
oldrepublicwizard May 28, 2026
ec08cca
fix(verify-pypi): add gh_watch multi-run and watch summary active_runs
oldrepublicwizard May 28, 2026
1ae4717
fix(verify-pypi): propagate gh_watch to strict exit and watch summary
oldrepublicwizard May 28, 2026
ef187ee
fix(verify-pypi): add gh_watch to preflight watch summary json
oldrepublicwizard May 28, 2026
d95a643
fix(verify-pypi): mirror gh_watch to gate json and watch polls
oldrepublicwizard May 28, 2026
d08f5c2
fix(verify-pypi): mirror active_runs json and queued on strict exit
oldrepublicwizard May 28, 2026
7880235
fix(verify-pypi): mirror queue_context and watch summary queued
oldrepublicwizard May 28, 2026
015d6eb
fix(verify-pypi): mirror expected_after and primary_action json
oldrepublicwizard May 28, 2026
c8d3bb5
fix(verify-pypi): enrich watch poll stderr with queued and expected_a…
oldrepublicwizard May 28, 2026
42b0a0a
fix(verify-pypi): mirror watch_recommended to gate json and stderr
oldrepublicwizard May 28, 2026
40efe83
fix(verify-pypi): mirror post_terminal_commands and poll watch flag
oldrepublicwizard May 28, 2026
3e6abe7
fix(verify-pypi): mirror wait_command and monitor_commands json
oldrepublicwizard May 28, 2026
7dd0404
fix(verify-pypi): mirror verify and fc run ids to gate json
oldrepublicwizard May 28, 2026
effe42f
fix(verify-pypi): mirror run urls to gate json (plan 138)
oldrepublicwizard May 28, 2026
3d770a3
fix(verify-pypi): mirror run status to gate json (plan 139)
oldrepublicwizard May 28, 2026
ff90f11
fix(verify-pypi): mirror blocked to gate json (plan 140)
oldrepublicwizard May 28, 2026
b5bc846
fix(verify-pypi): flatten queue flags to gate json (plan 141)
oldrepublicwizard May 28, 2026
2348d11
fix(verify-pypi): mirror briefing action to gate json (plan 142)
oldrepublicwizard May 28, 2026
b23df0a
fix(verify-pypi): mirror briefing notes to gate json (plan 143)
oldrepublicwizard May 28, 2026
6dcc766
fix(verify-pypi): mirror briefing reason to gate json (plan 144)
oldrepublicwizard May 28, 2026
1fab8e7
fix(verify-pypi): mirror briefing merge ready to gate json (plan 145)
oldrepublicwizard May 28, 2026
03fc2ca
fix(verify-pypi): flatten queue backlog note to gate json (plan 146)
oldrepublicwizard May 28, 2026
cf07dba
fix(verify-pypi): mirror sha gap to gate json (plan 147)
oldrepublicwizard May 28, 2026
07becb8
feat(ci): mirror gh_watch_command to top-level gate json (plan 148)
oldrepublicwizard May 28, 2026
a4b4053
feat(ci): mirror briefing_command to top-level gate json (plan 149)
oldrepublicwizard May 28, 2026
0b1f7d0
feat(ci): add queue_note to defer watch poll stderr (plan 150)
oldrepublicwizard May 28, 2026
317dd1c
feat(ci): add blocked to defer watch poll stderr (plan 151)
oldrepublicwizard May 28, 2026
2455b54
feat(ci): add briefing_reason to defer watch poll stderr (plan 152)
oldrepublicwizard May 28, 2026
7504c54
feat(ci): add briefing action to defer watch poll stderr (plan 153)
oldrepublicwizard May 28, 2026
f10c697
feat(ci): add briefing notes count to defer watch poll stderr (plan 154)
oldrepublicwizard May 28, 2026
5f2684a
feat(ci): add merge_ready to defer watch poll stderr (plan 155)
oldrepublicwizard May 28, 2026
739316a
feat(ci): add verify_run fc_run to defer watch poll stderr (plan 156)
oldrepublicwizard May 28, 2026
a2e416e
feat(ci): mirror run status on defer watch poll stderr (plan 157)
oldrepublicwizard May 28, 2026
a9509e3
feat(ci): mirror gh_watch_summary on defer watch poll stderr (plan 158)
oldrepublicwizard May 28, 2026
2d676c6
feat(ci): mirror queue flags on defer watch poll stderr (plan 159)
oldrepublicwizard May 28, 2026
c343264
feat(ci): mirror active_runs on defer watch poll stderr (plan 160)
oldrepublicwizard May 28, 2026
2df4f87
feat(ci): mirror run URLs on defer watch poll stderr (plan 161)
oldrepublicwizard May 28, 2026
44422a8
feat(ci): skip legacy verify/fc ids on defer watch poll (plan 162)
oldrepublicwizard May 28, 2026
e821e5b
feat(ci): skip per-run queued tokens on defer watch poll (plan 163)
oldrepublicwizard May 28, 2026
cd6f1aa
feat(ci): mirror sha_gap_short on defer watch poll stderr (plan 164)
oldrepublicwizard May 28, 2026
a2cba5d
feat(ci): mirror primary_action on defer watch poll stderr (plan 165)
oldrepublicwizard May 28, 2026
ea08ac7
feat(ci): mirror watch commands on defer watch poll stderr (plan 166)
oldrepublicwizard May 28, 2026
d9ef400
feat(ci): mirror notes and merge_ready on defer watch poll (plan 167)
oldrepublicwizard May 28, 2026
2c22b87
feat(ci): add run refs to watch summary one-liner stderr (plan 168)
oldrepublicwizard May 28, 2026
4f155a9
feat(ci): prefer top-level queue fields on watch summary stderr (plan…
oldrepublicwizard May 28, 2026
e6eb436
feat(ci): mirror watch summary from top-level status (plan 170)
oldrepublicwizard May 28, 2026
e53ef04
feat(ci): share strict exit stderr mirror helper from status (plan 171)
oldrepublicwizard May 28, 2026
19ffaf5
feat(ci): reuse mirror helper on watch summary stderr (plan 172)
oldrepublicwizard May 28, 2026
77583f4
merge(master): resolve verify-pypi track conflicts keeping plan 172 b…
oldrepublicwizard May 28, 2026
a42eb20
feat(ci): mirror briefing stderr from top-level status (plan 173)
oldrepublicwizard May 28, 2026
7b59b3b
feat(ci): mirror wait_recommended and ci_drift to top-level status
oldrepublicwizard May 28, 2026
1d66b3b
feat(ci): emit wait and drift_fields in shared mirror stderr
oldrepublicwizard May 28, 2026
d9e1f4e
refactor(ci): extract shared lfg flat field mirror helper
oldrepublicwizard May 28, 2026
fad79d1
feat(ci): export lfg_flat_field_keys in gate JSON
oldrepublicwizard May 28, 2026
b7d453e
feat(ci): add lfg_flat_field_values compact gate snapshot
oldrepublicwizard May 28, 2026
045fbbb
feat(ci): add flat_fields stderr token for poll scans
oldrepublicwizard May 28, 2026
4b58c59
fix(ci): strict-exit stderr when flat fields lack nested briefing
oldrepublicwizard May 28, 2026
5ae5a23
feat(ci): add lfg_flat_field_keys_present to gate JSON
oldrepublicwizard May 28, 2026
6060e61
feat(ci): add flat_keys stderr token for poll diffs
oldrepublicwizard May 28, 2026
9c8a1f2
feat(ci): omit unchanged flat_keys on gate-watch polls
oldrepublicwizard May 28, 2026
88fdf0b
feat(ci): track unchanged_flat_keys_polls in watch summary
oldrepublicwizard May 28, 2026
34e41ee
feat(ci): flat_keys heartbeat on gate-watch polls (plan 185)
oldrepublicwizard May 28, 2026
0b4ba2b
refactor(ci): relocate _mirror_lfg_flat_fields helper (plan 186)
oldrepublicwizard May 28, 2026
f226092
refactor(ci): relocate preflight watch summary mirror (plan 187)
oldrepublicwizard May 28, 2026
3f3e74f
feat(ci): gate flat-keys heartbeat summary stderr (plan 188)
oldrepublicwizard May 28, 2026
c9d00fa
feat(ci): emit watch heartbeat interval on preflight summary (plan 189)
oldrepublicwizard May 28, 2026
416f418
feat(ci): flat-field stderr helper and heartbeat_every polls (plan 190)
oldrepublicwizard May 28, 2026
0faafb3
feat(ci): heartbeat_every on preflight summary stderr (plan 191)
oldrepublicwizard May 28, 2026
132e08b
feat(ci): heartbeat_every json alias and flat_hb summary (plan 192)
oldrepublicwizard May 28, 2026
5c6de44
feat(ci): flat_hb poll stderr and json alias (plan 193)
oldrepublicwizard May 28, 2026
547d037
feat(ci): flat_unchanged summary stderr and json alias (plan 194)
oldrepublicwizard May 29, 2026
4e9eea9
feat(ci): use flat_unchanged=1 on gate-watch poll stderr (plan 195)
oldrepublicwizard May 29, 2026
f98ea86
feat(ci): flat_unchanged streak in preflight watch history (plan 196)
oldrepublicwizard May 29, 2026
8dbed9a
feat(ci): max_flat_unchanged on preflight watch summary (plan 197)
oldrepublicwizard May 29, 2026
7841f19
feat(ci): flat_unchanged streak on gate-watch poll stderr (plan 198)
oldrepublicwizard May 29, 2026
fc1da54
feat(verify-pypi): cumulative flat_hb on heartbeat poll stderr (plan …
oldrepublicwizard May 29, 2026
0708e86
feat(verify-pypi): flat_hb_total on watch summary stderr (plan 200)
oldrepublicwizard May 29, 2026
4b0f1b3
feat(verify-pypi): flat_hb_total in watch history snapshots (plan 201)
oldrepublicwizard May 29, 2026
3720105
feat(verify-pypi): flat_hb_total history fallback in watch summary (p…
oldrepublicwizard May 29, 2026
0e5a8ff
refactor(verify-pypi): co-locate preflight watch history helpers (pla…
oldrepublicwizard May 29, 2026
86f1b8f
refactor(verify-pypi): extract preflight poll flat stderr parts (plan…
oldrepublicwizard May 29, 2026
a486c32
refactor(verify-pypi): extract preflight summary flat stderr parts (p…
oldrepublicwizard May 29, 2026
96885a7
feat(verify-pypi): flat_unchanged max-streak summary fallback (plan 206)
oldrepublicwizard May 29, 2026
247004d
refactor(verify-pypi): resolve preflight watch summary counters (plan…
oldrepublicwizard May 29, 2026
e4bf587
refactor(verify-pypi): co-locate preflight flat stderr helpers (plan …
oldrepublicwizard May 29, 2026
4294b18
refactor(verify-pypi): preflight max_flat_unchanged resolver (plan 209)
oldrepublicwizard May 29, 2026
a8d6f31
refactor(verify-pypi): preflight max_flat_unchanged stderr gate (plan…
oldrepublicwizard May 29, 2026
d9950fa
refactor(verify-pypi): preflight flat_hb_total stderr gate (plan 211)
oldrepublicwizard May 29, 2026
5fe832d
refactor(verify-pypi): preflight heartbeat_every stderr gate (plan 212)
oldrepublicwizard May 29, 2026
27cb2ce
refactor(verify-pypi): extract summary unchanged flat stderr parts (p…
May 30, 2026
d84785d
refactor(verify-pypi): extract summary heartbeat flat stderr parts (p…
May 30, 2026
81b7ffd
Add batch PNG texture conversion CLI
Jun 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,365 changes: 1,320 additions & 45 deletions .github/scripts/local_verify_pypi_slice.py

Large diffs are not rendered by default.

23 changes: 21 additions & 2 deletions Libraries/PyKotor/CLI_COMMANDS_REFERENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1016,13 +1016,32 @@ Based on the comprehensive analysis above, PyKotorCLI should support:
- `assemble` - Assemble NSS to NCS (built-in)
- `nwnnsscomp` / `script-compile` - Unified nwnnsscomp.exe-compatible CLI: accepts all variant argument styles (V1, TSLPatcher, KOTOR Tool, KOTOR Scripting Tool); uses built-in compiler/decompiler or optional external exe with correct argv. Implementation and external invocation both rely on [compilers.py](Libraries/PyKotor/src/pykotor/resource/formats/ncs/compilers.py) (`KnownExternalCompilers`, `NwnnsscompConfig`).

### Resource Tools (To Add)
### Resource Tools

- `texture-convert` - Convert textures (TPC↔TGA, etc.)
- `texture-convert` - Convert textures (`.tpc`, `.tga`, `.png`) one file at a time or in batches.
- `sound-convert` - Convert sounds (SSF↔WAV, etc.)
- `model-convert` - Convert models (MDL↔ASCII)
- `walkmesh-rebuild` / `wok-rebuild` - Rebuild BWM derived data (AABB, adjacency, perimeter edges) from geometry

```bash
# Convert edited PNGs back to TGAs for Override. PNG support requires pykotor[textures].
uvx --refresh --with "pykotor[textures]" pykotor texture-convert ./edited_pngs --from-format png --to tga --output ./Override --recursive

# Convert source TGAs to PNGs for AI/image-editor work.
uvx --refresh --with "pykotor[textures]" pykotor texture-convert ./source_tgas --from-format tga --to png --output ./png_work --recursive

# Convert explicit files in place. Defaults: TPC->TGA, TGA->TPC, PNG->TGA.
pykotor texture-convert texture_a.png texture_b.png --overwrite
```

Useful options:

- `--to {tpc,tga,png}` - Force one output format.
- `--from-format {tpc,tga,png}` - Filter directory inputs; repeat for multiple source formats.
- `--output PATH` - Output file for one input, or output directory for multiple inputs.
- `--recursive` - Recurse into input directories and preserve relative paths under the output directory.
- `--overwrite` - Replace existing outputs; otherwise existing batch outputs are skipped.

### Utility Commands (Implemented)

- `diff` - Compare resources
Expand Down
16 changes: 16 additions & 0 deletions Libraries/PyKotor/CLI_QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,22 @@ uvx --refresh pykotor diff --path1 "C:\Games\KOTOR" --path2 "C:\Games\KOTOR_Modd
uvx --refresh pykotor diff --path1 "C:\Games\KOTOR" --path2 "C:\Games\KOTOR_Modded" --tslpatchdata .\tslpatchdata --incremental
```

### 8. Batch texture conversion for AI edit workflows

`texture-convert` accepts one or more files or directories and supports `.tpc`, `.tga`, and `.png`.
PNG support uses Pillow; install the `textures` extra when running from PyPI.

```bash
# Convert final edited PNGs back to TGAs for Override
uvx --refresh --with "pykotor[textures]" pykotor texture-convert ./edited_pngs --from-format png --to tga --output ./Override --recursive

# Convert exported TGAs to PNGs before editing
uvx --refresh --with "pykotor[textures]" pykotor texture-convert ./exported_tgas --from-format tga --to png --output ./png_work --recursive

# Convert a few files in place, using defaults: TPC->TGA, TGA->TPC, PNG->TGA
uvx --refresh --with "pykotor[textures]" pykotor texture-convert texture_a.png texture_b.png --overwrite
```

GUI (omit paths or pass `--gui`):

```bash
Expand Down
19 changes: 18 additions & 1 deletion Libraries/PyKotor/CLI_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ PyKotorCLI is a command-line tool for converting KOTOR modules, ERFs, and haks b
- **Pure Python** - No external tool dependencies required (nwnnsscomp optional)
- **Holocron kit generator** - Generate Holocron-compatible kits via `kit-generate` in headless mode or by launching the Tkinter GUI when no CLI args are provided
- **GUI converter** - Resize KotOR `.gui` layouts to common resolutions (`gui-convert` headless, GUI when arguments are omitted)
- **Batch texture conversion** - Convert `.tpc`, `.tga`, and `.png` files for texture editing workflows (`texture-convert`)
- **Integrated KotorDiff** - Structured comparisons across files, modules, and installations; stays headless when CLI args are provided and launches the KotorDiff GUI when omitted or `--gui` is passed

## Installation
Expand Down Expand Up @@ -126,7 +127,23 @@ Interactive GUI (omit args):
uvx --refresh pykotor gui-convert
```

### 7. Run KotorDiff comparisons (headless or GUI)
### 7. Batch texture conversion

Use `texture-convert` for headless TGA/PNG/TPC conversions. PNG support requires Pillow;
install with `pykotor[textures]` or `pykotor[all]`.

```bash
# AI edit loop: edited PNGs back to game-ready TGAs
uvx --refresh --with "pykotor[textures]" pykotor texture-convert ./edited_pngs --from-format png --to tga --output ./Override --recursive

# Export TGAs to PNGs for editing
uvx --refresh --with "pykotor[textures]" pykotor texture-convert ./exported_tgas --from-format tga --to png --output ./png_work --recursive

# One or more explicit files; defaults are TPC->TGA, TGA->TPC, PNG->TGA
pykotor texture-convert texture_a.png texture_b.png --overwrite
```

### 8. Run KotorDiff comparisons (headless or GUI)

Headless CLI (stays in the console when paths are provided):

Expand Down
7 changes: 6 additions & 1 deletion Libraries/PyKotor/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ readme = "README.md"
requires-python = ">=3.8"

[project.optional-dependencies]
all = ["pykotor[encodings,exp,extra,font,gl,updater]"]
all = ["pykotor[encodings,exp,extra,font,textures,gl,updater]"]
# Development dependencies
dev = [
"astroid>=3.2.0,<3.5.0; python_version<\"3.9\"",
Expand Down Expand Up @@ -127,6 +127,10 @@ font = [
"pillow>=10.0.0,<11; python_version < \"3.10\"",
"pillow>=12.1.1; python_version >= \"3.10\"",
]
textures = [
"pillow>=10.0.0,<11; python_version < \"3.10\"",
"pillow>=12.1.1; python_version >= \"3.10\"",
]
gl = [
"PyGLM>=2.0,<2.9",
"PyOpenGL>=3.1",
Expand Down Expand Up @@ -219,6 +223,7 @@ encodings = ["charset-normalizer"]
exp = ["fusepy", "pywin32"]
extra = ["PyYAML", "Send2Trash", "colorama", "comtypes", "gputil", "psutil"]
font = ["pillow"]
textures = ["pillow"]
gl = ["PyGLM", "PyOpenGL", "numpy"]
gl_exp = ["moderngl"]
updater = ["certifi", "pycryptodome", "requests"]
Expand Down
69 changes: 56 additions & 13 deletions Libraries/PyKotor/src/pykotor/cli/argparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -930,10 +930,41 @@ def create_parser(prog: str | None = None) -> ArgumentParser: # noqa: PLR0915

# Resource tools
texture_parser = subparsers.add_parser(
"texture-convert", help="Convert texture files (TPC<->TGA)"
"texture-convert", help="Convert texture files (TPC/TGA/PNG)"
)
texture_parser.add_argument(
"input",
nargs="+",
help="Input texture file(s) or directory/directories (.tpc, .tga, .png)",
)
texture_parser.add_argument(
"--output",
"-o",
dest="output",
help="Output file for one input, or output directory for multiple inputs",
)
texture_parser.add_argument(
"--to",
choices=["tpc", "tga", "png"],
help="Output format. Defaults: TPC->TGA, TGA->TPC, PNG->TGA",
)
texture_parser.add_argument(
"--from-format",
action="append",
choices=["tpc", "tga", "png"],
help="Only convert inputs with this format. Repeat to include multiple formats.",
)
texture_parser.add_argument(
"--recursive",
"-r",
action="store_true",
help="Recurse into input directories",
)
texture_parser.add_argument(
"--overwrite",
action="store_true",
help="Replace existing outputs during batch conversion",
)
texture_parser.add_argument("input", help="Input texture file (TPC or TGA)")
texture_parser.add_argument("--output", "-o", dest="output", help="Output texture file")
texture_parser.add_argument("--txi", help="TXI file path (for TPC<->TGA conversion)")
texture_parser.add_argument("--format", help="TPC format type (for TGA->TPC)")
texture_parser.add_argument(
Expand Down Expand Up @@ -1198,9 +1229,7 @@ def create_parser(prog: str | None = None) -> ArgumentParser: # noqa: PLR0915
"check-txi", help="Check if TXI files exist for specific textures"
)
check_txi_path_group = check_txi_parser.add_mutually_exclusive_group(required=True)
check_txi_path_group.add_argument(
"--path", "-p", dest="path", help="Path to a game root"
)
check_txi_path_group.add_argument("--path", "-p", dest="path", help="Path to a game root")
check_txi_path_group.add_argument("--installation", "-i", dest="path", help=SUPPRESS)
check_txi_parser.add_argument(
"--textures",
Expand Down Expand Up @@ -1340,11 +1369,15 @@ def create_parser(prog: str | None = None) -> ArgumentParser: # noqa: PLR0915
validate_installation_parser = subparsers.add_parser(
"validate-game-root", aliases=["validate-installation"], help="Validate a KotOR game root"
)
validate_installation_path_group = validate_installation_parser.add_mutually_exclusive_group(required=True)
validate_installation_path_group = validate_installation_parser.add_mutually_exclusive_group(
required=True
)
validate_installation_path_group.add_argument(
"--path", "-p", dest="path", help="Path to a game root"
)
validate_installation_path_group.add_argument("--installation", "-i", dest="path", help=SUPPRESS)
validate_installation_path_group.add_argument(
"--installation", "-i", dest="path", help=SUPPRESS
)
validate_installation_parser.add_argument(
"--check-essential",
action="store_true",
Expand All @@ -1358,7 +1391,9 @@ def create_parser(prog: str | None = None) -> ArgumentParser: # noqa: PLR0915
investigate_module_parser.add_argument(
"--module", "-m", required=True, help="Module name to investigate"
)
investigate_module_path_group = investigate_module_parser.add_mutually_exclusive_group(required=True)
investigate_module_path_group = investigate_module_parser.add_mutually_exclusive_group(
required=True
)
investigate_module_path_group.add_argument(
"--path", "-p", dest="path", help="Path to a game root"
)
Expand All @@ -1374,11 +1409,15 @@ def create_parser(prog: str | None = None) -> ArgumentParser: # noqa: PLR0915
check_missing_resources_parser.add_argument(
"--module", "-m", required=True, help="Module name to check"
)
check_missing_resources_path_group = check_missing_resources_parser.add_mutually_exclusive_group(required=True)
check_missing_resources_path_group = (
check_missing_resources_parser.add_mutually_exclusive_group(required=True)
)
check_missing_resources_path_group.add_argument(
"--path", "-p", dest="path", help="Path to a game root"
)
check_missing_resources_path_group.add_argument("--installation", "-i", dest="path", help=SUPPRESS)
check_missing_resources_path_group.add_argument(
"--installation", "-i", dest="path", help=SUPPRESS
)
check_missing_resources_parser.add_argument(
"--textures", "-t", nargs="+", help="Texture names to check"
)
Expand All @@ -1390,7 +1429,9 @@ def create_parser(prog: str | None = None) -> ArgumentParser: # noqa: PLR0915
"module-resources", help="Get all resources referenced by a module's models"
)
module_resources_parser.add_argument("--module", "-m", required=True, help="Module name")
module_resources_path_group = module_resources_parser.add_mutually_exclusive_group(required=True)
module_resources_path_group = module_resources_parser.add_mutually_exclusive_group(
required=True
)
module_resources_path_group.add_argument(
"--path", "-p", dest="path", help="Path to a game root"
)
Expand Down Expand Up @@ -1607,7 +1648,9 @@ def create_parser(prog: str | None = None) -> ArgumentParser: # noqa: PLR0915
patch_installation_parser = subparsers.add_parser(
"patch-game-root", aliases=["patch-installation"], help="Patch a KotOR game root"
)
patch_installation_path_group = patch_installation_parser.add_mutually_exclusive_group(required=True)
patch_installation_path_group = patch_installation_parser.add_mutually_exclusive_group(
required=True
)
patch_installation_path_group.add_argument(
"--path", "-p", dest="path", help="Path to a game root"
)
Expand Down
Loading
Loading