Reconcile docs with reality; fix module graph, token compare, health #1

Open
kami wants to merge 216 commits from webui-and-audit-reconciliation into master
4 changed files with 29 additions and 11 deletions
Showing only changes of commit de18f372d3 - Show all commits
+16 -7
View File
@@ -58,18 +58,27 @@ func RequestHumanDecision(s *store.Store, project registry.Project, taskID strin
return blockTask(s, t, domain.BlockReasonHumanDecision, req.Render(), &req)
}
// fenceToLease binds a lifecycle event to the lease that is producing it.
// Store.Append fences every lifecycle event on a leased task against the
// current owner and epoch, so an event that omits them is a conflict rather
// than a block. Every coordinator-side stop goes through here: two of them did
// not, and both failed silently against a live lease (F65). A task stops for a
// human only while some session is running, so the leased case is the only one
// that ever mattered.
func fenceToLease(payload map[string]any, t domain.Task) {
if t.Lease == nil {
return
}
payload["harness_id"] = t.Lease.HarnessID
payload["lease_epoch"] = t.Lease.Epoch
}
func blockTask(s *store.Store, t domain.Task, reason domain.BlockReason, blocker string, req *domain.DecisionRequest) (domain.Event, error) {
payload := map[string]any{
"blocker": blocker, "block_reason": string(reason),
"lifecycle_phase": "awaiting_human",
}
if t.Lease != nil {
// Store.Append fences every lifecycle event on a leased task against
// the current owner and epoch. A question from a session that no
// longer owns the task is a conflict, not a block.
payload["harness_id"] = t.Lease.HarnessID
payload["lease_epoch"] = t.Lease.Epoch
}
fenceToLease(payload, t)
if req != nil {
payload["decision_request"] = req
}
+4 -2
View File
@@ -154,11 +154,13 @@ func blockForPlanMismatch(s *store.Store, taskID string, m domain.PlanMismatch)
packet += "- evidence: " + oneLine(e) + "\n"
}
packet += "\nReply to say how to proceed. Your reply becomes a recorded decision and outranks the plan. If it resolves the contradiction, the task resumes on the same plan; say so explicitly if you want the plan rewritten instead.\n"
b, err := json.Marshal(map[string]any{
payload := map[string]any{
"blocker": packet,
"block_reason": string(domain.BlockReasonPlanMismatch),
"lifecycle_phase": "awaiting_human",
})
}
fenceToLease(payload, t)
b, err := json.Marshal(payload)
if err != nil {
return err
}
+5
View File
@@ -28,6 +28,11 @@ func planProject() registry.Project {
func planWith(t *testing.T, markdown string) (*store.Store, registry.Project, string) {
t.Helper()
s, id := phaseStore(t)
// Leased, because everything these tests drive comes from a live implement
// session. Skipping it hid F65: two coordinator-side stops omitted the
// fencing fields Store.Append requires on a leased task, and every test
// passed because no test ever leased one.
lease(t, s, id)
project := planProject()
if _, err := AdvanceWorkPhase(s, project, id, nil); err != nil {
t.Fatal(err)
+4 -2
View File
@@ -67,11 +67,13 @@ func raiseTrajectoryGate(s *store.Store, t domain.Task, from, to domain.WorkPhas
if err != nil {
return err
}
b, err := json.Marshal(map[string]any{
payload := map[string]any{
"blocker": packet,
"block_reason": string(domain.BlockReasonTrajectoryGate),
"lifecycle_phase": "awaiting_human",
})
}
fenceToLease(payload, t)
b, err := json.Marshal(payload)
if err != nil {
return err
}