CB-WP-0007 T01+T03: window the metric, budget it, cap meta at 25%
Scope cut first, on the maintainer's decision after a spend review: the project is 38% product / 62% loop-meta, cost per response is 2.9x worse than its best window, and INTENT stage 0 still lacks a CLI player and bots. CB-WP-0005 and CB-WP-0006 cost ~$74 — 31% of all spend — for zero measured efficiency gain. T02 and T04 are cancelled unstarted. T01: SH-1/SH-2/SH-3 now report over the window since the last commit, and the cumulative figure is retained but labelled "history, NOT the metric". The prediction held decisively — window 655,744 mean context against cumulative 255,307, a 2.6x gap against a 20% refutation threshold. A cumulative mean over 1,094 responses cannot detect a worsening trend because the history outvotes the present. T03: `make shape-budget`, modelled on CB-01/CB-02. Soft thresholds are the existing SessionShape targets; hard is 1.5x, set before the next measurement per §Step 4. Deliberately not in `make all` — failing the build on context would block committing, and committing is what closes the attribution window and is the natural point to compact, so a gate that blocks the remedy is a trap. It fires HARD on its first run: 656,574 against a 300,000 ceiling. InnerLoop v1.5 establishes the soft 25% meta budget. Workplans declare kind: product|meta|mixed and `make status` reports the share; mixed splits 50/50 and says so. Soft on purpose — a task already started may be finished, because stopping mid-task to satisfy a ratio wastes the work. What it forbids is opening new meta work above the line. A pass that exceeds it must say so in its evidence and name the product work displaced. First reading: 68% OVER, of $74.22 attributed. Product reads $0.00 because the only product workplan, CB-WP-0001, predates qualified task ids and its bare T## labels collide across passes — stated in the output rather than papered over. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
98e09c4394
commit
b79ea9690d
11 changed files with 229 additions and 26 deletions
|
|
@ -48,6 +48,7 @@ def parse_workplan(path):
|
|||
m = re.search(rf'^{key}:\s*"?(.*?)"?\s*$', text, re.M)
|
||||
return m.group(1) if m else None
|
||||
|
||||
kind = fm("kind") or "untagged"
|
||||
tasks = []
|
||||
for m in re.finditer(r"```task\n(.*?)```", text, re.S):
|
||||
body = m.group(1)
|
||||
|
|
@ -57,7 +58,7 @@ def parse_workplan(path):
|
|||
return mm.group(1) if mm else None
|
||||
|
||||
tasks.append((f("id"), f("status"), f("priority")))
|
||||
return fm("id"), fm("title"), fm("status"), tasks
|
||||
return fm("id"), fm("title"), fm("status"), tasks, kind
|
||||
|
||||
|
||||
def workplans():
|
||||
|
|
@ -69,7 +70,7 @@ def workplans():
|
|||
|
||||
def next_task(plans):
|
||||
"""First todo task of the first non-done workplan, with its heading."""
|
||||
for wid, _title, status, tasks in plans:
|
||||
for wid, _title, status, tasks, _kind in plans:
|
||||
if status == "done":
|
||||
continue
|
||||
for tid, tstatus, prio in tasks:
|
||||
|
|
@ -130,7 +131,7 @@ def report():
|
|||
+ (f" ({len(dirty)} uncommitted)" if dirty else " (clean)"))
|
||||
|
||||
print("\n workplans")
|
||||
for wid, title, status, tasks in plans:
|
||||
for wid, title, status, tasks, _kind in plans:
|
||||
done = sum(1 for _, s, _ in tasks if s == "done")
|
||||
if status == "done" and done == len(tasks):
|
||||
print(f" {wid} {status:<12} {done}/{len(tasks)}")
|
||||
|
|
@ -161,6 +162,34 @@ def report():
|
|||
except Exception as e:
|
||||
print(f" UNAVAILABLE — {e}")
|
||||
|
||||
# InnerLoop v1.5 — soft 25% meta budget. Reported, never gated.
|
||||
try:
|
||||
_, _, mod = cost_lines()
|
||||
rep = mod.collect("-home-worsch-clay-borg", None)
|
||||
detail = rep["by_task_detail"]
|
||||
by_kind = {"product": 0.0, "meta": 0.0, "mixed": 0.0}
|
||||
attributed = 0.0
|
||||
for wid, _t, _s, tasks, kind in plans:
|
||||
for tid, _ts, _p in tasks:
|
||||
d = detail.get(tid)
|
||||
if d and kind in by_kind:
|
||||
by_kind[kind] += d["cost"]
|
||||
attributed += d["cost"]
|
||||
if attributed > 0:
|
||||
# `mixed` splits evenly; stated rather than hidden.
|
||||
meta = by_kind["meta"] + by_kind["mixed"] / 2
|
||||
share = 100 * meta / attributed
|
||||
mark = "ok " if share <= 25 else "OVER"
|
||||
print(f"\n meta budget [{mark}] {share:.0f}% of "
|
||||
f"${attributed:,.2f} attributed (soft 25%, InnerLoop v1.5)")
|
||||
print(f" product ${by_kind['product']:,.2f} "
|
||||
f"meta ${by_kind['meta']:,.2f} "
|
||||
f"mixed ${by_kind['mixed']:,.2f} (split 50/50)")
|
||||
print(" NOTE: attributed tasks only — early workplans used bare")
|
||||
print(" T## ids that collide across passes and are excluded.")
|
||||
except Exception as e:
|
||||
print(f"\n meta budget UNAVAILABLE — {e}")
|
||||
|
||||
print("\n fast gates")
|
||||
code, out = run_tool("loop-lint.py")
|
||||
last = out.splitlines()[-1] if out else "?"
|
||||
|
|
@ -209,18 +238,18 @@ def self_test():
|
|||
fh.write(sample)
|
||||
tmp = fh.name
|
||||
try:
|
||||
wid, title, status, tasks = parse_workplan(tmp)
|
||||
wid, title, status, tasks, _kind = parse_workplan(tmp)
|
||||
check("workplan frontmatter parses", (wid, title, status)
|
||||
== ("CB-WP-0009", "Sample", "in_progress"), f"{wid} {status}")
|
||||
check("both task blocks parse with status and priority",
|
||||
tasks == [("CB-WP-0009-T01", "done", "high"),
|
||||
("CB-WP-0009-T02", "todo", "medium")])
|
||||
check("next task is the first todo, not the first task",
|
||||
next_task([(wid, title, status, tasks)])
|
||||
next_task([(wid, title, status, tasks, "meta")])
|
||||
== ("CB-WP-0009", "CB-WP-0009-T02", "medium"))
|
||||
check("a fully-done workplan yields no next task",
|
||||
next_task([("X", "t", "done",
|
||||
[("X-T01", "done", "high")])]) is None)
|
||||
[("X-T01", "done", "high")], "meta")]) is None)
|
||||
finally:
|
||||
os.unlink(tmp)
|
||||
|
||||
|
|
@ -232,9 +261,14 @@ def self_test():
|
|||
sum(len(t) for *_, t in plans) >= 20,
|
||||
f"{sum(len(t) for *_, t in plans)} task(s)")
|
||||
check("every real workplan has an id and a status",
|
||||
all(w and s for w, _, s, _ in plans))
|
||||
all(w and s for w, _, s, _, _ in plans))
|
||||
# InnerLoop v1.5: the meta budget needs every workplan classified, or
|
||||
# the ratio is computed over an unknown denominator.
|
||||
check("every workplan declares kind: product|meta|mixed",
|
||||
all(k in ("product", "meta", "mixed") for *_, k in plans),
|
||||
", ".join(f"{w}={k}" for w, *_, k in plans))
|
||||
check("every real task has an id and a status",
|
||||
all(i and s for *_, ts in plans for i, s, _ in ts))
|
||||
all(i and s for _, _, _, ts, _ in plans for i, s, _ in ts))
|
||||
|
||||
# A heading must be one line. The first version used a dot-all match
|
||||
# and returned the prose of the preceding task as the heading.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue