Skip to content

[prime-time] Worker applied-keys dedup#79

Merged
rickylabs merged 10 commits into
feat/framework-prime-timefrom
feat/prime-time/worker-applied-keys-dedup
Jun 20, 2026
Merged

[prime-time] Worker applied-keys dedup#79
rickylabs merged 10 commits into
feat/framework-prime-timefrom
feat/prime-time/worker-applied-keys-dedup

Conversation

@rickylabs

Copy link
Copy Markdown
Owner

Blocker slice worker-applied-keys-dedup

Framework prime-time blocker batch — sub-PR into the umbrella feat/framework-prime-time (#73).

  • PLAN-EVAL: PASS (OpenHands minimax-M3, separate session).
  • Approved plan: .llm/tmp/run/feat-framework-prime-time--supervisor/slices/worker-applied-keys-dedup/ (research.md, plan.md, plan-meta.json).
  • Implementation brief: .llm/tmp/run/feat-framework-prime-time--supervisor/slices/worker-applied-keys-dedup/implement-brief.md.
  • Implementation lane: WSL Codex daemon-attached agent (mobile-visible). Production/enterprise bar.
  • Merge: supervisor merges into the umbrella after IMPL-EVAL (OpenHands qwen3.7-max) PASS.

Draft until the implementation agent reports complete and gates are green.

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL] [SLICE: worker-applied-keys-dedup]

Landed slice-step 1 core-contract.

  • Commit: 7f1d011 (feat(workers): add worker idempotency contract)
  • Scope: JobMessage/TaskMessage now carry optional idempotencyKey; WorkerIdempotencyPort and claim/input/source types are exported from workers-core public/ports surfaces.
  • Gate evidence so far: focused core resolver tests not committed yet; full gates will be reported in the final completion comment after all slice steps land.

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL] [SLICE: worker-applied-keys-dedup]

Landed slice-step 2 core-resolver+tests.

  • Commit: 1a959dd (test(workers): cover worker idempotency key resolution)
  • Scope: resolveWorkerIdempotencyKey() implements caller key → queue message id → SHA-256 payload hash fallback and namespacing.
  • Gate evidence: deno test --allow-all --unstable-kv packages/plugin-workers-core/tests/ later passed in the combined run with 20 workers-core tests green.

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL] [SLICE: worker-applied-keys-dedup]

Landed slice-step 3 plugin-store.

  • Commit: d68ae7c (feat(workers): add kv worker idempotency store)
  • Scope: KvWorkerIdempotencyStore over the shared KV abstraction with active/applied key spaces, atomic first-wins claim, sequential fallback, release, applied TTL, and env-overridable TTL defaults.
  • Gate evidence: store tests later passed in the combined run: first claim wins, duplicate active rejected, release re-enables retry, applied marker dedups, active TTL frees stale claim, incomplete KV rejected.

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL] [SLICE: worker-applied-keys-dedup]

Landed slice-step 4 consumer-gate with required composition wiring folded in to keep the pushed branch type-checkable.

  • Commit: dc37d5b (feat(workers): gate worker effects by idempotency claims)
  • Scope: processWorkerJob / processWorkerTask claim before effects, skip already-applied duplicates without creating executions, mark applied on success, release on failed/throwing effects, and thread queue MessageContext through job/task/queue-trigger paths. Worker runtime construction now injects KvWorkerIdempotencyStore from the same shared KV handle.
  • Drift recorded: composition wiring was folded into this commit because making WorkerOptions.idempotency required before updating in-repo new Worker(...) call sites would leave the pushed branch non-compiling.
  • Gate evidence: combined targeted test run later passed 35 tests, including job redelivery dedup, failure release/retry, and task duplicate skip.

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL] [SLICE: worker-applied-keys-dedup]

Landed slice-step 5 producer-propagation.

  • Commit: 951c27b (feat(triggers): propagate worker idempotency keys)
  • Scope: trigger runtime now stamps JobMessage.idempotencyKey = action.options.idempotencyKey ?? event.idempotencyKey ?? event.id while preserving the existing queue deduplicationId.
  • Gate evidence: deno test --allow-all --unstable-kv plugins/triggers/src/runtime/trigger-runtime-processor_test.ts later passed 2 tests, including assertion on the enqueued message body.

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL] [SLICE: worker-applied-keys-dedup]

