Skip to content

chore: refine HITL specs and rename change#21

Merged
coji merged 4 commits into
mainfrom
feature/openspec-migration
Jan 17, 2026
Merged

chore: refine HITL specs and rename change#21
coji merged 4 commits into
mainfrom
feature/openspec-migration

Conversation

@coji
Copy link
Copy Markdown
Owner

@coji coji commented Jan 17, 2026

Summary

  • Simplify HITL design and align naming around message/wait_message (avoid AI prompt confusion)
  • Standardize resume flow on runId + required payload and add explicit HTTP error cases
  • Rename change from add-human-in-loop to add-human-in-the-loop and update related specs/tasks
  • Update React HITL hook to useHumanWaits with respond API and typed payload guidance
  • Document security considerations (authz/validation/audit) for HITL flows

Test plan

  • openspec validate add-human-in-the-loop --strict --no-interactive

Summary by CodeRabbit

  • New Features

    • Added automatic job definition versioning with hash tracking for managing schema changes across runs
    • Added PostgreSQL database support with atomic run claiming for multi-worker deployments
    • Added streaming v2 with event persistence and resumeFrom capability for reconnections
    • Added Human-in-the-Loop workflow enabling runs to pause for user input and resume
  • Documentation

    • Added comprehensive project documentation, specifications, and OpenSpec development guides

✏️ Tip: You can customize this high-level summary in your review settings.

Add OpenSpec framework structure with:
- Core spec (20 requirements) for implemented features
- 4 change proposals for planned features:
  - add-human-in-loop: ctx.human() API, waiting_human status
  - add-streaming-v2: step.stream(), event persistence
  - add-job-versioning: job_hash for run-job binding
  - add-postgresql: PostgreSQL dialect support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Jan 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
durably-demo Ready Ready Preview Jan 17, 2026 0:48am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 17, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

This PR introduces a comprehensive specification and documentation framework for the Durably project via OpenSpec, including core architecture specifications, project conventions, and structured proposals for four major features: Job Versioning, PostgreSQL Support, Streaming v2, and Human-in-the-Loop workflows.

Changes

