@walwal-harness/cli 7.1.55 → 7.1.56
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.
- package/CHANGELOG.md +5 -0
- package/package.json +1 -1
- package/scripts/harness-company-complete.sh +24 -0
package/CHANGELOG.md
CHANGED
|
@@ -31,6 +31,11 @@ docmeta:
|
|
|
31
31
|
|
|
32
32
|
## Unreleased
|
|
33
33
|
|
|
34
|
+
## 7.1.56 — Close the lessons-gate bypass at the terminal transition (2026-09-01)
|
|
35
|
+
- **Fix: the Hard Rule 20 gate could be bypassed by firing the completion transition.** Found by an A/B sandbox test of 7.1.54 vs 7.1.55 running identical fixtures. 7.1.55 put the gate in `harness-stop.sh` only, but `harness-company-complete.sh` sets `conductor.state=completed`, and `harness-stop.sh` short-circuits on that state at the top of the file — so a mission could complete having never recorded what it read, simply by running the transition. That is precisely the failure the gate was written to prevent. `harness-company-complete.sh` now runs `harness-lessons-gate.sh` itself and refuses the transition (non-zero exit, runtime left in `running`, refusal logged to `progress.log`) when the active mission's role documents lack `## Lessons Preflight` / `## Lessons Tally`.
|
|
36
|
+
- Deadlock-safe by construction, verified against every legitimate stop path: the gate is scoped to the latest **active** mission, so the Stop-hook auto-complete backstop — which fires only when no mission is active — always passes; and `harness-company-block.sh` (external-authority BLOCKED) is deliberately **not** gated, since a mission blocked on a missing credential must still be able to stop.
|
|
37
|
+
- Two escape hatches: `HARNESS_SKIP_LESSONS_GATE=1` for a single call, and `behavior.lessons_gate:false` for a project that has not adopted the sections.
|
|
38
|
+
|
|
34
39
|
## 7.1.55 — Read before plan: lessons-before-planning ordering + Stop-hook gate (2026-09-01)
|
|
35
40
|
- **Hard Rule 20 — Lessons precede planning.** `AGENTS.md` now carries an *ordering* rule, not another content artifact: before any source edit, any measurement, and before any brief is issued, every CXX and every hired worker reads `.harness/conventions/{shared,role}.md` + `.harness/gotchas/{shared,role}.md`, follows only the topic links those files name, and writes `## Lessons Preflight` (which items apply and why). Every `ceo.md`, `{cxx}.md`, and worker report closes with a one-line `## Lessons Tally` immediately above `## Implementation Notes`; **`0 fired` is valid and must be stated, not omitted** — a tally that only ever reports hits trains agents to manufacture them. The rule also states the propagation clause: a requirement placed on a CXX that its workers must also satisfy is inserted **verbatim** into the worker brief, because *a rule stated one layer above the layer that executes it does not apply*. Origin: a 24h autonomous run in which the company kept re-learning lessons it had already written down — index compliance was already perfect (40 gotchas, 0 orphans, all linked), and the knowledge still arrived after the mistake. **Deliberately not shipped: the distilled 28-item preflight file** that run also produced — a derived corpus must be re-synced whenever any source file changes, went factually stale within an hour, and would be a second thing nobody reads before planning.
|
|
36
41
|
- **Hard Rule 21 — every worker spawn declares its model.** Never inherit the CLI default. The model is recorded in the brief, the Worker Evidence Manifest, and `progress.json company_state.workers[]`. A worker terminated by a usage limit is indistinguishable, from the outside, from a worker that finished, so **a silent or truncated worker is a rate limit until proven otherwise**. `scripts/harness-worker-dispatch.sh` now resolves an explicit model (`company_mode.worker_model` → `flow.team.{gen,eval}_model` → `opus`), passes `--model` on every `claude -p` spawn form, and records it in the queue, the dispatch record, and `progress.log`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walwal-harness/cli",
|
|
3
|
-
"version": "7.1.
|
|
3
|
+
"version": "7.1.56",
|
|
4
4
|
"description": "Company-style AI agent harness for Claude and Codex. Installs commands, CXX agents, skills, HR-Resource hiring pool, and project-local .harness runtime state.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"walwal-harness": "bin/init.js"
|
|
@@ -25,6 +25,30 @@ command -v jq >/dev/null 2>&1 || {
|
|
|
25
25
|
exit 1
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
# Lessons-before-plan gate (AGENTS.md Hard Rule 20). The Stop hook cannot see
|
|
29
|
+
# this path: once this script sets conductor.state=completed, harness-stop.sh
|
|
30
|
+
# short-circuits at the top, so a mission could complete having never read the
|
|
31
|
+
# corpus simply by firing the transition. Refuse the terminal transition here —
|
|
32
|
+
# this is the transition P6 names, and it is the last point at which refusing
|
|
33
|
+
# still means anything.
|
|
34
|
+
#
|
|
35
|
+
# Safe against deadlock: the gate is scoped to the latest ACTIVE mission, so the
|
|
36
|
+
# stop-hook backstop (which fires only when no mission is active) always passes.
|
|
37
|
+
# Opt out per project with .harness/config.json behavior.lessons_gate=false, or
|
|
38
|
+
# override a single call with HARNESS_SKIP_LESSONS_GATE=1.
|
|
39
|
+
if [ "${HARNESS_SKIP_LESSONS_GATE:-0}" != "1" ] && [ -x "$SCRIPT_DIR/harness-lessons-gate.sh" ]; then
|
|
40
|
+
if ! gate_out="$(bash "$SCRIPT_DIR/harness-lessons-gate.sh" "$PROJECT_ROOT" text latest-active 2>/dev/null)"; then
|
|
41
|
+
{
|
|
42
|
+
echo "[company-complete] REFUSED: the active mission has not recorded what it read before planning."
|
|
43
|
+
echo "$gate_out"
|
|
44
|
+
echo " Add the two sections to each role document, then re-run this transition."
|
|
45
|
+
echo " (override: HARNESS_SKIP_LESSONS_GATE=1, or behavior.lessons_gate=false in .harness/config.json)"
|
|
46
|
+
} >&2
|
|
47
|
+
echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) | company-complete | refused | lessons-gate (Hard Rule 20)" >> "$PROJECT_ROOT/.harness/progress.log" 2>/dev/null || true
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
fi
|
|
51
|
+
|
|
28
52
|
state_mtime() {
|
|
29
53
|
stat -f %m "$1" 2>/dev/null || stat -c %Y "$1" 2>/dev/null || echo 0
|
|
30
54
|
}
|