mirror of
https://github.com/boshu2/agentops.git
synced 2026-09-14 15:08:13 +08:00
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:
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
|
||||
Reference in New Issue
Block a user