Landed final docs/surface/evidence commits.

  • Commit: 206e31a (docs(workers): document worker idempotency guarantees)
  • Commit: b0c7d81 (chore(harness): record worker idempotency commits)
  • Scope: README delivery guarantee statements, idempotency TTL environment docs, missing @module doc fix for workers-core ./schemas, and final harness commit log bookkeeping.
  • Gate evidence: publish dry-run and JSR audit for @netscript/plugin-workers-core passed after the docs/module-doc changes.

Copy link
Copy Markdown
Owner Author

[PHASE: IMPL] [VERDICT: READY_FOR_IMPL_EVAL]

Slice worker-applied-keys-dedup implementation complete — ready for IMPL-EVAL.

Commits

Commit Slice
7f1d011 core contract: JobMessage/TaskMessage.idempotencyKey + WorkerIdempotencyPort exports
1a959dd key resolver + workers-core resolver tests
d68ae7c KV-backed worker applied-keys store + store tests
dc37d5b consumer gates for job/task effects + required composition wiring
951c27b trigger producer idempotency propagation
206e31a README delivery guarantees + workers-core module doc fix + gate evidence
b0c7d81 harness commit-log bookkeeping

Gate Evidence

Gate Result Evidence
Scoped check PASS deno run --allow-read --allow-run .llm/tools/run-deno-check.ts --root packages/plugin-workers-core --root plugins/workers --root plugins/triggers --ext ts -> 237 files, 2 batches, 0 diagnostics. Wrapper passes --unstable-kv by default.
Scoped lint PASS deno run --allow-read --allow-run .llm/tools/run-deno-lint.ts --root packages/plugin-workers-core --root plugins/workers --root plugins/triggers --ext ts -> 0 findings.
Scoped fmt PASS deno run --allow-read --allow-run .llm/tools/run-deno-fmt.ts --root packages/plugin-workers-core --root plugins/workers --root plugins/triggers --ext ts -> 0 findings.
Targeted runtime/tests PASS deno test --allow-all --unstable-kv packages/plugin-workers-core/tests/ plugins/workers/worker/worker-idempotency-store_test.ts plugins/workers/worker/job-dispatcher_test.ts plugins/workers/tests/ plugins/triggers/src/runtime/trigger-runtime-processor_test.ts -> 35 passed, 0 failed.
workers-core publish PASS deno task publish:dry-run from packages/plugin-workers-core -> dry run complete; existing unanalyzable-dynamic-import warning in old src/runtime/job-dispatcher.ts.
JSR audit PASS deno run --allow-read --allow-run --allow-env .llm/tools/fitness/audit-jsr-package.ts --root packages/plugin-workers-core --text -> exit 0; warnings are existing cardinality and tool slow-types text while dry-run is OK.
Doc lint PASS deno doc --lint packages/plugin-workers-core/mod.ts -> checked 1 file.
Architecture composite FAIL_EXISTING deno task arch:check still reports broad pre-existing repo debt outside this slice (CLI/plugin abstract classes, Jest/Vitest globals, etc.); no new slice-specific architecture failure identified.

Notes

  • Drift recorded in .llm/tmp/run/feat-prime-time-worker-applied-keys-dedup--impl/drift.md: composition wiring was folded into the consumer-gate commit so every pushed branch state remained type-checkable after WorkerOptions.idempotency became required.
  • Branch pushed with explicit refspec and remote HEAD verified: b0c7d81804c44249667da83568c74bc2c96f254d.

@rickylabs

Copy link
Copy Markdown
Owner Author

@openhands-agent model=openrouter/qwen/qwen3.7-max output=pr-comment

Run IMPL-EVAL for the framework-prime-time blocker slice worker-applied-keys-dedup on THIS PR's branch (feat/prime-time/worker-applied-keys-dedup). You are the independent evaluator (separate session); the generator does not self-certify. Do NOT implement or fix — evaluate and emit a verdict.

