refactor(daemon): rename QueueClaim → QueueLease (soc-5yuy.3, drift #3)

First soc-5yuy child to close. Mechanical rename of `daemon.QueueClaim`
to `daemon.QueueLease` across 108 Go references in 28 files —
cli/internal/daemon (76 refs), cli/cmd/ao (22), cli/internal/rpi
(7), cli/internal/llmwiki (3). Resolves drift #3 from
docs/contracts/ubiquitous-language.md.

Why QueueLease, not QueueClaim:
- `Claim` is the BC2 noun for what the project says publicly
  (e.g., AOP-CLAIM-*, factory-claim-ledger.json).
- The daemon's QueueClaim was semantically a LEASE on a job slot
  with a token + expiration, not a public assertion. The struct
  has fields `ClaimToken`, `LeaseEpoch`, `LeaseExpiresAt` — three
  out of four already named "Lease".
- The name collision tax was real: a fresh contributor reading
  factory-claim-ledger could not tell whether daemon.QueueClaim
  was the same concept.

Audit-then-execute (cycle-125 pattern):
1. Pre-rename audit: counted refs by package (76+22+7+3+5+0).
2. Checked for split-concept surprise (cycle-125 lesson): all 111
   baseline refs are the same concept (no Session-like split).
3. Checked for serialization keys: no `"queue_claim"` JSON tags;
   no string literals containing "QueueClaim".
4. Then bulk sed across 4 Go packages; build clean; vet clean;
   tests pass (daemon 11s, rpi 4s, llmwiki 0.1s, cmd/ao 53s).

Docs updated:
- docs/contracts/ubiquitous-language.md drift #3 resolution
  block, schedule table row, baseline table row, and cycle log
  entry — all reflect "DONE cycle 126" + "0 refs (from 111)".
- docs/plans/2026-05-12-rescope-evolve-and-architecture.md soc-5yuy
  .3 row marked DONE.

soc-5yuy.3 bd closed with reason linking to this commit.

Net delta: 113 insertions, 112 deletions across 28 files. Zero
QueueClaim refs remain in tracked code/docs (testdata excluded —
those are immutable transcript fixtures).

Cycle 126 / soc-5yuy.3 audit-then-execute mode (first real rename
following the audit-then-execute discipline from cycle 125).
This commit is contained in:
Boden Fuller
2026-05-12 20:37:25 -04:00
parent 24a4fe2b35
commit 4c74bc8d4d
28 changed files with 113 additions and 112 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ func (e daemonFakeOpenClawSnapshotExecutor) JobTypes() []daemonpkg.JobType {
return []daemonpkg.JobType{daemonpkg.JobTypeOpenClawSnapshot}
}
func (e daemonFakeOpenClawSnapshotExecutor) RunJob(ctx context.Context, claim daemonpkg.QueueClaim) (daemonpkg.JobExecutionResult, error) {
func (e daemonFakeOpenClawSnapshotExecutor) RunJob(ctx context.Context, claim daemonpkg.QueueLease) (daemonpkg.JobExecutionResult, error) {
if ctx == nil {
ctx = context.Background()
}
+16 -16
View File
@@ -70,7 +70,7 @@ type (
compileProducerState = rpi.CompileProducerState
)
var errQueueClaimConflict = rpi.ErrQueueClaimConflict
var errQueueLeaseConflict = rpi.ErrQueueLeaseConflict
// Loop control constants — canonical definitions live in internal/rpi.
var (
@@ -377,7 +377,7 @@ func resolveLoopGoal(cwd, explicitGoal, nextWorkPath string, cfg rpiLoopSupervis
break
}
if err := markItemConsumed(nextWorkPath, sel.EntryIndex, sel.ItemIndex, queuePreflightConsumedBy); err != nil {
if errors.Is(err, errQueueClaimConflict) {
if errors.Is(err, errQueueLeaseConflict) {
continue
}
return "", nil, loopReturn, fmt.Errorf("consume preflight queue item %q: %w", sel.Item.Title, err)
@@ -652,7 +652,7 @@ func packetIsValidForTarget(packetPath, targetID string) bool {
// success/failure queue marking.
func runCycleWithRetries(ctx context.Context, cwd, goal string, cycle, executedCycles int, nextWorkPath string, sel *queueSelection, explicitGoal string, cfg rpiLoopSupervisorConfig) (loopCycleResult, error) {
if err := claimQueueSelection(nextWorkPath, sel, cycle); err != nil {
if errors.Is(err, errQueueClaimConflict) && explicitGoal == "" {
if errors.Is(err, errQueueLeaseConflict) && explicitGoal == "" {
fmt.Printf("Queue contention for %q; another consumer won the claim. Continuing.\n", goal)
return loopContinue, nil
}
@@ -939,8 +939,8 @@ func ensureQueueItemClaimable(status string, currentClaimedBy *string, claimedBy
return rpi.EnsureQueueItemClaimable(status, currentClaimedBy, claimedBy)
}
func requireQueueClaimOwner(currentClaimedBy *string, expectedClaimedBy string) error {
return rpi.RequireQueueClaimOwner(currentClaimedBy, expectedClaimedBy)
func requireQueueLeaseOwner(currentClaimedBy *string, expectedClaimedBy string) error {
return rpi.RequireQueueLeaseOwner(currentClaimedBy, expectedClaimedBy)
}
// rewriteNextWorkFile rewrites the JSONL file with updated entries applied via
@@ -1075,7 +1075,7 @@ func markItemConsumedOwned(path string, entryIndex int, itemIndex int, consumedB
}
targetFound = true
if len(entry.Items) == 0 && hasLegacyFlatNextWorkItem(*entry) {
if err := requireQueueClaimOwner(entry.ClaimedBy, expectedClaimedBy); err != nil {
if err := requireQueueLeaseOwner(entry.ClaimedBy, expectedClaimedBy); err != nil {
return err
}
entry.Consumed = true
@@ -1088,9 +1088,9 @@ func markItemConsumedOwned(path string, entryIndex int, itemIndex int, consumedB
return nil
}
if itemIndex < 0 || itemIndex >= len(entry.Items) {
return errQueueClaimConflict
return errQueueLeaseConflict
}
if err := requireQueueClaimOwner(entry.Items[itemIndex].ClaimedBy, expectedClaimedBy); err != nil {
if err := requireQueueLeaseOwner(entry.Items[itemIndex].ClaimedBy, expectedClaimedBy); err != nil {
return err
}
entry.Items[itemIndex].Consumed = true
@@ -1107,7 +1107,7 @@ func markItemConsumedOwned(path string, entryIndex int, itemIndex int, consumedB
return err
}
if !targetFound {
return errQueueClaimConflict
return errQueueLeaseConflict
}
return nil
}
@@ -1139,7 +1139,7 @@ func markEntryFailed(path string, entryIndex int) error {
return err
}
if !targetFound {
return errQueueClaimConflict
return errQueueLeaseConflict
}
return nil
}
@@ -1166,7 +1166,7 @@ func markItemClaimed(path string, entryIndex int, itemIndex int, claimedBy strin
return nil
}
if itemIndex < 0 || itemIndex >= len(entry.Items) {
return errQueueClaimConflict
return errQueueLeaseConflict
}
if err := ensureQueueItemClaimable(normalizeClaimStatus(entry.Items[itemIndex].Consumed, entry.Items[itemIndex].ClaimStatus), entry.Items[itemIndex].ClaimedBy, claimedBy); err != nil {
return err
@@ -1182,7 +1182,7 @@ func markItemClaimed(path string, entryIndex int, itemIndex int, claimedBy strin
return err
}
if !targetFound {
return errQueueClaimConflict
return errQueueLeaseConflict
}
return nil
}
@@ -1215,7 +1215,7 @@ func releaseQueueItem(path string, entryIndex int, itemIndex int, failedAt *stri
}
targetFound = true
if len(entry.Items) == 0 && hasLegacyFlatNextWorkItem(*entry) {
if err := requireQueueClaimOwner(entry.ClaimedBy, expectedClaimedBy); err != nil {
if err := requireQueueLeaseOwner(entry.ClaimedBy, expectedClaimedBy); err != nil {
return err
}
entry.ClaimStatus = "available"
@@ -1228,9 +1228,9 @@ func releaseQueueItem(path string, entryIndex int, itemIndex int, failedAt *stri
return nil
}
if itemIndex < 0 || itemIndex >= len(entry.Items) {
return errQueueClaimConflict
return errQueueLeaseConflict
}
if err := requireQueueClaimOwner(entry.Items[itemIndex].ClaimedBy, expectedClaimedBy); err != nil {
if err := requireQueueLeaseOwner(entry.Items[itemIndex].ClaimedBy, expectedClaimedBy); err != nil {
return err
}
entry.Items[itemIndex].ClaimStatus = "available"
@@ -1247,7 +1247,7 @@ func releaseQueueItem(path string, entryIndex int, itemIndex int, failedAt *stri
return err
}
if !targetFound {
return errQueueClaimConflict
return errQueueLeaseConflict
}
return nil
}
+5 -5
View File
@@ -1302,8 +1302,8 @@ func TestMarkItemClaimedConflict(t *testing.T) {
t.Fatalf("first markItemClaimed: %v", err)
}
err := markItemClaimed(path, 0, 0, "loop:cycle-2")
if !errors.Is(err, errQueueClaimConflict) {
t.Fatalf("second markItemClaimed error = %v, want errQueueClaimConflict", err)
if !errors.Is(err, errQueueLeaseConflict) {
t.Fatalf("second markItemClaimed error = %v, want errQueueLeaseConflict", err)
}
claimed := readJSONLEntries(t, path)
@@ -1348,7 +1348,7 @@ func TestMarkItemClaimedConcurrentSingleWinner(t *testing.T) {
switch {
case err == nil:
successes++
case errors.Is(err, errQueueClaimConflict):
case errors.Is(err, errQueueLeaseConflict):
conflicts++
default:
t.Fatalf("unexpected concurrent claim error: %v", err)
@@ -1388,8 +1388,8 @@ func TestMarkItemConsumedOwnedConflict(t *testing.T) {
t.Fatalf("markItemClaimed: %v", err)
}
err := markItemConsumedOwned(path, 0, 0, "ao-rpi-loop", "loop:cycle-2")
if !errors.Is(err, errQueueClaimConflict) {
t.Fatalf("markItemConsumedOwned error = %v, want errQueueClaimConflict", err)
if !errors.Is(err, errQueueLeaseConflict) {
t.Fatalf("markItemConsumedOwned error = %v, want errQueueLeaseConflict", err)
}
claimed := readJSONLEntries(t, path)
+1 -1
View File
@@ -61,7 +61,7 @@ func (e *DreamExecutor) JobTypes() []JobType {
}
// RunJob requires a non-nil ctx; callers passing nil will panic on first use.
func (e *DreamExecutor) RunJob(ctx context.Context, claim QueueClaim) (JobExecutionResult, error) {
func (e *DreamExecutor) RunJob(ctx context.Context, claim QueueLease) (JobExecutionResult, error) {
if claim.Job.JobType != JobTypeDreamRun {
return JobExecutionResult{}, fmt.Errorf("dream executor does not support job type %s", claim.Job.JobType)
}
+1 -1
View File
@@ -195,7 +195,7 @@ func TestDreamExecutor_RejectsSymlinkOutputDir(t *testing.T) {
t.Fatalf("NewDreamExecutor: %v", err)
}
claim := QueueClaim{Job: QueueJobState{
claim := QueueLease{Job: QueueJobState{
JobID: jobSpec.ID,
JobType: jobSpec.Type,
Payload: jobSpec.Payload,
@@ -76,7 +76,7 @@ func (e *FactoryAdmissionExecutor) JobTypes() []JobType {
return []JobType{JobTypeFactoryAdmission, JobTypeFactoryLocalPilot}
}
func (e *FactoryAdmissionExecutor) RunJob(ctx context.Context, claim QueueClaim) (JobExecutionResult, error) {
func (e *FactoryAdmissionExecutor) RunJob(ctx context.Context, claim QueueLease) (JobExecutionResult, error) {
if ctx == nil {
ctx = context.Background()
}
@@ -98,7 +98,7 @@ func (e *FactoryAdmissionExecutor) RunJob(ctx context.Context, claim QueueClaim)
}
}
func (e *FactoryAdmissionExecutor) runAdmission(ctx context.Context, claim QueueClaim, runID string, mode FactoryAdmissionMode, work FactoryWorkOrder, handoff FactoryHandoff) (JobExecutionResult, error) {
func (e *FactoryAdmissionExecutor) runAdmission(ctx context.Context, claim QueueLease, runID string, mode FactoryAdmissionMode, work FactoryWorkOrder, handoff FactoryHandoff) (JobExecutionResult, error) {
queue := NewQueue(e.store, QueueOptions{Actor: e.actor, Now: e.now})
evaluator := FactoryAdmissionEvaluator{
Clock: e.now,
@@ -147,7 +147,7 @@ func (e *FactoryAdmissionExecutor) runAdmission(ctx context.Context, claim Queue
return JobExecutionResult{Artifacts: resultArtifacts}, nil
}
func (e *FactoryAdmissionExecutor) submitRPIHandoff(ctx context.Context, queue *Queue, claim QueueClaim, runID string, work FactoryWorkOrder, handoff FactoryHandoff) (string, error) {
func (e *FactoryAdmissionExecutor) submitRPIHandoff(ctx context.Context, queue *Queue, claim QueueLease, runID string, work FactoryWorkOrder, handoff FactoryHandoff) (string, error) {
if err := ctx.Err(); err != nil {
return "", err
}
@@ -180,7 +180,7 @@ func (e *FactoryAdmissionExecutor) submitRPIHandoff(ctx context.Context, queue *
return submitted.JobID, nil
}
func (e *FactoryAdmissionExecutor) appendAdmissionEvent(queue *Queue, claim QueueClaim, decision FactoryAdmissionDecision, artifacts map[string]string) error {
func (e *FactoryAdmissionExecutor) appendAdmissionEvent(queue *Queue, claim QueueLease, decision FactoryAdmissionDecision, artifacts map[string]string) error {
payload := map[string]any{
"run_id": decision.RunID,
"work_order_id": decision.WorkOrderID,
+21 -21
View File
@@ -64,7 +64,7 @@ type SubmitJobInput struct {
Payload map[string]any
}
type QueueClaim struct {
type QueueLease struct {
Job QueueJobState `json:"job"`
ClaimToken string `json:"claim_token"`
LeaseEpoch int `json:"lease_epoch"`
@@ -238,15 +238,15 @@ func (q *Queue) SubmitJob(input SubmitJobInput, opts QueueMutationOptions) (Queu
return snapshot.jobByID(committed.JobID)
}
func (q *Queue) ClaimNext(actor string, opts QueueMutationOptions) (QueueClaim, error) {
func (q *Queue) ClaimNext(actor string, opts QueueMutationOptions) (QueueLease, error) {
return q.ClaimNextMatching(actor, nil, opts)
}
// ClaimNextMatching claims the next claimable job accepted by match.
func (q *Queue) ClaimNextMatching(actor string, match func(QueueJobState) bool, opts QueueMutationOptions) (QueueClaim, error) {
func (q *Queue) ClaimNextMatching(actor string, match func(QueueJobState) bool, opts QueueMutationOptions) (QueueLease, error) {
snapshot, err := q.Snapshot()
if err != nil {
return QueueClaim{}, err
return QueueLease{}, err
}
for _, job := range snapshot.Jobs {
if !q.isClaimable(job) {
@@ -257,27 +257,27 @@ func (q *Queue) ClaimNextMatching(actor string, match func(QueueJobState) bool,
}
return q.claimJobState(job, actor, opts)
}
return QueueClaim{}, ErrNoClaimableJobs
return QueueLease{}, ErrNoClaimableJobs
}
func (q *Queue) ClaimJob(jobID, actor string, opts QueueMutationOptions) (QueueClaim, error) {
func (q *Queue) ClaimJob(jobID, actor string, opts QueueMutationOptions) (QueueLease, error) {
snapshot, err := q.Snapshot()
if err != nil {
return QueueClaim{}, err
return QueueLease{}, err
}
job, err := snapshot.jobByID(jobID)
if err != nil {
return QueueClaim{}, err
return QueueLease{}, err
}
if isTerminalStatus(job.Status) {
return QueueClaim{}, ErrNoClaimableJobs
return QueueLease{}, ErrNoClaimableJobs
}
// Advisory lock-free lease check; authoritative serialization happens in claimJobState via the ledger append.
if job.Status == JobStatusRunning && !q.jobLeaseExpired(job) {
return QueueClaim{}, ErrJobAlreadyClaimed
return QueueLease{}, ErrJobAlreadyClaimed
}
if !q.isClaimable(job) {
return QueueClaim{}, ErrNoClaimableJobs
return QueueLease{}, ErrNoClaimableJobs
}
return q.claimJobState(job, actor, opts)
}
@@ -435,23 +435,23 @@ func (q *Queue) Snapshot() (QueueSnapshot, error) {
return q.snapshotFromEvents(events)
}
func (q *Queue) claimJobState(job QueueJobState, actor string, opts QueueMutationOptions) (QueueClaim, error) {
func (q *Queue) claimJobState(job QueueJobState, actor string, opts QueueMutationOptions) (QueueLease, error) {
if (job.Status == JobStatusRetryWaiting || job.RetryExhausted) && job.Attempt >= job.MaxAttempts {
if err := q.appendRetryExhausted(job, actor); err != nil {
return QueueClaim{}, err
return QueueLease{}, err
}
return QueueClaim{}, ErrNoClaimableJobs
return QueueLease{}, ErrNoClaimableJobs
}
// Advisory lock-free lease check; the appendLeaseExpired/appendRetryExhausted calls below serialize via the ledger.
if job.Status == JobStatusRunning && q.jobLeaseExpired(job) {
if job.Attempt >= job.MaxAttempts {
if err := q.appendRetryExhausted(job, actor); err != nil {
return QueueClaim{}, err
return QueueLease{}, err
}
return QueueClaim{}, ErrNoClaimableJobs
return QueueLease{}, ErrNoClaimableJobs
}
if err := q.appendLeaseExpired(job, actor); err != nil {
return QueueClaim{}, err
return QueueLease{}, err
}
job.Status = JobStatusRetryWaiting
}
@@ -475,16 +475,16 @@ func (q *Queue) claimJobState(job QueueJobState, actor string, opts QueueMutatio
},
})
if err != nil {
return QueueClaim{}, err
return QueueLease{}, err
}
if _, err := q.appendQueueEvent(event, opts); err != nil {
return QueueClaim{}, err
return QueueLease{}, err
}
updated, err := q.currentJob(job.JobID)
if err != nil {
return QueueClaim{}, err
return QueueLease{}, err
}
return QueueClaim{
return QueueLease{
Job: updated,
ClaimToken: claimToken,
LeaseEpoch: epoch,
+1 -1
View File
@@ -388,7 +388,7 @@ func assertRepeatCancelDoesNotAppend(t *testing.T, queue *Queue, cancelled Cance
}
}
func claimCancelTestJob(t *testing.T, queue *Queue, jobID, actor string) QueueClaim {
func claimCancelTestJob(t *testing.T, queue *Queue, jobID, actor string) QueueLease {
t.Helper()
claim, err := queue.ClaimJob(jobID, actor, QueueMutationOptions{})
if err != nil {
+1 -1
View File
@@ -71,7 +71,7 @@ func (e *PlansProjectionExecutor) JobTypes() []JobType {
// 5. returns artifacts mapping the snapshot path and entry count.
//
// RunJob requires a non-nil ctx; callers passing nil will panic on first use.
func (e *PlansProjectionExecutor) RunJob(ctx context.Context, claim QueueClaim) (JobExecutionResult, error) {
func (e *PlansProjectionExecutor) RunJob(ctx context.Context, claim QueueLease) (JobExecutionResult, error) {
if claim.Job.JobType != JobTypePlansProjection {
return JobExecutionResult{}, fmt.Errorf("plans.projection executor does not support job type %s", claim.Job.JobType)
}
+3 -3
View File
@@ -45,9 +45,9 @@ func (f *fakePlansBdSource) QueryEpics(ctx context.Context, projectID, issuePref
return entries, nil
}
// claimForPlansSpec returns a QueueClaim with the plans.projection spec
// claimForPlansSpec returns a QueueLease with the plans.projection spec
// payload-encoded the same way Queue.SubmitJob does.
func claimForPlansSpec(t *testing.T, jobID string, spec PlansProjectionJobSpec) QueueClaim {
func claimForPlansSpec(t *testing.T, jobID string, spec PlansProjectionJobSpec) QueueLease {
t.Helper()
raw, err := json.Marshal(spec)
if err != nil {
@@ -57,7 +57,7 @@ func claimForPlansSpec(t *testing.T, jobID string, spec PlansProjectionJobSpec)
if err := json.Unmarshal(raw, &payload); err != nil {
t.Fatalf("unmarshal spec: %v", err)
}
return QueueClaim{Job: QueueJobState{
return QueueLease{Job: QueueJobState{
JobID: jobID,
JobType: JobTypePlansProjection,
Payload: payload,
+1 -1
View File
@@ -62,7 +62,7 @@ func (e *RPIJobExecutor) JobTypes() []JobType {
// per-job execution.
//
// RunJob requires a non-nil ctx; callers passing nil will panic on first use.
func (e *RPIJobExecutor) RunJob(ctx context.Context, claim QueueClaim) (JobExecutionResult, error) {
func (e *RPIJobExecutor) RunJob(ctx context.Context, claim QueueLease) (JobExecutionResult, error) {
if !isRPIJobType(claim.Job.JobType) {
return JobExecutionResult{}, fmt.Errorf("rpi executor does not support job type %s", claim.Job.JobType)
}
+4 -4
View File
@@ -70,7 +70,7 @@ func TestRPIJobExecutorRunJobRejectsNonRPIJobType(t *testing.T) {
if err != nil {
t.Fatalf("new executor: %v", err)
}
claim := QueueClaim{Job: QueueJobState{JobID: "job-wiki", JobType: JobTypeWikiForge}}
claim := QueueLease{Job: QueueJobState{JobID: "job-wiki", JobType: JobTypeWikiForge}}
_, runErr := exec.RunJob(context.Background(), claim)
if runErr == nil {
t.Fatal("expected error for non-rpi job type")
@@ -98,7 +98,7 @@ func TestRPIJobExecutorRunJobExecutesPhaseSpec(t *testing.T) {
if err != nil {
t.Fatalf("payload: %v", err)
}
claim := QueueClaim{
claim := QueueLease{
Job: QueueJobState{
JobID: jobSpec.ID,
JobType: jobSpec.Type,
@@ -149,7 +149,7 @@ func TestRPIJobExecutorRunJobPropagatesRunPhaseTimeout(t *testing.T) {
if err != nil {
t.Fatalf("payload: %v", err)
}
_, err = exec.RunJob(context.Background(), QueueClaim{
_, err = exec.RunJob(context.Background(), QueueLease{
Job: QueueJobState{
JobID: jobSpec.ID,
JobType: jobSpec.Type,
@@ -181,7 +181,7 @@ func TestRPIJobExecutorRunJobPropagatesPhaseExecutorError(t *testing.T) {
if err != nil {
t.Fatalf("payload: %v", err)
}
claim := QueueClaim{
claim := QueueLease{
Job: QueueJobState{
JobID: jobSpec.ID,
JobType: jobSpec.Type,
+5 -5
View File
@@ -13,7 +13,7 @@ import (
// RPIRunRequest is the per-job input handed to the runner function injected
// into RPIRunExecutor. It carries the parsed RPIRunJobSpec, the original
// QueueClaim (so the runner can correlate IDs / heartbeat metadata), and the
// QueueLease (so the runner can correlate IDs / heartbeat metadata), and the
// daemon root cwd.
//
// soc-bcrn.3.6 (E3.W4 sub-5a): introduced as part of the in-process executor
@@ -21,7 +21,7 @@ import (
// supplies the runner so the daemon stays free of cmd/ao imports.
type RPIRunRequest struct {
Spec RPIRunJobSpec
Claim QueueClaim
Claim QueueLease
Root string
}
@@ -95,7 +95,7 @@ func (e *RPIRunExecutor) JobTypes() []JobType { return []JobType{JobTypeRPIRun}
// supervisor's terminal record.
//
// RunJob requires a non-nil ctx; callers passing nil receive a Background ctx.
func (e *RPIRunExecutor) RunJob(ctx context.Context, claim QueueClaim) (JobExecutionResult, error) {
func (e *RPIRunExecutor) RunJob(ctx context.Context, claim QueueLease) (JobExecutionResult, error) {
if ctx == nil {
ctx = context.Background()
}
@@ -188,7 +188,7 @@ func (e *RPIRunExecutor) queueOrNil() *Queue {
// callers that only inject a runner). Errors are logged via the queue contract
// but do not fail the job — the runner result is the source of truth for the
// supervisor's terminal-record.
func (e *RPIRunExecutor) emitAgentUpdate(claim QueueClaim, queue *Queue, base LedgerEventInput) {
func (e *RPIRunExecutor) emitAgentUpdate(claim QueueLease, queue *Queue, base LedgerEventInput) {
if e.store == nil || queue == nil {
return
}
@@ -213,7 +213,7 @@ func (e *RPIRunExecutor) emitAgentUpdate(claim QueueClaim, queue *Queue, base Le
// executor_policy="in-process" and backend="in-process" so downstream readers
// can distinguish the new path from the legacy CLI-fallback shell-out during
// the 5a/5b/5c migration.
func rpiRunArtifactsFor(claim QueueClaim, spec RPIRunJobSpec) map[string]string {
func rpiRunArtifactsFor(claim QueueLease, spec RPIRunJobSpec) map[string]string {
runID := sanitizeIDPart(spec.RunID)
if runID == "" {
runID = "unknown-run"
+7 -7
View File
@@ -37,7 +37,7 @@ func TestRPIRunExecutor_RunsViaFunc(t *testing.T) {
if err != nil {
t.Fatalf("job spec: %v", err)
}
claim := QueueClaim{Job: QueueJobState{
claim := QueueLease{Job: QueueJobState{
JobID: jobSpec.ID,
RequestID: "req-rpi-run",
JobType: jobSpec.Type,
@@ -99,7 +99,7 @@ func TestRPIRunExecutor_RejectsWrongJobType(t *testing.T) {
if err != nil {
t.Fatalf("new executor: %v", err)
}
claim := QueueClaim{Job: QueueJobState{JobID: "job-phase", JobType: JobTypeRPIPhase}}
claim := QueueLease{Job: QueueJobState{JobID: "job-phase", JobType: JobTypeRPIPhase}}
_, runErr := exec.RunJob(context.Background(), claim)
if runErr == nil || !strings.Contains(runErr.Error(), "does not support") {
t.Fatalf("RunJob error = %v, want unsupported type", runErr)
@@ -128,7 +128,7 @@ func TestRPIRunExecutor_PropagatesRunnerError(t *testing.T) {
if err != nil {
t.Fatalf("job spec: %v", err)
}
result, runErr := exec.RunJob(context.Background(), QueueClaim{Job: QueueJobState{
result, runErr := exec.RunJob(context.Background(), QueueLease{Job: QueueJobState{
JobID: jobSpec.ID,
JobType: jobSpec.Type,
Payload: jobSpec.Payload,
@@ -165,7 +165,7 @@ func TestRPIRunExecutor_ValidateFullRun(t *testing.T) {
if err != nil {
t.Fatalf("job spec: %v", err)
}
result, runErr := exec.RunJob(context.Background(), QueueClaim{Job: QueueJobState{
result, runErr := exec.RunJob(context.Background(), QueueLease{Job: QueueJobState{
JobID: jobSpec.ID,
JobType: jobSpec.Type,
Payload: jobSpec.Payload,
@@ -284,7 +284,7 @@ func TestRPIRunEmitsAgentUpdates(t *testing.T) {
if err != nil {
t.Fatalf("job spec: %v", err)
}
claim := QueueClaim{Job: QueueJobState{
claim := QueueLease{Job: QueueJobState{
JobID: jobSpec.ID,
RequestID: "req-emit",
JobType: jobSpec.Type,
@@ -398,7 +398,7 @@ func TestRPIRunEmitsCriterionVerdicts(t *testing.T) {
if err != nil {
t.Fatalf("job spec: %v", err)
}
claim := QueueClaim{Job: QueueJobState{
claim := QueueLease{Job: QueueJobState{
JobID: jobSpec.ID,
RequestID: "req-verdicts",
JobType: jobSpec.Type,
@@ -473,7 +473,7 @@ func TestRPIRunNoEmissionWithoutStore(t *testing.T) {
if err != nil {
t.Fatalf("job spec: %v", err)
}
claim := QueueClaim{Job: QueueJobState{JobID: jobSpec.ID, JobType: jobSpec.Type, Payload: jobSpec.Payload}}
claim := QueueLease{Job: QueueJobState{JobID: jobSpec.ID, JobType: jobSpec.Type, Payload: jobSpec.Payload}}
if _, err := exec.RunJob(context.Background(), claim); err != nil {
t.Fatalf("RunJob: %v", err)
}
+11 -11
View File
@@ -177,10 +177,10 @@ func (r *RPIRunner) RunRPIJob(ctx context.Context, jobID string) (RPIJobRunResul
return r.runClaimedJob(ctx, claim)
}
func (r *RPIRunner) claimNextRPIJob() (QueueClaim, error) {
func (r *RPIRunner) claimNextRPIJob() (QueueLease, error) {
snapshot, err := r.queue.Snapshot()
if err != nil {
return QueueClaim{}, err
return QueueLease{}, err
}
for _, job := range snapshot.Jobs {
if !isRPIJobType(job.JobType) {
@@ -191,14 +191,14 @@ func (r *RPIRunner) claimNextRPIJob() (QueueClaim, error) {
continue
}
if err != nil {
return QueueClaim{}, err
return QueueLease{}, err
}
return claim, nil
}
return QueueClaim{}, ErrNoRPIJobs
return QueueLease{}, ErrNoRPIJobs
}
func (r *RPIRunner) runClaimedJob(ctx context.Context, claim QueueClaim) (RPIJobRunResult, error) {
func (r *RPIRunner) runClaimedJob(ctx context.Context, claim QueueLease) (RPIJobRunResult, error) {
_ = r.writeRPIRegistryProjection()
stopHeartbeat := r.startHeartbeat(ctx, claim)
defer stopHeartbeat()
@@ -252,7 +252,7 @@ func (r *RPIRunner) runClaimedJob(ctx context.Context, claim QueueClaim) (RPIJob
// been claimed by some caller (the supervisor's claim path is one such
// caller; the operator-driven `ao rpi run` is another). It does not handle
// claim, heartbeat, or terminal write — those are the caller's responsibility.
func (r *RPIRunner) ExecuteClaim(ctx context.Context, claim QueueClaim) (map[string]string, string, error) {
func (r *RPIRunner) ExecuteClaim(ctx context.Context, claim QueueLease) (map[string]string, string, error) {
switch claim.Job.JobType {
case JobTypeRPIRun:
spec, err := RPIRunJobSpecFromPayload(claim.Job.Payload)
@@ -272,7 +272,7 @@ func (r *RPIRunner) ExecuteClaim(ctx context.Context, claim QueueClaim) (map[str
}
}
func (r *RPIRunner) executeRun(ctx context.Context, claim QueueClaim, spec RPIRunJobSpec) (map[string]string, string, error) {
func (r *RPIRunner) executeRun(ctx context.Context, claim QueueLease, spec RPIRunJobSpec) (map[string]string, string, error) {
artifacts := map[string]string{}
for phase := spec.StartPhase; phase <= spec.MaxPhase; phase++ {
phaseSpec := NewRPIPhaseJobSpec(spec.RunID, spec.Goal, phase)
@@ -295,7 +295,7 @@ func (r *RPIRunner) executeRun(ctx context.Context, claim QueueClaim, spec RPIRu
return artifacts, spec.RunID, nil
}
func (r *RPIRunner) executePhase(ctx context.Context, claim QueueClaim, req RPIPhaseExecutionRequest) (RPIPhaseExecutionResult, error) {
func (r *RPIRunner) executePhase(ctx context.Context, claim QueueLease, req RPIPhaseExecutionRequest) (RPIPhaseExecutionResult, error) {
if strings.TrimSpace(req.Prompt) == "" {
prompt, err := r.promptBuilder.BuildRPIPrompt(req)
if err != nil {
@@ -320,7 +320,7 @@ func (r *RPIRunner) executePhase(ctx context.Context, claim QueueClaim, req RPIP
return result, err
}
func (r *RPIRunner) recordPhaseProgress(claim QueueClaim) RPIPhaseProgressFunc {
func (r *RPIRunner) recordPhaseProgress(claim QueueLease) RPIPhaseProgressFunc {
return func(ctx context.Context, progress RPIPhaseProgress) error {
select {
case <-ctx.Done():
@@ -347,7 +347,7 @@ func (r *RPIRunner) recordPhaseProgress(claim QueueClaim) RPIPhaseProgressFunc {
}
}
func (r *RPIRunner) startHeartbeat(ctx context.Context, claim QueueClaim) func() {
func (r *RPIRunner) startHeartbeat(ctx context.Context, claim QueueLease) func() {
interval := r.heartbeatInterval
if interval <= 0 {
interval = r.queue.opts.LeaseDuration / 2
@@ -884,7 +884,7 @@ func captureGasCityRPIEvidence(ctx context.Context, client GasCityRPIClient, req
return path, nil
}
func requestFromPhaseSpec(root string, claim QueueClaim, spec RPIPhaseJobSpec) RPIPhaseExecutionRequest {
func requestFromPhaseSpec(root string, claim QueueLease, spec RPIPhaseJobSpec) RPIPhaseExecutionRequest {
return RPIPhaseExecutionRequest{
Root: root,
JobID: claim.Job.JobID,
+2 -2
View File
@@ -21,7 +21,7 @@ type SkillInvokeJobSpec struct {
type SkillInvokeRequest struct {
Spec SkillInvokeJobSpec
Claim QueueClaim
Claim QueueLease
Root string
}
@@ -55,7 +55,7 @@ func (e *SkillInvokeExecutor) JobTypes() []JobType {
return []JobType{JobTypeSkillInvoke}
}
func (e *SkillInvokeExecutor) RunJob(ctx context.Context, claim QueueClaim) (JobExecutionResult, error) {
func (e *SkillInvokeExecutor) RunJob(ctx context.Context, claim QueueLease) (JobExecutionResult, error) {
if ctx == nil {
ctx = context.Background()
}
+2 -2
View File
@@ -54,7 +54,7 @@ func TestSkillInvokeExecutorRunsInjectedFunc(t *testing.T) {
if err != nil {
t.Fatalf("ToJobSpec: %v", err)
}
result, err := exec.RunJob(context.Background(), QueueClaim{Job: QueueJobState{
result, err := exec.RunJob(context.Background(), QueueLease{Job: QueueJobState{
JobID: job.ID,
JobType: job.Type,
Payload: job.Payload,
@@ -91,7 +91,7 @@ func TestSkillInvokeExecutorReturnsRunnerErrorWithArtifacts(t *testing.T) {
if err != nil {
t.Fatalf("ToJobSpec: %v", err)
}
result, err := exec.RunJob(context.Background(), QueueClaim{Job: QueueJobState{
result, err := exec.RunJob(context.Background(), QueueLease{Job: QueueJobState{
JobID: job.ID,
JobType: job.Type,
Payload: job.Payload,
+2 -2
View File
@@ -17,7 +17,7 @@ type JobExecutionResult struct {
// JobExecutor runs claimed daemon jobs for one or more job types.
type JobExecutor interface {
JobTypes() []JobType
RunJob(context.Context, QueueClaim) (JobExecutionResult, error)
RunJob(context.Context, QueueLease) (JobExecutionResult, error)
}
// SupervisorOptions configures a daemon queue supervisor.
@@ -178,7 +178,7 @@ func (s *Supervisor) supportsJob(job QueueJobState) bool {
return ok
}
func (s *Supervisor) runExecutorWithHeartbeat(ctx context.Context, executor JobExecutor, claim QueueClaim) (JobExecutionResult, error) {
func (s *Supervisor) runExecutorWithHeartbeat(ctx context.Context, executor JobExecutor, claim QueueLease) (JobExecutionResult, error) {
if ctx == nil {
ctx = context.Background()
}
+3 -3
View File
@@ -224,7 +224,7 @@ func (e testOpenClawSnapshotExecutor) JobTypes() []JobType {
return []JobType{JobTypeOpenClawSnapshot}
}
func (e testOpenClawSnapshotExecutor) RunJob(_ context.Context, claim QueueClaim) (JobExecutionResult, error) {
func (e testOpenClawSnapshotExecutor) RunJob(_ context.Context, claim QueueLease) (JobExecutionResult, error) {
if claim.Job.JobType != JobTypeOpenClawSnapshot {
return JobExecutionResult{}, errors.New("test executor received unsupported job type")
}
@@ -246,7 +246,7 @@ func (e *oneShotOOMExecutor) JobTypes() []JobType {
return []JobType{JobTypeOpenClawSnapshot}
}
func (e *oneShotOOMExecutor) RunJob(_ context.Context, _ QueueClaim) (JobExecutionResult, error) {
func (e *oneShotOOMExecutor) RunJob(_ context.Context, _ QueueLease) (JobExecutionResult, error) {
e.calls++
if e.calls == 1 {
return JobExecutionResult{}, errors.New("worker killed by cgroup memory.max")
@@ -263,7 +263,7 @@ func (e *blockingOpenClawExecutor) JobTypes() []JobType {
return []JobType{JobTypeOpenClawSnapshot}
}
func (e *blockingOpenClawExecutor) RunJob(ctx context.Context, claim QueueClaim) (JobExecutionResult, error) {
func (e *blockingOpenClawExecutor) RunJob(ctx context.Context, claim QueueLease) (JobExecutionResult, error) {
close(e.started)
select {
case <-ctx.Done():
+2 -2
View File
@@ -39,10 +39,10 @@ func (e *WikiForgeExecutor) JobTypes() []JobType {
return []JobType{JobTypeWikiForge}
}
func (e *WikiForgeExecutor) RunJob(ctx context.Context, claim QueueClaim) (JobExecutionResult, error) {
func (e *WikiForgeExecutor) RunJob(ctx context.Context, claim QueueLease) (JobExecutionResult, error) {
// Honor cancellation issued mid-claim before performing any work
// (payload parse, source expansion, or worker spawn). Without this
// check, a context canceled between QueueClaim and execution start
// check, a context canceled between QueueLease and execution start
// is not observed until the underlying call blocks. See bd soc-58q5.12.
if err := ctx.Err(); err != nil {
return JobExecutionResult{}, err
+2 -2
View File
@@ -158,7 +158,7 @@ func TestWikiForgeExecutorInvalidOutputFailsWithQuarantineArtifact(t *testing.T)
// described in bd soc-58q5.12: RunJob must observe context cancellation
// issued mid-claim before doing any work (payload parse, source expansion,
// or worker spawn). Without the early ctx.Err() guard, a cancel issued
// between QueueClaim and execution start is silently ignored until an
// between QueueLease and execution start is silently ignored until an
// underlying call happens to block.
func TestWikiExecutor_RespectsCtxCancelBeforeRun(t *testing.T) {
store := NewStore(t.TempDir())
@@ -178,7 +178,7 @@ func TestWikiExecutor_RespectsCtxCancelBeforeRun(t *testing.T) {
t.Fatalf("NewWikiForgeExecutor: %v", err)
}
claim := QueueClaim{
claim := QueueLease{
Job: QueueJobState{
JobID: jobSpec.ID,
JobType: jobSpec.Type,
+3 -3
View File
@@ -167,7 +167,7 @@ func (r *WikiForgeRunner) RunWikiForgeJob(ctx context.Context, jobID string) (Wi
return r.runClaimedWikiForgeJob(ctx, claim)
}
func (r *WikiForgeRunner) runClaimedWikiForgeJob(ctx context.Context, claim QueueClaim) (WikiForgeJobRunResult, error) {
func (r *WikiForgeRunner) runClaimedWikiForgeJob(ctx context.Context, claim QueueLease) (WikiForgeJobRunResult, error) {
if claim.Job.JobType != JobTypeWikiForge {
return WikiForgeJobRunResult{}, fmt.Errorf("job %s type %s is not %s", claim.Job.JobID, claim.Job.JobType, JobTypeWikiForge)
}
@@ -266,7 +266,7 @@ func (r *WikiForgeRunner) runClaimedWikiForgeJob(ctx context.Context, claim Queu
}, nil
}
func (r *WikiForgeRunner) failWikiForgeJob(claim QueueClaim, failure JobFailure) WikiForgeJobRunResult {
func (r *WikiForgeRunner) failWikiForgeJob(claim QueueLease, failure JobFailure) WikiForgeJobRunResult {
job, err := r.queue.FailJob(FailJobInput{
JobID: claim.Job.JobID,
RequestID: RequestID(claim.Job.RequestID),
@@ -410,7 +410,7 @@ func expandWikiForgeSourcePaths(paths []string) ([]string, error) {
return out, nil
}
func newWikiForgePromptContext(claim QueueClaim, spec WikiForgeJobSpec, sourcePath string) (wikiForgePromptContext, error) {
func newWikiForgePromptContext(claim QueueLease, spec WikiForgeJobSpec, sourcePath string) (wikiForgePromptContext, error) {
sourceBytes, err := os.ReadFile(sourcePath)
if err != nil {
return wikiForgePromptContext{}, fmt.Errorf("read wiki forge source %q: %w", sourcePath, err)
+1 -1
View File
@@ -84,7 +84,7 @@ func (e *LLMWikiLoopExecutor) JobTypes() []daemon.JobType {
// 3. Look up the matching handler. If nil, return a Skipped result.
// 4. Invoke handler.Run with the QueueJobState attempt counter.
// 5. Emit artifacts so the supervisor can record them in the ledger.
func (e *LLMWikiLoopExecutor) RunJob(ctx context.Context, claim daemon.QueueClaim) (daemon.JobExecutionResult, error) {
func (e *LLMWikiLoopExecutor) RunJob(ctx context.Context, claim daemon.QueueLease) (daemon.JobExecutionResult, error) {
if ctx == nil {
ctx = context.Background()
}
+2 -2
View File
@@ -26,8 +26,8 @@ func (f *fakeHandler) Run(_ context.Context, _ string, attempt int) (StageResult
return StageResult{Stage: f.stage, Attempt: attempt}, nil
}
func mkClaim(jobType daemon.JobType, payload map[string]any, attempt int) daemon.QueueClaim {
return daemon.QueueClaim{
func mkClaim(jobType daemon.JobType, payload map[string]any, attempt int) daemon.QueueLease {
return daemon.QueueLease{
Job: daemon.QueueJobState{
JobID: "job-test",
JobType: jobType,
+5 -5
View File
@@ -199,21 +199,21 @@ func EntryConsumedTime(entry *NextWorkEntry) time.Time {
// EnsureQueueItemClaimable checks whether a queue item can be claimed.
func EnsureQueueItemClaimable(status string, currentClaimedBy *string, claimedBy string) error {
if status == "consumed" {
return ErrQueueClaimConflict
return ErrQueueLeaseConflict
}
if status == "in_progress" && (currentClaimedBy == nil || *currentClaimedBy != claimedBy) {
return ErrQueueClaimConflict
return ErrQueueLeaseConflict
}
return nil
}
// RequireQueueClaimOwner verifies the current claim owner matches expected.
func RequireQueueClaimOwner(currentClaimedBy *string, expectedClaimedBy string) error {
// RequireQueueLeaseOwner verifies the current claim owner matches expected.
func RequireQueueLeaseOwner(currentClaimedBy *string, expectedClaimedBy string) error {
if expectedClaimedBy == "" {
return nil
}
if currentClaimedBy == nil || *currentClaimedBy != expectedClaimedBy {
return ErrQueueClaimConflict
return ErrQueueLeaseConflict
}
return nil
}
+2 -2
View File
@@ -6,8 +6,8 @@ import (
"time"
)
// ErrQueueClaimConflict signals that a next-work item is no longer available.
var ErrQueueClaimConflict = errors.New("next-work item no longer available for this consumer")
// ErrQueueLeaseConflict signals that a next-work item is no longer available.
var ErrQueueLeaseConflict = errors.New("next-work item no longer available for this consumer")
const (
// ProviderSessionLost is the normalized RPI/GasCity status when a session
+4 -3
View File
@@ -39,7 +39,7 @@ BC1 is largely drift-free at the aggregate level. The one term to lock: **Contex
**Ranked drift #1 (Gate / Check / Validation / Validator) resolution:** `Gate` is the BC2 aggregate. `Check` is a single invocation of a Gate. `Validator` (where used in Go) is the concrete adapter type — fine to keep but it implements a Gate. The 90 `scripts/check-*.sh` filenames stay (the file name describes the action; the concept inside is the Gate they enforce). The new term in code/docs should be **Gate**.
**Ranked drift #3 (Claim / Assertion / Evidence) resolution:** `Claim` is the BC2 noun for what the project says publicly. `Evidence` is what backs it. `daemon.QueueClaim` (the Go type) is a naming collision and should rename to `QueueLease` (different concept entirely — leasing a job slot, not asserting a public claim).
**Ranked drift #3 (Claim / Assertion / Evidence) resolution:** `Claim` is the BC2 noun for what the project says publicly. `Evidence` is what backs it. `daemon.QueueClaim` (the Go type) was a naming collision (different concept entirely — leasing a job slot, not asserting a public claim) — **renamed to `QueueLease` in cycle 126** (commit ahead, 108 Go refs touched across cli/internal/daemon, cli/internal/rpi, cli/internal/llmwiki, cli/cmd/ao).
### BC3 Loop
@@ -104,7 +104,7 @@ The pinned distinction: **Skill is invokable**, **Pattern is reusable knowledge*
|---|---|---|
| #1 Gate / Check / Validation | Pass through ~90 `check-*.sh` headers; pin `Gate` in Go type renames where applicable | soc-5yuy.1 |
| #2 Cycle / Loop / Iteration / Run | Deprecate `Run` outside Phase context; `lifecycle.CloseLoopIngestResult` keeps "loop" (different concept) | soc-5yuy.2 |
| #3 Claim / Assertion / Evidence | Rename `daemon.QueueClaim` → `QueueLease`; update consumers | soc-5yuy.3 |
| #3 Claim / Assertion / Evidence | ✓ DONE cycle 126: `daemon.QueueClaim` → `QueueLease` (108 refs renamed; consumers updated) | soc-5yuy.3 |
| #4 Skill / Primitive / Pattern / Practice | Audit cross-references in `skills/*/SKILL.md` and `PRACTICE.md`; correct where the wrong term is used | soc-5yuy.4 |
| #5 Session | Rename ambiguous `daemon.Session` types per BC; add canonical `AgentSession` and `OperatorSession` where missing | soc-5yuy.5 |
@@ -138,7 +138,7 @@ soc-5yuy child PR ratchets one of these counts toward 0.
|---|---|---|---|
| #1 Gate / Check / Validation | `script header references "Validator"` outside Go code | ~90 `scripts/check-*.sh` files (filenames stay; headers/docs use "Gate") | `grep -rln 'scripts/check-' scripts/` |
| #2 Cycle / Loop / Iteration / Run | `rpi.Run` callers outside Phase context | _measure on demand_ | `grep -rn 'rpi\.Run\b\|RpiRun\b' cli/` |
| #3 Claim / Assertion / Evidence | `QueueClaim` references | 111 (vs 3 `QueueLease`) | `grep -rn 'QueueClaim' cli/ scripts/ docs/` |
| #3 Claim / Assertion / Evidence | `QueueClaim` references | ✓ 0 (down from 111 at cycle 123 baseline); cycle 126 sed rename + green tests | `grep -rn 'QueueClaim' cli/ scripts/ docs/` |
| #4 Skill / Primitive / Pattern / Practice | mixed terms in `skills/*/SKILL.md` cross-references | _measure on demand_ | (audit per file; no single grep) |
| #5 Session | bare `type Session struct` declarations | 3 (`cli/internal/{search,storage,gascity}/types.go`); refined cycle 125 — these are 3 DIFFERENT concepts (storage/search = TranscriptSession 97 refs; gascity = published-API Session 79 refs, keep as-is) | `grep -rn 'type Session ' cli/` |
@@ -150,3 +150,4 @@ files (`*_test.go`) where Session/Claim mock types are legitimate.
- 2026-05-12 cycle 58: contract written; rename schedule binds soc-5yuy.1–.5 to specific drift resolutions.
- 2026-05-13 cycle 123: added current-drift baseline section so rename PRs have a starting-count to ratchet against. QueueClaim sits at 111 refs (vs 3 QueueLease); `type Session struct` appears in 3 packages.
- 2026-05-13 cycle 125: refined drift #5 — the 3 bare `Session` types are 3 different concepts, not one. Added TranscriptSession (BC1) as missing canonical name. gascity.Session is a published-API surface — rename out of scope; keep + alias-document. storage.Session (93 refs) + search.Session (4 refs) rename to TranscriptSession is the actual soc-5yuy.5 unit; gascity stays.
- 2026-05-13 cycle 126: **drift #3 RESOLVED.** `daemon.QueueClaim` → `QueueLease` rename shipped: 108 Go refs across cli/internal/{daemon,rpi,llmwiki} + cli/cmd/ao. Audit-then-execute: pre-rename audit (cycle-125 pattern) showed no split-concept surprise here — all 111 baseline refs were the same concept, mechanical sed across 4 packages, all package tests green (daemon 11s, rpi 4s, llmwiki 0.1s, cmd/ao 53s). First soc-5yuy child to close.
@@ -108,7 +108,7 @@ Each port becomes one bead. Each bead is sized to land as one operator-shaped co
|---|---|---|---|
| .1 | Gate vs Check vs Validation — pick `Gate` (BC2 aggregate); rename ~90 scripts to use consistent term in headers | NEW | 1-2 cycles |
| .2 | Cycle vs Loop vs Iteration vs Run — pick `Cycle` (BC3 aggregate); deprecate `Run` outside Phase context | NEW | 1 cycle |
| .3 | Claim vs Assertion vs Evidence — rename `daemon.QueueClaim` → `QueueLease` | NEW | 1 cycle |
| .3 | Claim vs Assertion vs Evidence — `daemon.QueueClaim` → `QueueLease` | ✓ DONE cycle 126 (108 Go refs renamed; daemon/rpi/llmwiki/cmd-ao tests green) | 1 cycle |
| .4 | Skill vs Primitive vs Pattern vs Practice — pin definitions per BC | NEW (extends `soc-w6vh.1` practice slug drift) | 1 cycle |
| .5 | Session — scope per BC (`AgentSession` BC5, `OperatorSession` BC5; drop the daemon "session" usage) | NEW | 1 cycle |