From 0d2e5a592f619fbc4bfa974b2c85cd5f4931be1f Mon Sep 17 00:00:00 2001 From: Torres Date: Fri, 13 Nov 2026 13:39:22 -0400 Subject: [PATCH] =?UTF-8?q?feat(v1.1):=20item=206=20=E2=80=94=20dry-catalo?= =?UTF-8?q?g=20messaging=20(forged=20batches=20with=200=20fresh=20are=20la?= =?UTF-8?q?beled)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit section_state now mirrors the composed recipe at body.recipe; the forge note appends 'catalog fully reviewed' when the batch has zero fresh cards. The FE shows the BACKLOG sentence in the report (dryCap) and in the forge status line whenever recipe.new===0 with cards served; a non-dry forge behaves exactly as before. No new fetch loops. --- app/api.py | 5 +++++ app/static/index.html | 16 ++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/app/api.py b/app/api.py index d52da43..91133c8 100644 --- a/app/api.py +++ b/app/api.py @@ -530,6 +530,11 @@ def create_app(db_path, img_dir, state_dir=None): conn, engine, size=size, profile_version=prof['version'] if prof else None, note=note) + # v1.1 item 6: label the dry-catalog state on the forge note + recipe = (json.loads(newsec['recipe']) + if newsec['recipe'] else {}) + if recipe.get('new') == 0: + note = '%s · catalog fully reviewed' % (note or '') return section_state(conn, newsec, note=note) finally: conn.close() diff --git a/app/static/index.html b/app/static/index.html index bf370bb..01bd9ca 100644 --- a/app/static/index.html +++ b/app/static/index.html @@ -219,6 +219,7 @@ nav{height:calc(68px + env(safe-area-inset-bottom,0px));display:flex;align-items
+
on demand⇄strict @@ -1191,6 +1192,8 @@ function paintMode(){ } function updateSectionUI(body){ sectTotal=body.progress.total; + // item 6: the dry-catalog caption rides every hydrate (legacy API -> absent) + $('dryCap').style.display= dryLabel(body)?'':'none'; let decided=0; for(const it of (body.items||[])){ const local=localDecisions.get(it.id); @@ -1231,6 +1234,13 @@ async function setRubricDebug(m){ } $('tRubOff').onclick=()=>setRubricDebug('off'); $('tRubOn').onclick=()=>setRubricDebug('on'); +/* item 6: dry catalog — a forged batch with zero fresh cards is labeled, + never silent (BACKLOG "Dry-catalog messaging"). */ +const DRY_MSG='Catalog fully reviewed — fresh listings arrive with the next 08:30 import; showing second looks'; +function dryLabel(body){ + return !!(body && body.recipe && body.recipe.new===0 + && body.items && body.items.length>0); +} $('btnForge').onclick=async()=>{ if(forgeBusy||!section) return; forgeBusy=true; @@ -1240,8 +1250,10 @@ $('btnForge').onclick=async()=>{ const res=await fetch('/api/section/forge',{method:'POST',headers:{'Content-Type':'application/json'},body:'{}'}); const body=await res.json(); if(res.ok){ - $('forgeStatus').textContent= body.note&&body.note.indexOf('fallback')>=0 - ?'Agent offline — forging on the last read.':''; + $('forgeStatus').textContent= dryLabel(body) + ?DRY_MSG + :(body.note&&body.note.indexOf('fallback')>=0 + ?'Agent offline — forging on the last read.':''); section=body; buffer.length=0; const live=new Set([...pile.map(c=>c.d.id),...hist.map(h=>h.id)]);