sow: sovereign-agent-v1-unit9-pulse-proactive-work
project: sovereign-agent
unit: 9
status: AUTHORIZED_ON_MERGE
authority: principal
base_commit: 9fbc8f7e2c55c6949ec1c36238bc46faa35f4f7e
governing_ruling: docs/rulings/2026-08-29-unit9-pulse-is-separate-from-supervisor.md
work_branch: unit-9/pulse-proactive-work
runtime: Python 3.14
runtime_dependencies:
- pydantic
This SOW is the Principal’s implementation direction for Unit 9.
Before implementation begins, file this SOW in the repository, route it through Sparring review, and merge the reviewed text into main. Implementation begins from that resulting exact merged commit—not from the drafting branch and not from 9fbc8f7e if main has advanced.
A changed SOW head invalidates an earlier co-sign. Branch reconciliation must use an allowed, auditable PR-based mechanism; do not substitute a local history rewrite for the denied git rebase, git merge, or force-push mechanisms.
Close the gap between the manually dispatched Unit 5 Store pipeline and the proactive milestone ratified by sequencing amendment 5:
sale
→ durable inventory signal
→ deterministic wake gate
→ genuine durable Pulse event
→ governed replenishment work created without a human prompt
→ Scripted Operator
→ deterministic effect boundary
→ evidence
→ independent review
→ acceptance
Unit 9 builds the first four previously missing links and connects them to the existing governed-work path. It does not replace that path and does not create a second teaching implementation.
Create a distinct Pulse mechanism under the reserved pulse CLI surface.
Do not add Pulse imports, wake-gate reads, work creation, or Pulse event writes to Supervisor.tick(). After Unit 9 lands, these accepted Unit 8 statements must remain literally true:
The supervisor never creates work, never reads a Pulse signal, never fires a wake gate.
A future foreground runtime may call the supervisor and Pulse as two distinct operations. It may not disguise Pulse as a fourth supervisor reconciliation step.
The canonical ledger must answer, with structured columns and enforced relationships:
pulse.* event records that firing?Absence of a CLI invocation, process logs, JSON payload inspection, and absence of a manual-origin row are not proof.
Use explicit equivalents of:
origin_kind
source_signal_id
source_event_id
wake_decision_id
pulse_event_id
sow_id
assignment_id
Existing manual work must migrate to an explicit manual origin. “No Pulse-origin row exists” must never be the definition of manual.
Add one production Pulse mechanism, separate from supervisor.py.
Its deterministic one-pass operation must be available through:
sovereign-agent pulse --once --root ORGANIZATION_ROOT
Exact supporting flags may be added only when needed for durable configuration or unambiguous actor selection. The command must not ask the user to author or dispatch a SOW.
A pass must:
Organization.run_assignment() path for a newly created or safely resumable CREATED assignment.The Scripted provider remains the offline proof provider. Do not introduce a provider-specific execution fork.
For this unit, a qualifying trigger is a genuine sale-origin inventory.changed signal whose subject is currently below its reorder point and can be mapped unambiguously to an active governed outcome.
The gate must fail closed when:
A non-qualifying pass creates no SOW, assignment, origin row, or pulse.* event.
The existing below_reorder() behavior is inherited. Do not create a second reorder calculation that can drift from it.
The wake decision, Pulse event, SOW, assignment, and origin links must become durable atomically.
Refactor existing Organization construction/state-transition helpers if necessary so manual and Pulse creation share production logic. Do not copy create_sow(), ready_sow(), or assign() into a teaching or Pulse-only fork.
The transaction must enforce at least:
pulse origin on the created SOW and assignment;Concurrent contenders must either return the same canonical identifiers or report that the canonical work is already running. They must not create parallel work.
Pulse origin cannot safely reference a source row that later disappears through INSERT OR REPLACE.
Make committed sale signals stable enough to be referenced durably. A later sale that reaches the same inventory level must not replace or rewrite the earlier signal that already caused work. Preserve existing Unit 2–6 transaction guarantees: the sale, cash movement, inventory mutation, signal, and sale.committed event remain one atomic transaction.
Any migration of existing signal data must preserve all valid rows and fail closed—without stamping the migration—if a required relationship cannot be reconstructed honestly.
The same qualifying signal must resolve to the same canonical work under:
RUNNING;Required behavior:
| Canonical assignment state | Pulse replay behavior |
|---|---|
CREATED |
May invoke that same assignment; never create another |
RUNNING |
Report existing work; do not bypass Unit 8 fencing |
COMPLETED |
Return the existing result; do not invoke again |
BLOCKED / FAILED |
Preserve the canonical failure; do not guess success or silently create a replacement |
Recovery or reassignment after a failed execution continues through the existing governed state machine. Pulse does not invent an automatic retry policy.
Unit 9 may introduce genuine pulse.* event kinds, emitted only by the production Pulse mechanism after the wake gate fires.
Tests must not manufacture Pulse success by calling append_event("pulse.…"), inserting a Pulse event directly, or preloading a classified Pulse result. They must cause the real sale, real signal, real gate, and real creation transaction to run.
Outside that mechanism, the source tree remains Pulse-clean.
Add an offline reference scenario proving the complete proactive slice:
plan or run command.Organization.run_assignment().apply_restock() boundary.ACCEPTED and the attribution chain remains queryable afterward.Pulse must not itself impersonate Sparring or the Principal. The reference scenario may drive the already-existing simulated teaching actors, as the current Store demo does.
Ship a new forward-only migration after migration 14.
The exact table names may differ, but the resulting schema must expose equivalent indexed facts:
| Fact | Required enforcement |
|---|---|
| Manual or Pulse origin | Non-null structured value |
| Source signal | Foreign key or equally strong enforced reference |
| Source committed event | Foreign key to events |
| Wake decision | Stable unique identifier |
| Pulse event | Unique reference to a genuine pulse.* event |
| Created SOW | Unique foreign key |
| Created assignment | Unique foreign key |
| Replay key | Unique at the database boundary |
Pulse attribution is proof-bearing. Its canonical relation must be append-only and receive update, delete, and replace guards in the migration that introduces it. Do not edit a previously applied migration.
Add migration tests for:
At minimum, tests must establish all neighboring cases below.
| Property | Required cases |
|---|---|
| Separate mechanism | pulse --once works; Supervisor.tick() still creates no work and emits no Pulse event |
| No creation from nothing | Empty organization; seeded Store with no sale; sale remaining above reorder |
| Qualification | Real sale crossing the threshold creates canonical proactive work |
| Current-state check | A formerly qualifying signal does not create work after the condition is already resolved |
| Attribution | Structured query walks source event → signal → decision → Pulse event → SOW → assignment |
| Manual attribution | Existing and newly created manual work says manual explicitly |
| Replay | Same-process replay returns the same identifiers and counts remain one |
| Restart | Reopen the database and replay; counts and identifiers remain one |
| Concurrency | Two real processes evaluate the same signal; one canonical creation, at most one provider invocation |
| Crash window | Canonical CREATED work survives restart and resumes without duplication |
| Existing RUNNING work | Pulse does not bypass actor leases or execution-attempt fencing |
| Terminal work | Completed, blocked, and failed canonical assignments are not rerun or replaced |
| Source integrity | Missing, mismatched, or fabricated source relationships fail closed |
| Ledger integrity | FK, unique, append-only, and record/column disagreement tests |
| Recurrence | A later genuine sale reaching a previously seen inventory level retains the old signal and can create distinct new work |
| Real mechanism | No test fabricates a pulse.* event or injects a pre-classified wake result |
| Full teaching slice | Real Pulse-created Scripted work reaches verified, reviewed, truthful acceptance |
| CLI artifact | Built wheel runs pulse --once outside the repository |
For every central property, falsify the implementation deliberately and assert that the named test becomes red. Confirm the mutation actually changed the intended bytes before interpreting the result. Restore byte-identically and rerun.
The concurrency proof must use separate database connections and real processes. A pair of mocks calling the same helper does not prove the SQLite uniqueness boundary.
Add:
docs/v1-unit9-pulse-proactive-work.md
It begins as PROPOSED and must state:
Update:
CHANGELOG.md;Do not perform Unit 10’s editorial completion of Chapters 0–7. If a learner-facing exercise is added, it must import and execute the production Pulse mechanism rather than contain a teaching fork.
Do not:
Supervisor.tick();The nine credentialed provider tests remain deselected and explicitly deferred to Unit 12.
The accepted Unit 8 baseline is:
26 / 40 modules
5473 / 6000 nonblank source lines
7 / 30 root exports
runtime dependencies: exactly pydantic
Those gates remain binding. Unit 9 has only 527 nonblank production lines of headroom. Prefer a small Pulse component, a shared transactional helper, and a Store-specific gate over parallel abstractions.
If the truthful implementation cannot fit, stop and request a budget ruling. Do not compress correctness into opaque code merely to pass the number, and do not silently raise the budget.
Run at the exact implementation head:
uv lock --check
make verify
python scripts/verify_curriculum.py
git diff --check
Also build and install the wheel into a clean Python 3.14 environment outside the source tree, then run:
sovereign-agent --help
sovereign-agent doctor
sovereign-agent pulse --once --root /tmp/sovereign-agent-unit9
The full default test suite must pass twice consecutively. Live-provider tests remain deselected and must be reported as unrun.
unit-9/pulse-proactive-work; it does not open or merge its own PR.Master independently mutation-checks at least:
Supervisor.tick().CHANGES_REQUESTED.main from a clean clone.docs/v1-unit9-pulse-proactive-work.md against merged behavior.ACCEPTED only in a separate, reviewed change.If main advances, reconcile through an auditable PR-based path and rerun gates and review on the resulting exact head. A prior co-sign does not survive a head change.
Unit 9 is accepted only when the Principal can inspect the merged ledger and prove:
Proceed first by filing and reviewing this SOW. Do not begin implementation before it is merged unchanged or a subsequent Principal ruling amends it.