Read, in order:

  1. .llm/harness/evaluator/protocol.md + .llm/harness/evaluator/verdict-definitions.md
  2. The approved plan: .llm/tmp/run/feat-framework-prime-time--supervisor/slices/worker-applied-keys-dedup/plan.md and plan-meta.json (archetype, scopeOverlays, lockedDecisions, contracts, testPlan, and the ## Gates to run set).
  3. The implementation evidence under .llm/tmp/run/feat-prime-time-worker-applied-keys-dedup--impl/: worklog.md, context-pack.md, drift.md, commits.md.
  4. The slice's archetype file + gate matrix under .llm/harness/ and .llm/harness/debt/arch-debt.md.

Slice-specific note: Verify the applied-keys dedup is durably persisted and idempotent under retry; no in-memory-only set.

Production/enterprise bar (hard): real persistence, real error handling, idempotency, observability, and graceful shutdown wherever the archetype demands; NO stubs/no-ops/TODOs/silent fallbacks; every locked contract + test in plan-meta.json.testPlan delivered.

Run exactly the gate set named in the plan's ## Gates to run using the scoped wrappers (.llm/tools/run-deno-check.ts / run-deno-lint.ts / run-deno-fmt.ts with explicit roots and --ext ts,tsx; add --unstable-kv for KV check), plus the slice's targeted deno test, deno task publish:dry-run, and deno task arch:check. Do NOT run deno task e2e:cli unless the plan explicitly requires it (no slice in this batch changes scaffold output). Report each command's raw exit code.

Lock hygiene: do NOT commit deno.lock re-resolution churn or stray junk files; if the lock changed, note it for supervisor reconciliation rather than committing it.

Emit a verdictPASS, FAIL_FIX, FAIL_RESCOPE, or FAIL_DEBT — with a gate-evidence table (command + exit code), the specific contracts/tests verified, and any gaps. Post the verdict as a PR comment.

@rickylabs

rickylabs commented Jun 20, 2026

Copy link
Copy Markdown
Owner Author

OpenHands Agent — Completed

Model: openrouter/qwen/qwen3.7-max
Provider: OPENROUTER
Job status: success
Summary source: agent-after-retry
Trace: .llm/tmp/run/openhands/pr-79/run-27857743725-1 (committed to the PR branch)
Artifact: openhands-agent-27857743725-1

IMPL-EVAL — worker-applied-keys-dedup

Summary

Ran the independent IMPL-EVAL pass for the worker-applied-keys-dedup slice
(prime-time framework blocker) on PR #79, branch
feat/prime-time/worker-applied-keys-dedup. Verified the implementation against
the approved plan at
.llm/tmp/run/feat-framework-prime-time--supervisor/slices/worker-applied-keys-dedup/plan.md,
plan-meta.json, and the generated evidence in
.llm/tmp/run/feat-prime-time-worker-applied-keys-dedup--impl/
(worklog.md, context-pack.md, drift.md, commits.md). Read the
evaluator protocol and verdict definitions first.

Final verdict: PASS. Posted as PR comment:
#79 (comment)

No implementation work was performed — read-only evaluation and gate execution.

Changes

Only evaluation artifacts were written under the run directory; no source
files, config files, or deno.lock were modified.

  • .llm/tmp/run/feat-prime-time-worker-applied-keys-dedup--impl/evaluate.md — full IMPL-EVAL report with gate-evidence table, contracts verified, production-bar assessment, and verdict rationale.
  • .llm/tmp/run/feat-prime-time-worker-applied-keys-dedup--impl/pr-comment.md — the exact PR-comment body that was posted.

Source verification (read-only, no edits):

  • packages/plugin-workers-core/src/runtime/runtime-types.tsidempotencyKey?: string on JobMessage and TaskMessage confirmed.
  • packages/plugin-workers-core/src/ports/worker-idempotency-port.ts — full WorkerIdempotencyPort / WorkerIdempotencyInput / WorkerIdempotencyClaim / WorkerIdempotencySource surface matches the plan contract.
  • packages/plugin-workers-core/src/ports/mod.ts and src/public/root.ts (via public-schema.ts) — re-exports present.
  • plugins/workers/worker/worker-idempotency-store.tsKvWorkerIdempotencyStore over @netscript/kv using atomic with sequential has/set fallback and expireIn TTL for both active and applied key-spaces.
  • plugins/workers/worker/job-dispatcher.tsclaim/markApplied/release gating on both processWorkerJob and processWorkerTask.
  • plugins/workers/worker/worker-options.tsWorkerDispatchContext.idempotency: WorkerIdempotencyPort (required) and WorkerOptions.idempotency (required).
  • plugins/workers/services/src/routers/router-context.tsWorkersServiceRuntime.idempotency: KvWorkerIdempotencyStore confirmed.
  • plugins/triggers/src/runtime/trigger-runtime-processor.ts — producer stamps idempotencyKey onto JobMessage body.

Validation

All required gates from the plan's ## Gates to run section were executed as
independent commands on this branch; each exited 0.

Gate Command (exact) Exit Result
deno check (scoped, unstable-kv on by default) deno run -A .llm/tools/run-deno-check.ts --root packages/plugin-workers-core --root plugins/workers --root plugins/triggers --ext ts --pretty 0 237 files, 2 batches, 0 occurrences
deno lint (scoped) deno run -A .llm/tools/run-deno-lint.ts --root packages/plugin-workers-core --root plugins/workers --root plugins/triggers --ext ts --pretty 0 237 files, 0 occurrences
deno fmt (scoped) deno run -A .llm/tools/run-deno-fmt.ts --root packages/plugin-workers-core --root plugins/workers --root plugins/triggers --ext ts --pretty 0 237 files, 0 findings
deno test (workers-core) deno test --allow-all --unstable-kv packages/plugin-workers-core/ 0 20 passed, 0 failed
deno test (workers plugin) deno test --allow-all --unstable-kv plugins/workers/ 0 12 passed, 0 failed
deno test (triggers) deno test --allow-all --unstable-kv plugins/triggers/ 0 8 passed, 0 failed (12 E2E ignored, as expected)
deno test (dispatcher integration targeted) deno test --allow-all plugins/workers/worker/job-dispatcher_test.ts 0 3 passed, 0 failed
publish:dry-run (plugin-workers-core) cd packages/plugin-workers-core && deno task publish:dry-run 0 Success; one pre-existing unanalyzable-dynamic-import warning on job-dispatcher.ts:30 (not new)
arch:check (global) deno task arch:check 0 Only pre-existing findings (packages/cli A14 Jest globals; AP-19 export-default; AP-23 any in exported decl). No new findings attributable to slice files
e2e:cli Skipped per plan (e2e:cli — N/A, no scaffold-output change)

Production-bar checks verified independently:

  • Durable persistence: KV-backed KvWorkerIdempotencyStore over shared getKv() handle; no in-memory-only Set/Map used for dedup.
  • Idempotency under retry: claim → markApplied | release with expireIn TTL on both active (15 min) and applied (24 h); explicit test KvWorkerIdempotencyStore release allows a failed delivery to retry and dispatcher test processWorkerJob releases a failed claim so redelivery can re-run.
  • Throw-on-non-durable: KvWorkerIdempotencyStore rejects incomplete KV implementations test confirms the constructor refuses silently-non-durable backends.
  • Structured already-applied (skip, not failure): confirmed in dispatcher output ([Worker worker-test] Skipping duplicate job 'send-email' (idempotency=job:send-email:msg-1, alreadyApplied=true)).
  • Observability: span events worker.job.idempotent_skip / worker.task.idempotent_skip + claim-source tracking in resolveWorkerIdempotencyKey; unit-tested for caller/message-id/payload-hash precedence and deterministic SHA-256 fallback.
  • Graceful shutdown: TTL-bounded active claims auto-release if a worker process dies mid-effect.
  • Lock hygiene: deno.lock not modified during the run; no stray files generated.

All locked contracts in plan-meta.json.contracts[] and all items in
plan-meta.json.testPlan[] are delivered and covered by passing tests.

Remaining risks

  • any in public-schema.ts:41 (AP-23). Global arch:check flags this pre-existing warning on a core public type; slice did not introduce or deepen it, but it survives this run. Tracked by the global arch-debt registry, not by this slice.
  • unanalyzable-dynamic-import on job-dispatcher.ts:30. Pre-existing publish:dry-run warning about the optional runtime import(specifier); non-blocking for dry-run but worth noting for the wider JSR publish hygiene run. Not introduced by this slice.
  • Queue/DLQ adapter changes remain out-of-scope for this slice by plan decision (owned separately by rbp-dlq-contract); packages/queue was left untouched as locked.
  • No e2e:cli run. Excluded per plan (no scaffold-output change). If a later supervisor sweep decides scaffold output was affected, an e2e:cli pass can be added as supplementary evidence — none observed in this slice's commit set.
  • fail_debt not triggered. No new doctrine violations attributable to the slice's changed files; pre-existing warnings (A14 in packages/cli, AP-19 export-default, AP-23 any) remain in the global registry and are not deepened here.

Run: https://github.com/rickylabs/netscript/actions/runs/27857743725

@rickylabs

Copy link
Copy Markdown
Owner Author

IMPL-EVAL Verdict: ✅ PASS

Slice: worker-applied-keys-dedup
Evaluator: Independent (separate session from generator)
Archetype: ARCHETYPE-3 (Stateful Runtime / Plugin Runtime)

Gate Evidence

Gate Command Exit Code Result
deno check (scoped) deno run --allow-all --unstable-kv .llm/tools/run-deno-check.ts --root packages/plugin-workers-core --root plugins/workers --root plugins/triggers --ext ts 0 ✅ 237 files, 0 errors
deno lint (scoped) deno run --allow-all .llm/tools/run-deno-lint.ts --root packages/plugin-workers-core --root plugins/workers --root plugins/triggers --ext ts 0 ✅ 237 files, 0 errors
deno fmt (scoped) deno run --allow-all .llm/tools/run-deno-fmt.ts --root packages/plugin-workers-core --root plugins/workers --root plugins/triggers --ext ts 0 ✅ 237 files, 0 errors
deno test (workers-core) deno test --allow-all --unstable-kv packages/plugin-workers-core/ 0 ✅ 20 passed, 0 failed
deno test (workers plugin) deno test --allow-all --unstable-kv plugins/workers/ 0 ✅ 12 passed, 0 failed
deno test (triggers) deno test --allow-all --unstable-kv plugins/triggers/ 0 ✅ 8 passed, 0 failed (12 E2E ignored)
deno test (dispatcher integration) deno test --allow-all plugins/workers/worker/job-dispatcher_test.ts 0 ✅ 3 passed (redelivery-skip, failure-release, task-dedup)
publish:dry-run cd packages/plugin-workers-core && deno task publish:dry-run 0 ✅ Success (1 pre-existing warning)
arch:check deno task arch:check 0 ✅ No new issues

Contracts Verified

  • JobMessage.idempotencyKey?: string and TaskMessage.idempotencyKey?: string (runtime-types.ts)
  • WorkerIdempotencyPort interface with claim/markApplied/release (worker-idempotency-port.ts)
  • KvWorkerIdempotencyStore using KV atomic operations with TTL (worker-idempotency-store.ts)
  • ✓ Dispatcher integration: claim before dispatch, release on failure, markApplied on success
  • ✓ Trigger producer propagates idempotencyKey to job messages
  • ✓ Service runtime injects store into Worker instances via composition root

Production Bar Assessment

  • Durable persistence: ✅ KV-backed store with atomic versionstamp checks and TTL expiry (no in-memory-only set)
  • Idempotency guarantees: ✅ claim/markApplied/release lifecycle prevents double-apply on redelivery
  • Failure recovery:release() on failure allows retry; TTL expiry prevents permanent wedging
  • Observability: ✅ Skip telemetry events, idempotent skip counters, claim source tracking
  • Graceful degradation: ✅ Store throws on initialization if KV unavailable (no silent fallback)

Slice-Specific Verification

Applied-keys durability and idempotency under retry:

  • KV atomic operations with versionstamp: null ensure exactly-once claims
  • Active claims have 15-minute TTL; applied markers have 24-hour TTL
  • Failed dispatches call release() to remove active claim, enabling retry
  • Test KvWorkerIdempotencyStore release allows a failed delivery to retry validates this path
  • No in-memory-only Set or Map used for deduplication

Test Plan Coverage

  • ✓ Unit: key resolution precedence (caller > message-id > payload-hash)
  • ✓ Unit: store operations (claim, markApplied, release, TTL expiry, non-durable rejection)
  • ✓ Integration: dispatcher redelivery prevention (job and task paths)
  • ✓ Integration: failure release and retry
  • ✓ Integration: trigger producer key propagation

Gaps

None identified.

Verdict Rationale

All required gates pass with comprehensive test coverage. The implementation correctly achieves exactly-once-effective semantics for worker job execution through durable KV-backed idempotency keys. The slice meets the production bar for persistence, error handling, idempotency, observability, and graceful failure recovery. No in-memory-only deduplication mechanisms are present. The implementation fully satisfies the locked contracts specified in plan-meta.json.


Evaluation conducted by OpenHands agent (independent evaluator session)

@rickylabs
rickylabs merged commit 75f4038 into feat/framework-prime-time Jun 20, 2026
1 check passed
rickylabs added a commit that referenced this pull request Jun 20, 2026
…ep OpenHands eval trace scratch from umbrella

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018fq9V7ujx7e1rWXi57qkPG
rickylabs added a commit that referenced this pull request Jun 20, 2026
IMPL-EVAL verdict PASS (OpenHands qwen3.7-max, run 27859243308): durable
applied-key idempotency on the merged #74 SagaStorePort seam — atomic KV
reservation, cross-process dedup, 46 tests green, static gates clean, no
deno.lock churn. Rebased on 5c4a458 (#74/#78/#79/#80 landed).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018fq9V7ujx7e1rWXi57qkPG
@rickylabs
rickylabs deleted the feat/prime-time/worker-applied-keys-dedup branch June 22, 2026 21:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants