← back to Chief Of Operations
add continuous DW-priority ticket supervision
dd5f1884faf3fed801e1379be12192233b0d7392 · 2026-09-17 08:58:17 -0700 · Steve Abrams
Files touched
M README.mdM chief_ops.pyA supervisor_loop.sh
Diff
commit dd5f1884faf3fed801e1379be12192233b0d7392
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 17 08:58:17 2026 -0700
add continuous DW-priority ticket supervision
---
README.md | 8 ++++++++
chief_ops.py | 32 +++++++++++++++++++++++++++++++-
supervisor_loop.sh | 8 ++++++++
3 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 10c570e..8e2b9fe 100644
--- a/README.md
+++ b/README.md
@@ -11,3 +11,11 @@ It checks the master `dot-screen-router`, the `desktop-dotbar` launch agent and
```
The Arrange action delegates to the existing master router through the desktop bar API. The harness does not delete, publish, or mutate fleet data.
+
+## Continuous ticket supervision
+
+`supervisor_loop.sh` refreshes `state/queue.json` every 60 seconds under launchd (`com.steve.chief-of-operations`). The queue includes open, blocked, and doing tickets, scores Designer Wallcoverings/client-impact work first, and records the next safe step. It does not auto-claim tickets or bypass approval gates.
+
+```sh
+./chief_ops.py queue
+```
diff --git a/chief_ops.py b/chief_ops.py
index 723ca22..3bf4681 100755
--- a/chief_ops.py
+++ b/chief_ops.py
@@ -8,6 +8,8 @@ from pathlib import Path
HOME = Path.home()
ROUTER = HOME / '.claude/skills/dot-screen-router'
DOTBAR = HOME / 'Projects/desktop-dotbar'
+TICKET_LIB = HOME / 'Projects/ticket-system/lib.js'
+STATE = Path(__file__).with_name('state')
STATUS = HOME / '.local/state/abrams-terminal-status/ttys016.json'
TICKET = 'TK-11882-chief-of-operations-harness-for-terminal'
SCREENSHOTS = [HOME/'Desktop/arrange-click-screen1.png', HOME/'Desktop/arrange-click-screen2.png']
@@ -74,6 +76,31 @@ def plannator_state():
except Exception: continue
return {'ok': root.exists(), 'manifest_count': len(files), 'active': active[-20:], 'blocked': blocked[-20:]}
+def ticket_queue(write=False):
+ js = "const l=require(process.argv[1]); console.log(JSON.stringify([...l.tickets().values()].map(t=>({id:t.id,title:t.title,project:t.project,status:t.status,updated_at:t.updated_at,assignee:t.assignee||''}))));"
+ rc,out,err=cmd(['node','-e',js,str(TICKET_LIB)], timeout=12)
+ if rc or not out: return {'ok':False,'error':err or 'ticket ledger unavailable','items':[]}
+ try: rows=json.loads(out)
+ except Exception as e: return {'ok':False,'error':str(e),'items':[]}
+ dw_terms=('designer wallcoverings','designerwallcoverings','dw-commerce','dw-catalog','dw_unified','shopify','wallcovering','wallpaper','vendor','microsite','catalog')
+ client_terms=('client','customer','live','production','revenue','merchant','shopify','storefront')
+ items=[]
+ for t in rows:
+ if t.get('status') not in ('open','blocked','doing'): continue
+ text=(str(t.get('title',''))+' '+str(t.get('project',''))).lower()
+ dw=any(x in text for x in dw_terms); client=any(x in text for x in client_terms)
+ status_score={'blocked':70,'open':60,'doing':35}.get(t.get('status'),0)
+ score=status_score + (100 if dw else 0) + (35 if client else 0)
+ if t.get('status')=='blocked': next_step='review blocker and route the next reversible step'
+ elif t.get('status')=='open': next_step='claim or dispatch through Plannator'
+ else: next_step='verify active work and unblock dependencies'
+ items.append({**t,'score':score,'dw_priority':dw,'client_impact':client,'next_step':next_step})
+ items.sort(key=lambda x:(-x['score'], x.get('updated_at') or ''))
+ result={'ok':True,'generated_at':time.strftime('%Y-%m-%dT%H:%M:%SZ',time.gmtime()),'total':len(items),'dw_count':sum(x['dw_priority'] for x in items),'blocked_count':sum(x['status']=='blocked' for x in items),'items':items[:40]}
+ if write:
+ STATE.mkdir(exist_ok=True); (STATE/'queue.json').write_text(json.dumps(result,indent=2)+'\n')
+ return result
+
def check():
status={}
@@ -93,6 +120,7 @@ def check():
'dotbar_health': http_health(9787),
'plannator_health': http_health(9772),
'plannator_state': plannator_state(),
+ 'ticket_queue': ticket_queue(write=True),
'router_evidence': router_evidence(),
'legacy_conflicts_archived': {'ok': all(x in archived for x in ('arrange','tile-blue-right','tile-green-left')), 'items': archived},
'screenshots': {'ok': all(x['ok'] for x in screenshots), 'items': screenshots},
@@ -114,6 +142,7 @@ class Handler(BaseHTTPRequestHandler):
def log_message(self,*args): pass
def do_GET(self):
if self.path == '/api/check': self.send_json(check()); return
+ if self.path == '/api/queue': self.send_json(ticket_queue(write=True)); return
self.send_response(200); self.send_header('Content-Type','text/html'); self.end_headers(); self.wfile.write(HTML.encode())
def do_POST(self):
if self.path == '/api/arrange': self.send_json(arrange()); return
@@ -122,8 +151,9 @@ class Handler(BaseHTTPRequestHandler):
b=json.dumps(data, indent=2).encode(); self.send_response(200); self.send_header('Content-Type','application/json'); self.send_header('Content-Length',str(len(b))); self.end_headers(); self.wfile.write(b)
def main():
- ap=argparse.ArgumentParser(); ap.add_argument('action', choices=['check','arrange','serve'], nargs='?', default='check'); ap.add_argument('--port',type=int,default=9896); a=ap.parse_args()
+ ap=argparse.ArgumentParser(); ap.add_argument('action', choices=['check','arrange','queue','serve'], nargs='?', default='check'); ap.add_argument('--port',type=int,default=9896); ap.add_argument('--write',action='store_true'); a=ap.parse_args()
if a.action=='check': print(json.dumps(check(), indent=2)); return
if a.action=='arrange': print(json.dumps(arrange(), indent=2)); return
+ if a.action=='queue': print(json.dumps(ticket_queue(write=a.write or True), indent=2)); return
print(f'Chief of Operations on http://127.0.0.1:{a.port}', flush=True); ThreadingHTTPServer(('127.0.0.1',a.port), Handler).serve_forever()
if __name__=='__main__': main()
diff --git a/supervisor_loop.sh b/supervisor_loop.sh
new file mode 100755
index 0000000..6060911
--- /dev/null
+++ b/supervisor_loop.sh
@@ -0,0 +1,8 @@
+#!/usr/bin/env bash
+set -u
+cd "$(dirname "$0")"
+INTERVAL="${CHIEF_OPS_INTERVAL:-60}"
+while true; do
+ ./chief_ops.py queue --write >> state/supervisor.log 2>&1 || true
+ sleep "$INTERVAL"
+done
← 9614de0 classify authenticated health endpoints
·
back to Chief Of Operations
·
report supervisor launchd health 030f843 →