Cohort / File(s) Summary
OpenSpec Framework & Guidance
AGENTS.md, openspec/AGENTS.md, openspec/project.md, .claude/commands/openspec/*
Establishes OpenSpec instructions for AI agents, project context (tech stack, conventions, architecture), and Claude command templates for proposal, apply, and archive workflows.
Core Specification
openspec/specs/core/spec.md
Defines the foundational batch execution framework for Node.js and browsers, covering job registration, run lifecycle, idempotency, concurrency controls, event systems, logging, and multi-environment support.
Job Versioning Feature
openspec/changes/add-job-versioning/proposal.md, specs/core/spec.md, tasks.md
Proposes automatic job hash generation and validation to detect job definition changes during Run execution, with optional allowIncompatible bypass.
PostgreSQL Support Feature
openspec/changes/add-postgresql/proposal.md, specs/core/spec.md, tasks.md
Proposes PostgreSQL dialect support via Kysely, atomic run claiming with FOR UPDATE SKIP LOCKED, concurrency key locking, and stale run recovery.
Streaming v2 Feature
openspec/changes/add-streaming-v2/proposal.md, specs/core/spec.md, tasks.md
Proposes real-time token-level streaming via step.stream(), event persistence for replay, resumeFrom support in subscribe(), and checkpoint API for long-running steps.
Human-in-the-Loop (HITL) Feature
openspec/changes/add-human-in-the-loop/proposal.md, specs/core/spec.md, tasks.md
Proposes human wait workflows via ctx.human(), waiting_human status, runId-based resume, HTTP resume endpoints, and timeout handling.
Feature Documentation
docs/spec-human-in-loop.md, docs/spec-job-versioning.md, docs/spec-postgres.md, docs/spec-react.md, docs/spec-streaming.md
Detailed future-facing specifications and design guides for each feature, including API surfaces, data models, integration points, and implementation guidance.
Existing File Updates
CLAUDE.md
Adds OpenSpec instruction block and updates database schema table name references to durably-prefixed equivalents (durably_runs, durably_steps, durably_logs, durably_schema_versions).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A spec-tacular warren of changes, so bright,
With OpenSpec guides and proposals in sight!
Job versions, streaming, and humans to talk,
PostgreSQL paths for the data to walk,
This framework now dances on documentation's light! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: migrate to OpenSpec for spec-driven development' clearly and concisely summarizes the primary change: adopting OpenSpec framework for structured specification-driven development instead of ad-hoc documentation.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@openspec/changes/add-human-in-loop/specs/core/spec.md`:
- Around line 94-105: Update the GET /runs scenarios to require explicit
authorization before returning wait_token: only return wait_token when the query
param includeToken=true AND the caller has explicit permission (e.g., a new
required scope/claim such as "runs:read:token" or an equivalent authz check).
Modify the Scenario: GET /runs with includeToken to state that the request must
include includeToken=true and valid authorization that grants token access, and
add a note to Scenario: GET /runs without includeToken that no token is returned
unless both includeToken=true and the required authz is present.

In `@openspec/changes/add-streaming-v2/proposal.md`:
- Around line 18-22: The Impact section mixes Japanese with English; update the
listed entries to use consistent English wording (e.g., replace "追加" with
"added", "テーブル操作追加" with "added table operations", "拡張" with "extended",
"テーブル定義" with "table definition", "マイグレーション" with "migration") for the lines
referencing packages/durably/src/context.ts (step.stream()),
packages/durably/src/storage.ts (events table operations),
packages/durably/src/durably.ts (subscribe()), packages/durably/src/schema.ts
(events table definition), and packages/durably/src/migrations.ts (events table
migration) so the entire Impact section is fully English and consistent.
🧹 Nitpick comments (10)
openspec/changes/add-postgresql/proposal.md (1)

9-21: Clarify dialect selection/config path.
Please specify how PostgreSQL is selected at runtime (e.g., configuration flag, env, or explicit factory like createDurably({ dialect })) and whether PG support is optional or required for certain deployments. This will prevent ambiguity in implementation tasks.

openspec/changes/add-job-versioning/tasks.md (1)

21-33: Add a task for API/contract docs + error mapping.
Consider adding a checklist item to update public docs/API references for job_version_mismatch, allowIncompatible, and any HTTP status mapping (e.g., 412) so implementation and docs stay aligned.

openspec/changes/add-job-versioning/proposal.md (1)

18-22: Standardize language for consistency.
This block mixes English and Japanese terms. Consider standardizing to a single language for consistency across OpenSpec docs.

openspec/project.md (2)

105-117: Confirm repository layout matches docs/ and openspec/.
If specs live under openspec/, consider updating this tree to avoid confusion for contributors.


89-97: Consider adding the top‑level await constraint.
Given the ESM-only constraint, it may help to note the top‑level await requirement for async initialization (e.g., await durably.migrate()) to avoid incorrect patterns. Based on learnings, ...

openspec/changes/add-job-versioning/specs/core/spec.md (1)

7-12: Define canonicalization/normalization for stability.
To guarantee order-independence, consider specifying the exact canonicalization strategy (e.g., stable JSON serialization, sorted keys, normalized schema representation).

openspec/AGENTS.md (1)

26-31: Optional: consolidate repeated example phrases.

The adjacent “I want to create a spec proposal / spec” bullets are redundant; consider merging to keep the trigger list tighter.

openspec/changes/add-streaming-v2/specs/core/spec.md (2)

31-58: Clarify sequence scope and replay ordering guarantees.

Please specify whether sequence is per-run or global, and whether ordering is strictly monotonic across all persisted event types. Also clarify the replay boundary (inclusive/exclusive) and ordering between replayed events and the first live event to avoid divergent implementations.


20-25: Explicitly note that stream events are not replayed.

Given stream events are memory-only, please state in the replay scenario that no prior stream events will be re-emitted on resume/replay, so consumers don’t expect token replay.

Also applies to: 34-35

openspec/specs/core/spec.md (1)

73-77: Consider retention policy for perpetual idempotency keys.

“No expiration” can create unbounded storage growth and retention risk. Consider documenting an optional retention/cleanup policy or a maintenance job to prune old idempotency records if product requirements allow.

Comment on lines +94 to +105
#### Scenario: GET /runs with includeToken

- **GIVEN** Run is in `waiting_human` state
- **WHEN** `GET /runs?status=waiting_human&includeToken=true` is called
- **THEN** response includes `wait_token`

#### Scenario: GET /runs without includeToken

- **GIVEN** Run is in `waiting_human` state
- **WHEN** `GET /runs?status=waiting_human` is called (without includeToken)
- **THEN** response does NOT include `wait_token`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Require explicit authz for includeToken to avoid token leakage.

wait_token is a bearer credential; the spec should mandate authorization/least-privilege and explicit opt‑in checks before returning it to clients.

🤖 Prompt for AI Agents
In `@openspec/changes/add-human-in-loop/specs/core/spec.md` around lines 94 - 105,
Update the GET /runs scenarios to require explicit authorization before
returning wait_token: only return wait_token when the query param
includeToken=true AND the caller has explicit permission (e.g., a new required
scope/claim such as "runs:read:token" or an equivalent authz check). Modify the
Scenario: GET /runs with includeToken to state that the request must include
includeToken=true and valid authorization that grants token access, and add a
note to Scenario: GET /runs without includeToken that no token is returned
unless both includeToken=true and the required authz is present.

Comment on lines +18 to +22
- `packages/durably/src/context.ts` - `step.stream()` 追加
- `packages/durably/src/storage.ts` - `events` テーブル操作追加
- `packages/durably/src/durably.ts` - `subscribe()` 拡張
- `packages/durably/src/schema.ts` - `events` テーブル定義
- `packages/durably/src/migrations.ts` - events テーブルマイグレーション
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Normalize language in Impact section.

This section mixes English with Japanese (“追加”, “テーブル操作追加”, etc.). Consider keeping it fully English for consistency with the rest of the doc.

🤖 Prompt for AI Agents
In `@openspec/changes/add-streaming-v2/proposal.md` around lines 18 - 22, The
Impact section mixes Japanese with English; update the listed entries to use
consistent English wording (e.g., replace "追加" with "added", "テーブル操作追加" with
"added table operations", "拡張" with "extended", "テーブル定義" with "table
definition", "マイグレーション" with "migration") for the lines referencing
packages/durably/src/context.ts (step.stream()), packages/durably/src/storage.ts
(events table operations), packages/durably/src/durably.ts (subscribe()),
packages/durably/src/schema.ts (events table definition), and
packages/durably/src/migrations.ts (events table migration) so the entire Impact
section is fully English and consistent.

Keep spec.md in English for OpenSpec validation and OSS accessibility,
while using Japanese for proposal.md and tasks.md for faster authoring.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @.claude/commands/openspec/apply.md:
- Line 8: Replace the section titles that use bold emphasis (e.g.,
"**Guardrails**" and other occurrences like "**Reference**") with proper
Markdown heading syntax (for example, change "**Guardrails**" to "##
Guardrails"); update all similar emphasis-as-heading instances in the file
(including the other reported occurrence) so they use the appropriate heading
level and run markdownlint to verify no emphasis-as-heading warnings remain.

In `@docs/spec-human-in-loop.md`:
- Around line 59-63: Add the language identifier "text" to the fenced code block
containing the ASCII state transition diagram (the block that starts with
"pending -> running -> waiting_human -> running -> completed" and the
accompanying lines with "failed"), i.e., change the opening triple backticks to
```text so the diagram is treated as plain text.
♻️ Duplicate comments (1)
openspec/changes/add-streaming-v2/proposal.md (1)

18-22: Normalize language in Impact section (already noted).

🧹 Nitpick comments (4)
.claude/commands/openspec/archive.md (1)

8-13: Use proper headings instead of bold labels.

Markdownlint flags these as emphasis-as-heading; switch to ##/### to keep lint clean.

♻️ Proposed fix
-**Guardrails**
+## Guardrails
 ...
-**Steps**
+## Steps
 ...
-**Reference**
+## Reference

Also applies to: 24-24

docs/spec-job-versioning.md (1)

37-39: Convert the bold line to a heading.

Markdownlint MD036 will flag this; prefer a heading for consistency.

♻️ Proposed fix
-**HITL との整合(Phase 2)**
+### HITL との整合(Phase 2)
docs/spec-human-in-loop.md (1)

1-492: Well-structured HITL specification with comprehensive coverage.

This specification thoroughly documents the Human-in-the-Loop feature including:

  • Clear API surface (ctx.human, durably.resume)
  • Complete data model with security considerations
  • HTTP endpoint specifications with error handling
  • Implementation guidance with SQL migrations and transaction boundaries
  • UX considerations and usage examples

The phased rollout approach (Phase 1: HITL standalone, Phase 2: Job Versioning integration) demonstrates good architectural planning.

Optional: Consider using markdown headings for subsections

Several subsections use bold text (e.g., lines 50, 72, 80, 148, 167, 177, 224, 282, 289, 294, 308, 342, 348, 401) instead of proper markdown headings. While this creates a more compact document, using #### or ##### headings would improve document structure, enable better navigation, and resolve the markdownlint warnings.

This is purely a documentation quality suggestion and not blocking.

docs/spec-react.md (1)

530-599: Excellent HITL API design with good security boundaries.

The useHumanInbox hook provides a clean, developer-friendly interface for Human-in-the-Loop workflows:

  • Single-hook approach simplifies the API surface (no separate useWaitingRuns / useResume)
  • Convenience methods (approve, reject, edit) automatically populate the decision field
  • Security-conscious: wait_token is kept internal to the hook, not exposed in the WaitingRun type
  • Consistent with endpoints defined in docs/spec-human-in-loop.md

The separation between server-connected mode (@coji/durably-react/client) and browser-only mode (@coji/durably-react) with the same API surface is elegant.

Optional: Subsection heading formatting

Lines 572 and 596 use bold text for subsection headers ("戻り値" and "内部動作"). Consider using proper markdown headings (#####) for better document structure, though the current formatting is acceptable.

tags: [openspec, apply]
---
<!-- OPENSPEC:START -->
**Guardrails**
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use headings instead of bold text for section titles.

Markdownlint flags emphasis-as-heading here; switch to actual heading syntax (e.g., ## Guardrails, ## Reference) for consistency.

Also applies to: 21-21

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

8-8: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🤖 Prompt for AI Agents
In @.claude/commands/openspec/apply.md at line 8, Replace the section titles
that use bold emphasis (e.g., "**Guardrails**" and other occurrences like
"**Reference**") with proper Markdown heading syntax (for example, change
"**Guardrails**" to "## Guardrails"); update all similar emphasis-as-heading
instances in the file (including the other reported occurrence) so they use the
appropriate heading level and run markdownlint to verify no emphasis-as-heading
warnings remain.

Comment thread docs/spec-human-in-loop.md Outdated
@coji coji changed the title feat: migrate to OpenSpec for spec-driven development chore: refine HITL specs and rename change Jan 17, 2026
@coji coji merged commit 5d30895 into main Jan 17, 2026
7 checks passed
@coji coji deleted the feature/openspec-migration branch March 5, 2026 12:14
@coderabbitai coderabbitai Bot mentioned this pull request Mar 8, 2026
4 tasks
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.

1 participant