Add v19 timeline intents, readings, and drafts#729
Conversation
📝 WalkthroughSummary by CodeRabbit
WalkthroughThis PR introduces v19 first-use intent, reading, receipt, draft, and join APIs, wires them through Changesv19 First-Use API
Estimated code review effort: 4 (Complex) | ~75 minutes Possibly related issues
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
Comment |
Release Preflight
If this PR is from a |
There was a problem hiding this comment.
Actionable comments posted: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
scripts/check-source-backed-reference.ts (1)
211-270: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider naming the per-surface
SourceTextinstances for consistency.Other sources (
packageSource,jsrSource,registrySource,cliSource,errorSource) are assigned to named consts before use, but the five new export-surface sources are constructed inline insideexportSurface(...)calls. Purely stylistic, but slightly inconsistent within the same function.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@scripts/check-source-backed-reference.ts` around lines 211 - 270, The export-surface SourceText instances are created inline in generate(), unlike the other named sources, which makes the style inconsistent. Introduce named consts for each surface source used by exportSurface (for example the ones passed for root, storage, advanced, diagnostics, and legacy) and then pass those variables into exportSurface so the source declarations match the pattern used by packageSource, jsrSource, registrySource, cliSource, and errorSource.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/domain/api/IntentRuntime.ts`:
- Around line 26-72: The six lowerer functions in IntentRuntime all repeat the
same kind-mismatch guard and WarpError logic. Extract that shared check into a
single helper near
lowerNodeAdd/lowerNodeRemove/lowerEdgeAdd/lowerEdgeRemove/lowerPropertySet/lowerEdgePropertySet,
then have each lowerer call it before delegating to PatchBuilder. Keep the
existing E_INTENT_KIND error behavior unchanged while removing the duplicated if
blocks.
In `@src/domain/api/JoinReceipt.ts`:
- Line 7: The receipt outcome type in JoinReceipt is duplicating the literal
list from WriteReceipt and can drift over time. Update JoinReceipt to import and
reuse the shared RECEIPT_OUTCOMES definition from WriteReceipt rather than
redefining the outcome union, so both JoinReceiptOutcome and ReceiptOutcome stay
in sync automatically.
In `@src/domain/api/Timeline.ts`:
- Around line 105-123: `Timeline.read()` and `Timeline.write()` validate their
inputs inline, unlike `draft()`, `previewJoin()`, and `join()` which use shared
assertion helpers. Extract matching helpers such as `assertReadingInstance()`
and `assertIntentInstance()` in `Timeline` and have `read()`/`write()` call them
so validation follows the same consistent pattern as `assertDraftTimeline()`.
- Around line 150-166: The port-validation helpers in Timeline are duplicated
across assertJoinDraft, assertOpenDraft, assertReadReading, and
assertWriteIntent, all doing the same undefined-or-function check with only
message/code differences. Refactor these into a single generic validator helper
in the same module, then have each of those functions call it with their
specific error text and WarpError code so the existing behavior and symbols
remain unchanged.
In `@src/domain/api/WriteReceipt.ts`:
- Around line 5-27: Export RECEIPT_OUTCOMES from WriteReceipt so other modules
like JoinReceipt can reuse the same canonical outcome list instead of
duplicating it. Update the declaration of RECEIPT_OUTCOMES in WriteReceipt to be
exported, and keep its contents unchanged so both validators stay in sync.
In `@test/unit/domain/WarpFacade.test.ts`:
- Around line 45-58: The browser export fence in FORBIDDEN_BROWSER_V19_EXPORTS
is missing the new speculative-workflow exports, so update the list to include
DraftTimeline, JoinReceipt, and JoinResult. Keep the change in the
WarpFacade.test.ts fixture where the existing forbidden browser exports are
defined so the browser root is still validated against the full v19 facade
surface.
---
Outside diff comments:
In `@scripts/check-source-backed-reference.ts`:
- Around line 211-270: The export-surface SourceText instances are created
inline in generate(), unlike the other named sources, which makes the style
inconsistent. Introduce named consts for each surface source used by
exportSurface (for example the ones passed for root, storage, advanced,
diagnostics, and legacy) and then pass those variables into exportSurface so the
source declarations match the pattern used by packageSource, jsrSource,
registrySource, cliSource, and errorSource.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: e9a194e0-7ff1-4bdb-80c1-ba127dbd2206
📒 Files selected for processing (28)
CHANGELOG.mdREADME.mddocs/migrations/v19/README.mddocs/topics/api/README.mddocs/topics/reference.mdindex.tsscripts/check-source-backed-reference.tssrc/domain/WarpWorldline.tssrc/domain/api/DraftTimeline.tssrc/domain/api/DraftTimelineRuntime.tssrc/domain/api/Intent.tssrc/domain/api/IntentBuilders.tssrc/domain/api/IntentRuntime.tssrc/domain/api/JoinReceipt.tssrc/domain/api/JoinResult.tssrc/domain/api/ReadReceipt.tssrc/domain/api/Reading.tssrc/domain/api/ReadingBuilders.tssrc/domain/api/ReadingResult.tssrc/domain/api/ReadingRuntime.tssrc/domain/api/Timeline.tssrc/domain/api/TimelineRuntime.tssrc/domain/api/WriteReceipt.tstest/type-check/tsconfig.jsontest/type-check/v19-consumer.tstest/type-check/v19-first-use.tstest/type-check/v19-subpaths.tstest/unit/domain/WarpFacade.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: coverage-threshold
- GitHub Check: test-node (22)
- GitHub Check: preflight
⚠️ CI failures not shown inline (2)
GitHub Actions: Link Check / Check broken links: Add v19 timeline intents, readings, and drafts
Conclusion: failure
##[group]Run /home/runner/work/_actions/lycheeverse/lychee-action/v2/entrypoint.sh
�[36;1m/home/runner/work/_actions/lycheeverse/lychee-action/v2/entrypoint.sh�[0m
shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
env:
INPUT_***REDACTED***
INPUT_ARGS: --config .lychee.toml '**/*.md'
INPUT_DEBUG: false
INPUT_FAIL: true
INPUT_FAILIFEMPTY: true
INPUT_FORMAT: markdown
INPUT_JOBSUMMARY: true
INPUT_CHECKBOX: true
INPUT_OUTPUT: ./lychee-report.md
SUMMARY_URL: https://github.com/git-stunts/git-warp/actions/runs/29029891504#summary-86159505233
##[endgroup]
[ERROR] Error while loading config: Cannot load configuration file `.lychee.toml`: Failed to load config from .lychee.toml
Caused by:
0: Failed to parse configuration file
1: TOML parse error at line 15, column 21
|
15 | include_fragments = true
| ^^^^
wanted string or table
See: https://github.com/lycheeverse/lychee/blob/lychee-v0.24.2/lychee.example.toml
##[notice]Summary report available at: https://github.com/git-stunts/git-warp/actions/runs/29029891504#summary-86159505233
##[error]Process completed with exit code 3.
GitHub Actions: Link Check / 0_Check broken links.txt: Add v19 timeline intents, readings, and drafts
Conclusion: failure
##[group]Run /home/runner/work/_actions/lycheeverse/lychee-action/v2/entrypoint.sh
�[36;1m/home/runner/work/_actions/lycheeverse/lychee-action/v2/entrypoint.sh�[0m
shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
env:
INPUT_***REDACTED***
INPUT_ARGS: --config .lychee.toml '**/*.md'
INPUT_DEBUG: false
INPUT_FAIL: true
INPUT_FAILIFEMPTY: true
INPUT_FORMAT: markdown
INPUT_JOBSUMMARY: true
INPUT_CHECKBOX: true
INPUT_OUTPUT: ./lychee-report.md
SUMMARY_URL: https://github.com/git-stunts/git-warp/actions/runs/29029891504#summary-86159505233
##[endgroup]
[ERROR] Error while loading config: Cannot load configuration file `.lychee.toml`: Failed to load config from .lychee.toml
Caused by:
0: Failed to parse configuration file
1: TOML parse error at line 15, column 21
|
15 | include_fragments = true
| ^^^^
wanted string or table
See: https://github.com/lycheeverse/lychee/blob/lychee-v0.24.2/lychee.example.toml
##[notice]Summary report available at: https://github.com/git-stunts/git-warp/actions/runs/29029891504#summary-86159505233
##[error]Process completed with exit code 3.
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Do not use direct imports fromsrc/infrastructure/**insrc/domain/**orsrc/ports/**; depend on a port instead.
Do not use direct Node built-ins insrc/domain/**orsrc/ports/**; use a port instead.
Files:
test/type-check/v19-first-use.tssrc/domain/api/JoinResult.tstest/type-check/v19-subpaths.tssrc/domain/api/IntentBuilders.tssrc/domain/api/ReadReceipt.tssrc/domain/api/WriteReceipt.tstest/type-check/v19-consumer.tssrc/domain/api/ReadingBuilders.tssrc/domain/api/JoinReceipt.tssrc/domain/api/ReadingRuntime.tssrc/domain/api/TimelineRuntime.tstest/unit/domain/WarpFacade.test.tssrc/domain/api/Reading.tssrc/domain/api/IntentRuntime.tssrc/domain/api/Intent.tssrc/domain/api/DraftTimeline.tssrc/domain/api/DraftTimelineRuntime.tssrc/domain/api/ReadingResult.tsindex.tssrc/domain/api/Timeline.tsscripts/check-source-backed-reference.tssrc/domain/WarpWorldline.ts
src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx,js,jsx}: Do not introduceany,as any,as unknown as,unknown(outside adapters),Record<string, unknown>(outside adapters),*Likeplaceholder types,JSON.parse/JSON.stringify(outside adapters),fetch(outside adapters),process.env(outside adapters),@ts-ignore, orz.any()in core code; use validated boundary models and ports instead.
Use constructor-injected ports for external capabilities; do not rely on ambient dependencies for I/O, clocks, persistence, or entropy.
Do not createutils.ts,helpers.ts,misc.ts, orcommon.ts; name files after the actual concept they model.
Prefer one file per class, type, or object; if a file accumulates peer concepts, split it.
Keep helper corridors, fake shape trust, transitional duplication, and compile-time theater out of the codebase; runtime-honest TypeScript must reflect actual behavior.
No enum usage; prefer runtime-backed domain forms and unions.
Do not use boolean trap parameters; prefer named option objects or separate methods.
Avoid magic strings or numbers when a named constant should exist.
Keep domain bytes asUint8Array;Bufferbelongs in infrastructure adapters.
Files:
src/domain/api/JoinResult.tssrc/domain/api/IntentBuilders.tssrc/domain/api/ReadReceipt.tssrc/domain/api/WriteReceipt.tssrc/domain/api/ReadingBuilders.tssrc/domain/api/JoinReceipt.tssrc/domain/api/ReadingRuntime.tssrc/domain/api/TimelineRuntime.tssrc/domain/api/Reading.tssrc/domain/api/IntentRuntime.tssrc/domain/api/Intent.tssrc/domain/api/DraftTimeline.tssrc/domain/api/DraftTimelineRuntime.tssrc/domain/api/ReadingResult.tssrc/domain/api/Timeline.tssrc/domain/WarpWorldline.ts
src/domain/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/domain/**/*.{ts,tsx,js,jsx}: Insrc/domain/**, do not useDate.now(),new Date(),Date(),performance.now(),Math.random(),crypto.randomUUID(),crypto.getRandomValues(),setTimeout,setInterval, rawnew Error(...)/new TypeError(...), or direct imports from Node built-ins; time, entropy, and external capabilities must enter through ports or parameters, and domain errors should extendWarpError.
Construct domain objects only in core when doing so establishes validated runtime truth; do not build infrastructure adapters, host APIs, persistence implementations, wall clocks, or entropy sources inside core.
Prefer discriminated unions and explicit result types instead of boolean-flag bags, and model expected failures as return values rather than exceptions.
src/domain/must not import host APIs or Node-specific globals; hexagonal architecture boundaries are mandatory.
Domain code must not use the wall clock directly; time must enter through a port or parameter.
Files:
src/domain/api/JoinResult.tssrc/domain/api/IntentBuilders.tssrc/domain/api/ReadReceipt.tssrc/domain/api/WriteReceipt.tssrc/domain/api/ReadingBuilders.tssrc/domain/api/JoinReceipt.tssrc/domain/api/ReadingRuntime.tssrc/domain/api/TimelineRuntime.tssrc/domain/api/Reading.tssrc/domain/api/IntentRuntime.tssrc/domain/api/Intent.tssrc/domain/api/DraftTimeline.tssrc/domain/api/DraftTimelineRuntime.tssrc/domain/api/ReadingResult.tssrc/domain/api/Timeline.tssrc/domain/WarpWorldline.ts
src/domain/**/!(*.test).{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use explicit domain concepts with validated constructors,
Object.freeze, andinstanceofdispatch; domain objects should be runtime-backed nouns, not ad hoc shape bags.
Files:
src/domain/api/JoinResult.tssrc/domain/api/IntentBuilders.tssrc/domain/api/ReadReceipt.tssrc/domain/api/WriteReceipt.tssrc/domain/api/ReadingBuilders.tssrc/domain/api/JoinReceipt.tssrc/domain/api/ReadingRuntime.tssrc/domain/api/TimelineRuntime.tssrc/domain/api/Reading.tssrc/domain/api/IntentRuntime.tssrc/domain/api/Intent.tssrc/domain/api/DraftTimeline.tssrc/domain/api/DraftTimelineRuntime.tssrc/domain/api/ReadingResult.tssrc/domain/api/Timeline.tssrc/domain/WarpWorldline.ts
🧠 Learnings (1)
📚 Learning: 2026-03-08T19:50:17.519Z
Learnt from: flyingrobots
Repo: git-stunts/git-warp PR: 65
File: CHANGELOG.md:88-88
Timestamp: 2026-03-08T19:50:17.519Z
Learning: Follow the Keep a Changelog convention for CHANGELOG.md. Allow duplicate subheadings across versions (e.g., '### Added', '### Fixed'). Configure markdownlint MD024 with {"siblings_only": true} to avoid cross-version false positives.
Applied to files:
CHANGELOG.md
🔇 Additional comments (34)
src/domain/api/DraftTimeline.ts (1)
1-76: LGTM!src/domain/WarpWorldline.ts (1)
33-256: LGTM!index.ts (1)
19-53: LGTM!src/domain/api/DraftTimelineRuntime.ts (2)
60-75: 🎯 Functional CorrectnessCheck
previewDraftJoinresult handlingpreviewJoindrops theruntime.previewDraftJoin(draft.name)result and hardcodesaccepted; wire the runtime outcome through, or make this an explicit placeholder if conflicts and policy rejections are not meant to surface here.
77-125: 🗄️ Data Integrity & IntegrationJoin can replay already-applied intents after a mid-stream failure.
commitDraftIntentspersists each intent in its ownruntime.commit(...)call, whilestate.joinedis only set after the loop. If a later commit throws, retryingjoinwill re-run the full intent list and can duplicate the earlier writes.CHANGELOG.md (1)
10-36: LGTM!README.md (1)
3-4: LGTM!Also applies to: 55-58, 73-76, 87-89
docs/migrations/v19/README.md (1)
125-132: LGTM!Also applies to: 252-252, 287-294, 308-309
docs/topics/reference.md (1)
29-38: LGTM!Also applies to: 39-118, 119-157, 158-186, 187-266, 267-316, 317-495, 497-552
test/unit/domain/WarpFacade.test.ts (2)
6-43: LGTM!
269-393: LGTM!docs/topics/api/README.md (1)
310-313: 🎯 Functional CorrectnessCheck the
previewJoinsignature here. If it only acceptsdraft, remove the options object.scripts/check-source-backed-reference.ts (2)
12-17: LGTM!
131-157: 📐 Maintainability & Code QualitySearch for stale
captureRootExportsreferences
Check for any remaining script or test imports and rename them tocaptureExports.test/type-check/tsconfig.json (1)
11-17: LGTM!test/type-check/v19-consumer.ts (3)
8-26: LGTM!
43-73: LGTM! The write/read/draft/join round-trip and the three@ts-expect-errornegatives (operation-name literals for both receipt outcome unions, and thedryRunboolean-trap rejection onpreviewJoin) correctly pin the intended public contract, and excess-property checking on the inline{ dryRun: true }literal makes the third negative valid as long asJoinOptionsdoesn't declaredryRun.
86-93: LGTM!test/type-check/v19-first-use.ts (1)
1-36: LGTM! Clean root-only fixture matching the first-use surface (intent,openWarp,readingplus the storage subpath adapter).test/type-check/v19-subpaths.ts (1)
1-60: LGTM! Subpath-only imports (storage/advanced/diagnostics/legacy) correctly stay off the root surface, consistent with#714's requirement to keepStrand/Braid-adjacent and advanced terminology out of first-use.src/domain/api/Intent.ts (1)
1-189: LGTM!src/domain/api/IntentBuilders.ts (1)
1-41: LGTM!src/domain/api/WriteReceipt.ts (1)
29-60: LGTM!src/domain/api/ReadReceipt.ts (1)
1-62: LGTM!src/domain/api/JoinResult.ts (1)
1-27: LGTM!src/domain/api/Timeline.ts (1)
3-33: LGTM on the remaining port-wiring, join-normalization, and operation logic — the dry-run trap, deterministic policy default, and unavailable-runtime guards are all correctly implemented.Also applies to: 42-104, 126-149, 168-196
src/domain/api/JoinReceipt.ts (1)
3-3: 🗄️ Data Integrity & IntegrationCheck for a circular import between
JoinReceipt.tsandDraftTimeline.ts.JoinReceiptusesDraftTimelinein aninstanceofcheck, so any back-reference fromDraftTimelineorDraftTimelineRuntimetoJoinReceipt/JoinResultwould make module init order fragile.src/domain/api/IntentRuntime.ts (1)
1-24: LGTM!src/domain/api/Reading.ts (1)
1-95: LGTM!src/domain/api/ReadingBuilders.ts (1)
1-21: LGTM!src/domain/api/ReadingResult.ts (1)
1-136: LGTM!src/domain/api/ReadingRuntime.ts (1)
1-62: LGTM!src/domain/api/TimelineRuntime.ts (2)
3-22: LGTM!
23-34: 🎯 Functional Correctness
writeIntentstill only emitsaccepted. IfcommitorapplyIntentToPatchcan produceobstructed,conflicted,underdetermined, orrejected, this path needs to map them to receipts instead of letting the promise reject.
|
@codex second opinion requested. Code Lawyer self-audit findings
Verified non-issues during audit:
|
Activity Summary@codex follow-up from the Code Lawyer cleanup pass.
Verified non-issues:
Validation:
Pushed branch: |
Release Preflight
If this PR is from a |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/domain/api/DraftTimelineRuntime.ts (1)
93-134: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winRace window allows concurrent
join()calls to double-commit the same intents.
rejectedJoinPreconditionis a synchronous check, butstate.joinedis only flipped totrueafterawait commitDraftIntents(...)resolves (Line 110). Two concurrentjoinDraftTimelinecalls on the same draft both pass the precondition check before either setsjoined/joinFailed, so both proceed tocommitDraftIntentsand each commits every intent instate.intents— resulting in duplicate commits to the live timeline. The sequential "no replay after failure" fix (joinFailed) only guards retries after a call has already resolved; it does not guard overlapping in-flight calls.🔒 Proposed fix: synchronous in-flight guard
type DraftTimelineState = { readonly runtime: WarpWorldline; readonly draftPatchShas: string[]; readonly intents: Intent[]; readonly joinPatchShas: string[]; joinFailed: boolean; joined: boolean; + joining: boolean; };function rejectedJoinPrecondition( runtime: WarpWorldline, draft: DraftTimeline, state: DraftTimelineState, ): JoinResult | null { if (state.joined) { return rejectedJoin({ runtime, draft, reason: 'Draft has already joined' }); } + if (state.joining) { + return rejectedJoin({ runtime, draft, reason: 'Draft join is already in progress' }); + } if (state.joinFailed) {const rejected = rejectedJoinPrecondition(runtime, draft, state); if (rejected !== null) { return rejected; } - + state.joining = true; const patchShas = await commitDraftIntents(runtime, state); const failed = rejectedIncompleteJoin({ runtime, draft, state, patchShas }); if (failed !== null) { + state.joining = false; return failed; } state.joined = true; + state.joining = false; return acceptedJoin({ runtime, draft, state, patchShas });Also applies to: 196-211
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/domain/api/DraftTimelineRuntime.ts` around lines 93 - 134, Add a synchronous in-flight join guard in the draft state and enforce it within joinDraftTimeline/rejectedJoinPrecondition before the first await, marking the join as in progress before calling commitDraftIntents. Ensure concurrent calls reject without committing, and clear or transition the guard appropriately on success and failure while preserving the existing joinFailed behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/check-source-backed-reference.ts`:
- Around line 241-243: Split the multi-variable declarations in the
source-reference generation function so each const binding—rootSource,
storageSource, diagnosticsSource, and legacySource—appears on its own line,
matching the surrounding one-declaration-per-line style.
---
Outside diff comments:
In `@src/domain/api/DraftTimelineRuntime.ts`:
- Around line 93-134: Add a synchronous in-flight join guard in the draft state
and enforce it within joinDraftTimeline/rejectedJoinPrecondition before the
first await, marking the join as in progress before calling commitDraftIntents.
Ensure concurrent calls reject without committing, and clear or transition the
guard appropriately on success and failure while preserving the existing
joinFailed behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 5d1aed7d-cc52-49aa-bed2-b92e63f52441
📒 Files selected for processing (16)
.github/workflows/links.yml.github/workflows/main-push-release-branch-check.yml.github/workflows/release.yml.lychee.tomlpackage.jsonscripts/check-source-backed-reference.tsscripts/hooks/pre-pushsrc/domain/api/DraftTimelineRuntime.tssrc/domain/api/IntentRuntime.tssrc/domain/api/JoinReceipt.tssrc/domain/api/Timeline.tssrc/domain/api/WriteReceipt.tstest/unit/domain/DraftTimelineRuntime.test.tstest/unit/domain/ReceiptOutcome.test.tstest/unit/domain/WarpFacade.test.tstest/unit/scripts/pre-push-hook.test.ts
💤 Files with no reviewable changes (1)
- .lychee.toml
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: preflight
- GitHub Check: test-node (22)
- GitHub Check: coverage-threshold
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Do not use direct imports fromsrc/infrastructure/**insrc/domain/**orsrc/ports/**; depend on a port instead.
Do not use direct Node built-ins insrc/domain/**orsrc/ports/**; use a port instead.
Files:
test/unit/scripts/pre-push-hook.test.tstest/unit/domain/ReceiptOutcome.test.tstest/unit/domain/DraftTimelineRuntime.test.tssrc/domain/api/WriteReceipt.tssrc/domain/api/JoinReceipt.tssrc/domain/api/IntentRuntime.tssrc/domain/api/Timeline.tstest/unit/domain/WarpFacade.test.tsscripts/check-source-backed-reference.tssrc/domain/api/DraftTimelineRuntime.ts
src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx,js,jsx}: Do not introduceany,as any,as unknown as,unknown(outside adapters),Record<string, unknown>(outside adapters),*Likeplaceholder types,JSON.parse/JSON.stringify(outside adapters),fetch(outside adapters),process.env(outside adapters),@ts-ignore, orz.any()in core code; use validated boundary models and ports instead.
Use constructor-injected ports for external capabilities; do not rely on ambient dependencies for I/O, clocks, persistence, or entropy.
Do not createutils.ts,helpers.ts,misc.ts, orcommon.ts; name files after the actual concept they model.
Prefer one file per class, type, or object; if a file accumulates peer concepts, split it.
Keep helper corridors, fake shape trust, transitional duplication, and compile-time theater out of the codebase; runtime-honest TypeScript must reflect actual behavior.
No enum usage; prefer runtime-backed domain forms and unions.
Do not use boolean trap parameters; prefer named option objects or separate methods.
Avoid magic strings or numbers when a named constant should exist.
Keep domain bytes asUint8Array;Bufferbelongs in infrastructure adapters.
Files:
src/domain/api/WriteReceipt.tssrc/domain/api/JoinReceipt.tssrc/domain/api/IntentRuntime.tssrc/domain/api/Timeline.tssrc/domain/api/DraftTimelineRuntime.ts
src/domain/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/domain/**/*.{ts,tsx,js,jsx}: Insrc/domain/**, do not useDate.now(),new Date(),Date(),performance.now(),Math.random(),crypto.randomUUID(),crypto.getRandomValues(),setTimeout,setInterval, rawnew Error(...)/new TypeError(...), or direct imports from Node built-ins; time, entropy, and external capabilities must enter through ports or parameters, and domain errors should extendWarpError.
Construct domain objects only in core when doing so establishes validated runtime truth; do not build infrastructure adapters, host APIs, persistence implementations, wall clocks, or entropy sources inside core.
Prefer discriminated unions and explicit result types instead of boolean-flag bags, and model expected failures as return values rather than exceptions.
src/domain/must not import host APIs or Node-specific globals; hexagonal architecture boundaries are mandatory.
Domain code must not use the wall clock directly; time must enter through a port or parameter.
Files:
src/domain/api/WriteReceipt.tssrc/domain/api/JoinReceipt.tssrc/domain/api/IntentRuntime.tssrc/domain/api/Timeline.tssrc/domain/api/DraftTimelineRuntime.ts
src/domain/**/!(*.test).{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use explicit domain concepts with validated constructors,
Object.freeze, andinstanceofdispatch; domain objects should be runtime-backed nouns, not ad hoc shape bags.
Files:
src/domain/api/WriteReceipt.tssrc/domain/api/JoinReceipt.tssrc/domain/api/IntentRuntime.tssrc/domain/api/Timeline.tssrc/domain/api/DraftTimelineRuntime.ts
🧠 Learnings (1)
📚 Learning: 2026-03-04T12:08:30.347Z
Learnt from: flyingrobots
Repo: git-stunts/git-warp PR: 63
File: package.json:126-126
Timestamp: 2026-03-04T12:08:30.347Z
Learning: Vitest 4 removes vite-node as a dependency and rewrites its pool system. Do not flag the absence of vite-node in package.json or lockfiles as an error for Vitest 4 projects. Use this as a general guideline: if a project uses Vitest 4, missing vite-node is expected and correct; only flag issues if there is evidence the project is not using Vitest 4 or if vite-node is explicitly required by the project.
Applied to files:
package.json
🔇 Additional comments (18)
scripts/check-source-backed-reference.ts (3)
3-14: LGTM!
235-240: LGTM!Also applies to: 244-264, 274-287
265-273: LGTM!.github/workflows/main-push-release-branch-check.yml (1)
89-92: LGTM!.github/workflows/release.yml (1)
110-113: LGTM!package.json (1)
84-84: LGTM!scripts/hooks/pre-push (1)
57-57: LGTM!test/unit/scripts/pre-push-hook.test.ts (1)
139-139: LGTM!Also applies to: 171-171
.github/workflows/links.yml (1)
22-25: 🗄️ Data Integrity & IntegrationNo conflict with
.lychee.toml..lychee.tomldoesn’t setinclude_fragments, so the new CLI flag is the only setting in play.> Likely an incorrect or invalid review comment.src/domain/api/IntentRuntime.ts (1)
26-69: LGTM!src/domain/api/WriteReceipt.ts (1)
21-27: LGTM!src/domain/api/JoinReceipt.ts (1)
4-4: LGTM!Also applies to: 20-20, 47-62
src/domain/api/Timeline.ts (1)
33-37: LGTM!Also applies to: 110-124, 133-144, 163-227
src/domain/api/DraftTimelineRuntime.ts (1)
11-91: LGTM!Also applies to: 136-158, 185-195, 213-243
test/unit/domain/DraftTimelineRuntime.test.ts (1)
1-81: LGTM!test/unit/domain/ReceiptOutcome.test.ts (1)
1-28: LGTM!test/unit/domain/WarpFacade.test.ts (2)
45-61: LGTM!Also applies to: 388-388
272-308: LGTM!Also applies to: 310-344, 346-395
Activity Summary UpdateFollow-up CodeRabbit pass on
Additional validation on
Pushed branch head: |
Release Preflight
If this PR is from a |
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
test/unit/domain/DraftTimelineRuntime.test.ts (1)
71-114: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winLGTM! Preview materialization and partial-failure/no-replay behavior are well covered. Consider adding a case where
commitPatch(or the intent-application step) throws synchronously outside the "return partial snapshot" path, to lock in thestate.joiningreset guarantee raised insrc/domain/api/DraftTimelineRuntime.ts.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/unit/domain/DraftTimelineRuntime.test.ts` around lines 71 - 114, Add a test covering a synchronous throw from commitPatch or intent application outside the partial-snapshot path, then verify the draft can safely handle a subsequent join attempt with state.joining reset. Place it alongside the existing partial-failure test and use the createRuntime, createDraftTimeline, and joinDraftTimeline helpers to assert the expected rejection and retry behavior.src/domain/api/DraftTimelineRuntime.ts (1)
118-141: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winBlock writes while a join is in progress.
writeDraftIntentstill appends tostate.intentsduringstate.joining, andcommitDraftIntentsiterates that live array. A concurrentdraft.write(...)can be pulled into the in-flight join or make the final length check fail nondeterministically.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/domain/api/DraftTimelineRuntime.ts` around lines 118 - 141, Block or reject writes while a join is in progress: update writeDraftIntent to check state.joining before appending to state.intents, returning the appropriate rejection/error result. Ensure commitDraftIntents uses a stable snapshot of intents captured before the join begins and performs its final length validation against that snapshot, preventing concurrent writes from affecting the in-flight commit.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/domain/api/DraftTimelineRuntime.ts`:
- Around line 118-141: Block or reject writes while a join is in progress:
update writeDraftIntent to check state.joining before appending to
state.intents, returning the appropriate rejection/error result. Ensure
commitDraftIntents uses a stable snapshot of intents captured before the join
begins and performs its final length validation against that snapshot,
preventing concurrent writes from affecting the in-flight commit.
In `@test/unit/domain/DraftTimelineRuntime.test.ts`:
- Around line 71-114: Add a test covering a synchronous throw from commitPatch
or intent application outside the partial-snapshot path, then verify the draft
can safely handle a subsequent join attempt with state.joining reset. Place it
alongside the existing partial-failure test and use the createRuntime,
createDraftTimeline, and joinDraftTimeline helpers to assert the expected
rejection and retry behavior.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0bc9f939-6f70-46dd-ba37-8758c45f7ae3
📒 Files selected for processing (3)
scripts/check-source-backed-reference.tssrc/domain/api/DraftTimelineRuntime.tstest/unit/domain/DraftTimelineRuntime.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
- GitHub Check: coverage-threshold
- GitHub Check: test-node (22)
- GitHub Check: preflight
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx,js,jsx}: Do not use direct imports fromsrc/infrastructure/**insrc/domain/**orsrc/ports/**; depend on a port instead.
Do not use direct Node built-ins insrc/domain/**orsrc/ports/**; use a port instead.
Files:
test/unit/domain/DraftTimelineRuntime.test.tsscripts/check-source-backed-reference.tssrc/domain/api/DraftTimelineRuntime.ts
src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/**/*.{ts,tsx,js,jsx}: Do not introduceany,as any,as unknown as,unknown(outside adapters),Record<string, unknown>(outside adapters),*Likeplaceholder types,JSON.parse/JSON.stringify(outside adapters),fetch(outside adapters),process.env(outside adapters),@ts-ignore, orz.any()in core code; use validated boundary models and ports instead.
Use constructor-injected ports for external capabilities; do not rely on ambient dependencies for I/O, clocks, persistence, or entropy.
Do not createutils.ts,helpers.ts,misc.ts, orcommon.ts; name files after the actual concept they model.
Prefer one file per class, type, or object; if a file accumulates peer concepts, split it.
Keep helper corridors, fake shape trust, transitional duplication, and compile-time theater out of the codebase; runtime-honest TypeScript must reflect actual behavior.
No enum usage; prefer runtime-backed domain forms and unions.
Do not use boolean trap parameters; prefer named option objects or separate methods.
Avoid magic strings or numbers when a named constant should exist.
Keep domain bytes asUint8Array;Bufferbelongs in infrastructure adapters.
Files:
src/domain/api/DraftTimelineRuntime.ts
src/domain/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
src/domain/**/*.{ts,tsx,js,jsx}: Insrc/domain/**, do not useDate.now(),new Date(),Date(),performance.now(),Math.random(),crypto.randomUUID(),crypto.getRandomValues(),setTimeout,setInterval, rawnew Error(...)/new TypeError(...), or direct imports from Node built-ins; time, entropy, and external capabilities must enter through ports or parameters, and domain errors should extendWarpError.
Construct domain objects only in core when doing so establishes validated runtime truth; do not build infrastructure adapters, host APIs, persistence implementations, wall clocks, or entropy sources inside core.
Prefer discriminated unions and explicit result types instead of boolean-flag bags, and model expected failures as return values rather than exceptions.
src/domain/must not import host APIs or Node-specific globals; hexagonal architecture boundaries are mandatory.
Domain code must not use the wall clock directly; time must enter through a port or parameter.
Files:
src/domain/api/DraftTimelineRuntime.ts
src/domain/**/!(*.test).{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use explicit domain concepts with validated constructors,
Object.freeze, andinstanceofdispatch; domain objects should be runtime-backed nouns, not ad hoc shape bags.
Files:
src/domain/api/DraftTimelineRuntime.ts
🔇 Additional comments (14)
scripts/check-source-backed-reference.ts (11)
8-8: LGTM!
41-41: LGTM!
68-68: LGTM!
86-86: LGTM!
128-128: LGTM!
142-142: LGTM!
161-161: LGTM!
172-172: LGTM!
183-183: LGTM!
238-242: LGTM!
264-272: LGTM!src/domain/api/DraftTimelineRuntime.ts (2)
11-19: LGTM!Also applies to: 77-92, 166-176
94-116: 🩺 Stability & Availability
state.joiningdoes not stay stuck on commit failure.commitDraftIntents()already catches commit errors and returns the partial patch list, so thejoiningflag only depends on the local completion/receipt path here.> Likely an incorrect or invalid review comment.test/unit/domain/DraftTimelineRuntime.test.ts (1)
36-69: LGTM! Correctly gates commit interleaving to deterministically prove the guard prevents double-commits.
Code Lawyer Activity SummaryFinal update after the latest push (
Validation:
MERGE GATE: LOCKED 🔒 Blocking reasons:
|
Summary
This PR lands the v19 first-use timeline facade slices after the v19 openWarp closeout audit:
intentbuilders, runtime-backedIntent,Timeline.write(intent), andWriteReceipt.readingbuilders, runtime-backedReading,Timeline.read(reading),ReadReceipt, andReadingResult.DraftTimeline,Timeline.draft(name),Timeline.previewJoin(draft), andTimeline.join(draft)with join receipts. Draft writes are backed by strand overlays; joins replay the recorded public intents into the live timeline.Issue Coverage
Closes #713.
Closes #723.
Closes #725.
Closes #724.
Closes #714.
Part of #712.
Validation
npm run lintnpm run typechecknpm run typecheck:consumernpm run lint:source-backed-referencenpm run lint:mdnpx vitest run test/unit/domain/WarpFacade.test.tsgit diff --checknpm run test:localstable unit shardsNotes
npm run test:localinitially refused to start with 83 MiB free memory and a 512 MiB guard. The pre-push hook reran once memory recovered and completed all stable unit shards successfully.