Skip to content

Phase 0 · 0.A–0.C — monorepo scaffold + strict TS/lint/test spine#1

Merged
cemililik merged 3 commits into
mainfrom
development
Jun 4, 2026
Merged

Phase 0 · 0.A–0.C — monorepo scaffold + strict TS/lint/test spine#1
cemililik merged 3 commits into
mainfrom
development

Conversation

@cemililik

@cemililik cemililik commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Lands Phase 0 workstreams 0.A / 0.B / 0.C — the project's first code: the monorepo + toolchain foundation Phase 1 builds on. Types and tooling, not features.

What's here

  • 0.A Turborepo + pnpm workspace skeleton — private root package.json (pnpm@9.12.3 pinned), .nvmrc, .npmrc, pnpm-workspace.yaml, turbo.json (build/lint/typecheck/test + globalDependencies). Directory skeleton per project-structure.md; only @relavium/shared is built out, the rest are README-only placeholders.
  • 0.B Strict tsconfig.base.json (strict + noUncheckedIndexedAccess + exactOptionalPropertyTypes + noImplicitOverride + verbatimModuleSyntax + isolatedModules + moduleResolution: bundler); @relavium/shared has a build/typecheck split. Strictness verified load-bearing.
  • 0.C Root ESLint flat config (no-explicit-any + no-floating-promises as errors, scoped to the TS family with projectService; disableTypeChecked for JS), Prettier (the docs/ house style is governed separately), and a workspace-aware Vitest with V8 coverage.

Hardening pass (2nd commit)

After a three-pass review + adversarial re-verification of every finding against the real toolchain:

  • ESLint .tsx/.mts/.cts no longer crash type-aware lint (the unscoped typed config would have failed packages/ui lint entirely at 0.H); JS gets disableTypeChecked; config files ignored at any depth.
  • lint now dependsOn: ["^build"] (cross-package type-aware lint at 0.D); .nvmrc + pnpm-workspace.yaml added to globalDependencies; a //#format:check turbo root task.
  • noEmit hardening + *.spec.ts build-leak exclude; Vitest include pinned to **/*.test.ts; a root coverage script (closes 0.C's "branch coverage reported").

Verification (green from a fresh checkout)

pnpm install && pnpm turbo run lint typecheck test build ✅ · pnpm format:check ✅ · pnpm coverage ✅ (V8 branch coverage). The lint + strictness gates are proven load-bearing (any, a floating promise, and noUncheckedIndexedAccess all error; .tsx reports both non-negotiables with no crash).

Scope

In: 0.A, 0.B, 0.C. Still open before M0: 0.D/0.E (Zod schemas — critical path), 0.F (seam fence), 0.G (CI), 0.H (docs), 0.I (@relavium/db).

🤖 Generated with Claude Code

Summary by Sourcery

Scaffold the initial monorepo toolchain and shared package, establishing strict TypeScript, linting, formatting, and testing foundations for future phases.

New Features:

  • Introduce a Turborepo- and pnpm-based workspace with root scripts for build, lint, typecheck, test, coverage, and formatting.
  • Add the initial @relavium/shared package as the dependency root, exposing a versioned schema scaffold and package-level build/test scripts.

Enhancements:

  • Configure a strict root TypeScript base config to standardize compiler options across packages.
  • Add a root ESLint flat config with type-aware rules for TypeScript, JS-safe defaults, and Prettier compatibility.
  • Introduce a root Vitest configuration with V8 coverage and a repo-wide test harness.
  • Document the status of Phase 0 workstreams and add README placeholders for planned packages and apps to define the future workspace layout.

Documentation:

  • Update the current roadmap to reflect that the monorepo scaffold (Phase 0 workstreams 0.A–0.C) is landed and green, and clarify the next active workstreams.

Tests:

  • Add a workspace-wide Vitest setup and an initial test file in @relavium/shared aligned with the project’s testing conventions.

Summary by CodeRabbit

  • Chores

    • Configured monorepo tooling: package manager & Node version, workspace layout, shared scripts, linting, formatting, TypeScript baseline, build orchestration, and test runner/coverage.
  • Documentation

    • Added placeholder READMEs for apps/packages and updated the project roadmap with current Phase 0 status.
  • Tests

    • Added workspace test configuration and a basic shared-package verification.

cemililik and others added 2 commits June 4, 2026 13:06
…e lint/format/test spine (Phase 0 · 0.A–0.C)

The project's first code: the foundation Phase 1 builds on — types and tooling, not
features. `pnpm install && pnpm turbo run lint typecheck test build` is green and
`format:check` is clean from a fresh checkout.

0.A — Turborepo + pnpm workspace skeleton: private root package.json (pnpm@9.12.3
pinned via packageManager), .nvmrc, .npmrc (auto-install-peers), pnpm-workspace.yaml
(packages/* + apps/*), turbo.json (build/lint/typecheck/test + globalDependencies so a
root-config change busts caches). Directory skeleton from project-structure.md:
packages/{shared,llm,core,db,ui} + apps/{desktop,vscode-extension,cli}; only shared is
built out — the rest are README-only placeholders (no package.json) per the
no-over-scaffolding rule, so pnpm/Turborepo ignore them until their phase.

0.B — strict tsconfig.base.json: strict + noUncheckedIndexedAccess +
exactOptionalPropertyTypes + noImplicitOverride + verbatimModuleSyntax + isolatedModules
+ moduleResolution bundler. @relavium/shared extends it with a build/typecheck split
(tsconfig.build.json emits dist, excludes tests; tsconfig.json type-checks everything).
Strictness verified load-bearing (a removed flag yields TS18048).

0.C — root spine: ESLint flat config (typescript-eslint typed rules; no-explicit-any
and no-floating-promises as errors; the seam fence via built-in no-restricted-imports
is 0.F), Prettier (docs/ + markdown governed by documentation-style.md, not Prettier),
and a workspace-aware Vitest config with V8 coverage. Lint gate verified load-bearing
(an any and a floating promise both error).

@relavium/shared is a real, buildable package exporting SCHEMA_VERSION; the full Zod
schema set lands in 0.E. All added dependencies are devDependencies (the
tech-stack-pinned toolchain) — no runtime dependency added, so no ADR required.

Refs: docs/roadmap/phases/phase-0-foundations.md (0.A, 0.B, 0.C)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…slint TS-family scoping, lint ^build, format:check task, coverage)

Acts on a three-pass review of the scaffold after adversarially re-verifying every
finding against the real toolchain (one report was stale; one "HIGH" was a false
positive — corrected below). All fixes proven green: lint/typecheck/test/build +
format:check + coverage, with live .tsx/.js ESLint probes.

- ESLint (the real bug): type-aware rules (recommendedTypeChecked) + projectService +
  the no-explicit-any / no-floating-promises errors were scoped to `**/*.ts`, so
  .tsx/.mts/.cts got type-aware rules with NO project and ESLint hard-crashed (exit 2)
  the moment such a file was linted — packages/ui (.tsx) would have failed lint entirely
  at 0.H. Now the typed config is scoped to `**/*.{ts,tsx,mts,cts}` with projectService;
  `disableTypeChecked` covers `**/*.{js,jsx,mjs,cjs}` (no crash on JS); config files are
  ignored at any depth via `**/*.config.*` (a bare `*.config.*` matched only the repo
  root, so a nested per-package vitest/tsup config would crash type-aware lint). Proven:
  a .tsx inside a tsconfig reports BOTH non-negotiable errors with no crash; a nested
  config is ignored; a .js does not crash. (The review's "no-explicit-any silently
  downgrades to warn on .tsx" was FALSE — recommendedTypeChecked already pins it to
  error; the real failure mode was the crash.)
- turbo.json: `lint` now `dependsOn: ["^build"]` — type-aware lint resolves a
  dependency's types via its built dist/*.d.ts, so without this the first cross-package
  @relavium/* import at 0.D would lint against absent/stale types on a clean checkout.
  Added .nvmrc + pnpm-workspace.yaml to globalDependencies. Added a `//#format:check`
  root task so `pnpm turbo run format:check` resolves and caches (Prettier is repo-global
  → a root task, not per-workspace, is the correct design).
- tsconfig: noEmit:true in packages/shared/tsconfig.json + noEmit:false in
  tsconfig.build.json (emit is a config property now, not reliant on the --noEmit flag);
  build excludes *.spec.ts as well as *.test.ts. Vitest include pinned to `**/*.test.ts`
  (Vitest's default also matches *.spec.ts, which the build did not exclude — a dist-leak
  path).
- Added a root `coverage` script (`vitest run --coverage`) so 0.C's "branch coverage
  reported" acceptance has an invokable command (was configured but never run).
- .npmrc: keep strict-peer-dependencies=false locally (Phase-1 surface packages pull
  React/Tauri/provider-SDK peers not all present at once → a hard local `true` would
  break fresh installs); peer drift is caught by a CI-only strict gate (0.G). Documented.

Refs: docs/roadmap/phases/phase-0-foundations.md (0.A, 0.B, 0.C)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Reviewer's Guide

Sets up the initial monorepo/tooling spine (Turborepo + pnpm workspace) with strict shared TypeScript config, a root ESLint/Prettier/Vitest configuration, and a minimal but fully buildable @relavium/shared package, plus roadmap/docs updates to reflect Phase 0.A–0.C as landed and green.

File-Level Changes

Change Details Files
Establish Turborepo + pnpm-based monorepo root with workspace wiring and tooling scripts.
  • Add private root package.json with turbo-based build/lint/typecheck/test scripts, coverage and formatting commands, and pinned pnpm/node versions
  • Define pnpm-workspace.yaml to include packages/* and apps/* as workspaces
  • Introduce Turbo configuration to orchestrate build, lint, typecheck, and test across packages, including globalDependencies and lint depending on build
  • Add repo-level tooling files such as pnpm lockfile, Node version file, npm config, and Prettier config/ignore
package.json
pnpm-workspace.yaml
turbo.json
pnpm-lock.yaml
.nvmrc
.npmrc
.prettierrc.json
.prettierignore
Introduce strict shared TypeScript configuration and hook it into the shared package build/test pipeline.
  • Create tsconfig.base.json with strict compiler options (strict, noUncheckedIndexedAccess, exactOptionalPropertyTypes, noImplicitOverride, verbatimModuleSyntax, isolatedModules, bundler moduleResolution)
  • Add package-level tsconfig.json for @relavium/shared that extends the base config, sets rootDir/outDir, enables noEmit, and scopes includes to src/**/*.ts
  • Add tsconfig.build.json for @relavium/shared to produce dist output while excluding tests and ensuring noEmit hardening
tsconfig.base.json
packages/shared/tsconfig.json
packages/shared/tsconfig.build.json
Set up a single root ESLint flat config with type-aware TS rules and Prettier compatibility.
  • Create eslint.config.mjs using @eslint/js, globals, typescript-eslint, and eslint-config-prettier
  • Scope recommendedTypeChecked configs to TS-family files with projectService and node globals configured
  • Apply strict lint rules forbidding explicit any and floating promises as errors
  • Disable type-checked rules for JS-family files to avoid projectless crashes and ignore build/coverage/node_modules and config files at any depth
eslint.config.mjs
Configure Vitest as a root, workspace-aware test runner with V8 coverage and aligned test-file conventions.
  • Add vitest.config.ts defining a node environment and V8 coverage provider with text/html/lcov reporters
  • Restrict test discovery to **/*.test.ts so runner and build tsconfigs stay aligned and *.spec.ts cannot leak into dist
  • Add root coverage script wired to Vitest run with coverage enabled
vitest.config.ts
package.json
Create the initial @relavium/shared package as the dependency root with build, lint, typecheck, and test wiring plus a minimal public API.
  • Add @relavium/shared package.json with module/typings exports, dist-only files list, and build/typecheck/lint/test scripts
  • Implement src/index.ts exporting a versioned SCHEMA_VERSION constant and its inferred type, with documentation emphasizing curated exports and upcoming schemas
  • Add a placeholder test file in src to exercise the Vitest and typechecking pipeline
  • Document package conventions and status in a README, including its role as the single source of truth for schemas and strict TS expectations
packages/shared/package.json
packages/shared/src/index.ts
packages/shared/src/index.test.ts
packages/shared/README.md
Document future packages/apps as directory placeholders without workspace participation yet.
  • Add README placeholders for core engine, db, llm abstraction, shared UI, desktop app, CLI, and VS Code extension, explicitly noting they lack package.json so are not yet part of the workspace graph
  • Align each placeholder with its respective roadmap phase and architecture/reference docs
packages/core/README.md
packages/db/README.md
packages/llm/README.md
packages/ui/README.md
apps/desktop/README.md
apps/cli/README.md
apps/vscode-extension/README.md
Update roadmap documentation to reflect that Phase 0 workstreams 0.A–0.C (monorepo + tooling) are landed and green, and to clarify current focus.
  • Revise current roadmap status text to describe the monorepo scaffold, strict tsconfig base, root ESLint/Prettier/Vitest spine, and buildable @relavium/shared package
  • Mark 0.A/0.B/0.C as completed and identify 0.D/0.E as the active next workstreams
  • Clarify that Phase 0 focuses on types/tooling and that CI/DB/docs workstreams remain open before M0
docs/roadmap/current.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7fb62319-0759-4afe-80ef-2a0820392d46

📥 Commits

Reviewing files that changed from the base of the PR and between db249e5 and 7f898c3.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • eslint.config.mjs
  • package.json
  • packages/shared/package.json
  • packages/shared/tsconfig.build.json
  • packages/shared/tsconfig.json
  • pnpm-workspace.yaml
  • tsconfig.base.json
✅ Files skipped from review due to trivial changes (1)
  • packages/shared/tsconfig.build.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • package.json
  • eslint.config.mjs

📝 Walkthrough

Walkthrough

This PR establishes the monorepo scaffolding: Node/pnpm and Prettier configs, pnpm workspace/catalog, strict TypeScript baseline, root package.json with Turbo scripts, ESLint flat config with TS overrides, Vitest workspace config with V8 coverage, and bootstraps @relavium/shared with a pinned SCHEMA_VERSION and test; adds placeholder READMEs and roadmap updates.

Changes

Monorepo Scaffold and Shared Package

Layer / File(s) Summary
Baseline monorepo configuration
.npmrc, .nvmrc, .prettierignore, .prettierrc.json, pnpm-workspace.yaml
Node version pinned to 22; pnpm auto-install-peers enabled with strict-peer-dependencies=false for local installs; Prettier configured (semicolons, single quotes, trailing commas: all, print width 100, tab width 2, LF endings) and ignore list updated; pnpm workspace globs and catalog defined.
TypeScript compiler baseline
tsconfig.base.json
Repository-wide strict TypeScript baseline: target ES2022, lib ES2023, module/moduleResolution NodeNext, moduleDetection: "force", strict and multiple safety flags, declaration/sourceMap output enabled.
Root package manifest and dependencies
package.json
Root private ESM package with Node/pnpm engine constraints, Turbo-based scripts for build/lint/typecheck/test/ci, format scripts, and devDependencies for ESLint, Prettier, TypeScript, Turbo, and Vitest (coverage).
Build, lint, and test orchestration
turbo.json, eslint.config.mjs, vitest.config.ts
Turbo pipeline with globalDependencies and task outputs; ESLint flat config applies recommendedTypeChecked for TypeScript files, pins no-explicit-any and no-floating-promises as errors, and disables type-checked rules for JS files; Vitest runs in node, includes **/*.test.ts only, enables V8 coverage reporters (text/html/lcov) to ./coverage, and allows passing with no tests.
@relavium/shared package bootstrap
packages/shared/package.json, packages/shared/tsconfig.json, packages/shared/tsconfig.build.json, packages/shared/src/index.ts, packages/shared/src/index.test.ts, packages/shared/README.md
ESM package @relavium/shared with exports mapping to dist JS/types, build and typecheck configs (separate build tsconfig), initial SCHEMA_VERSION: '1.0' export with inferred SchemaVersion type, and a Vitest test asserting the version; README documents package role and Phase 0 status.
Package/app scaffolding documentation and roadmap
apps/cli/README.md, apps/desktop/README.md, apps/vscode-extension/README.md, packages/core/README.md, packages/db/README.md, packages/llm/README.md, packages/ui/README.md, docs/roadmap/current.md
Placeholder READMEs for non-built packages/apps describing scope and explicit "not built yet" + no package.json to avoid workspace inclusion; roadmap updated (Last updated date and status text) noting Phase 0.A–C landed and active focus on 0.D→0.E (Zod schemas).

Sequence Diagram — Tooling flow:

sequenceDiagram
  participant RootPackage as package.json
  participant Turbo as turbo.json
  participant ESLint as eslint.config.mjs
  participant Vitest as vitest.config.ts
  RootPackage->>Turbo: run scripts (build/lint/test)
  Turbo->>ESLint: execute lint task using eslint.config.mjs
  Turbo->>Vitest: execute test task using vitest.config.ts (coverage)
  ESLint->>ESLint: apply TypeScript-specific overrides for .ts/.tsx
Loading

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 Hop along, the toolchain is spun,
Monorepo foundation all set and done!
Shared schemas await on the path ahead,
Phase zero complete—let's build what we said! 🛠️✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main deliverables of the PR: Phase 0 work (0.A–0.C) establishing the monorepo scaffold and strict TypeScript/lint/test toolchain, which aligns with the actual changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch development

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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request scaffolds the Relavium monorepo using Turborepo and pnpm, establishing root configurations for ESLint, Prettier, TypeScript, and Vitest, alongside a buildable @relavium/shared package and placeholders for future packages and applications. Feedback on these changes highlights several key improvement opportunities: first, updating moduleResolution and module to NodeNext in the base TypeScript configuration to enforce explicit file extensions and prevent runtime ESM resolution crashes; second, explicitly declaring typescript and eslint in @relavium/shared's devDependencies to ensure robust script execution in a strict pnpm workspace; and third, scoping globals.node in the ESLint configuration more narrowly to prevent unsafe Node-specific globals from leaking into frontend packages.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread tsconfig.base.json Outdated
Comment on lines +7 to +8
"module": "ESNext",
"moduleResolution": "bundler",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using "moduleResolution": "bundler" allows extensionless relative imports (e.g., import { foo } from './utils') and directory index imports to compile without errors.

However, since @relavium/shared (and other packages like @relavium/core or apps/cli) are compiled directly with tsc to ESM and executed in Node.js (which strictly requires explicit file extensions for relative imports in ESM mode), any extensionless imports will compile successfully but crash at runtime with ERR_MODULE_NOT_FOUND.

To enforce strict ESM import path compliance at compile time and prevent runtime resolution crashes, consider using "moduleResolution": "NodeNext" and "module": "NodeNext" instead. If "bundler" is required for frontend/Tauri packages, consider overriding it in those specific packages' tsconfig.json files.

Suggested change
"module": "ESNext",
"moduleResolution": "bundler",
"module": "NodeNext",
"moduleResolution": "NodeNext",

Comment on lines +24 to +26
"devDependencies": {
"vitest": "^3.0.0"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The package scripts invoke tsc and eslint directly, but these packages are not declared in devDependencies.

In a strict pnpm workspace, relying on root-hoisted binaries can be fragile and may fail if hoisting is restricted or if the package is built/linted in isolation. It is a best practice to explicitly declare typescript and eslint in the package's own devDependencies to ensure they are always available in the package's local .bin path.

  "devDependencies": {
    "eslint": "^9.17.0",
    "typescript": "^5.7.2",
    "vitest": "^3.0.0"
  }

Comment thread eslint.config.mjs Outdated
Comment on lines +41 to +43
globals: {
...globals.node,
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Applying globals.node globally to all files in the TS family (**/*.{ts,tsx,mts,cts}) is unsafe for frontend packages like packages/ui (React components) and apps/desktop (Tauri frontend). It allows Node-specific globals (like process or Buffer) to be used in browser/UI code without lint errors, which will cause runtime crashes in the browser.

Consider scoping Node.js globals to Node-specific packages/files, or adding globals.browser for .tsx files and frontend packages.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • In packages/shared/tsconfig.json, outDir is configured but noEmit: true prevents output; consider either removing outDir from the typecheck config or splitting emit/no-emit concerns more clearly between tsconfig.build.json and tsconfig.json to avoid confusion.
  • You currently declare vitest both at the repo root and in packages/shared; if all packages will rely on the same runner version, consider centralizing vitest at the workspace root (or using a workspace protocol reference) to reduce version-drift risk.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `packages/shared/tsconfig.json`, `outDir` is configured but `noEmit: true` prevents output; consider either removing `outDir` from the typecheck config or splitting emit/no-emit concerns more clearly between `tsconfig.build.json` and `tsconfig.json` to avoid confusion.
- You currently declare `vitest` both at the repo root and in `packages/shared`; if all packages will rely on the same runner version, consider centralizing `vitest` at the workspace root (or using a workspace protocol reference) to reduce version-drift risk.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

…globals cleanup, tsconfig emit split, pnpm catalog

Each finding was reproduced/refuted against the real toolchain before acting.

- moduleResolution (real, the important one): the base used `bundler`, which lets an
  extensionless relative import (`import './x'`) typecheck clean — but `@relavium/shared`
  is compiled with `tsc` and consumed as real ESM, so that would crash with
  ERR_MODULE_NOT_FOUND in Node. Switched the base to `module`/`moduleResolution`:
  `NodeNext`, which rejects it at compile time (TS2835, "Did you mean './x.js'?").
  Proven: an extensionless import now errors; the existing code (already using `./x.js`)
  builds clean. Vite-bundled surfaces (packages/ui, apps/desktop frontend, apps/portal)
  override back to `bundler` in their own tsconfig at 0.H+.
- ESLint globals (partly real, wrong mechanism): the review feared blanket `globals.node`
  lets Node globals into browser code "without lint errors". But type-aware linting
  disables `no-undef` for TS (verified: resolves to [0]), so `globals.node` was inert and
  misleading; the real platform boundary is each package's tsconfig `types`/`lib`
  (`process` already errors TS2591 under shared's `types: []`). Removed the blanket
  `globals.node` (and the now-unused `globals` dep) and documented per-surface globals.
- tsconfig emit/typecheck split (real, minor): moved `rootDir`/`outDir` to
  tsconfig.build.json so tsconfig.json is purely the typecheck config (`noEmit` only).
- dep hygiene (real, minor): adopted a pnpm `catalog` as the single source of truth for
  dev-tool versions (no cross-package drift), and `@relavium/shared` now declares the
  tools its scripts invoke (typescript, eslint, vitest) so per-package isolation holds —
  verified `pnpm --filter @relavium/shared run typecheck/lint` work standalone.

Gate green: lint/typecheck/test/build + format:check + coverage (100% branch).

Refs: PR #1
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@cemililik cemililik merged commit 3a398e0 into main Jun 4, 2026
2 checks passed
cemililik added a commit that referenced this pull request Jun 4, 2026
…ings

Phase 0 — Foundations is done: all workstreams 0.A–0.I merged (PR #1#3), achieving
milestone M0. Reflect that across the roadmap and entry docs:
- phase-0-foundations.md: status -> Complete; 0.F–0.I marked done; the 0.M3/M0 milestone
  done; exit criterion #7 lists better-sqlite3 (ADR-0021).
- current.md: Where-we-are / What-is-active / next-steps now point at Phase 1
  (@relavium/llm seam + @relavium/core engine); M1 is the next checkpoint.
- roadmap/README.md milestone spine: M0 done; root README + CLAUDE.md status updated.

Adds docs/roadmap/deferred-tasks.md: every confirmed-but-deferred finding from the
97-agent comprehensive review, as discrete checkable tasks (decisions, schema/test depth,
tooling, docs, packaging) so none get lost. None blocked M0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cemililik added a commit that referenced this pull request Jun 16, 2026
1.U is the proof the engine works end-to-end before any surface exists. It composes
the already-landed pieces behind the @relavium/llm seam (1.K FallbackChain, 1.N run
loop + RunEventBus, 1.O AgentRunner, 1.P node handlers, 1.Q human gate, 1.R
checkpoint/resume, 1.S node retry, 1.T ToolRegistry) on the in-memory ExecutionHost
reference — zero platform imports, no live network/keys, deterministic. No engine
code and no new ADR: the harness uses only already-exported @relavium/core symbols.

A scenario suite (the seed the Phase-2 CLI regression harness 2.K grows from):
- happy-path — the literal 3-node input -> agent(+tool call) -> output: live token
  streaming, per-attempt cost (attributed to the model), a gap-free sequenceNumber
  stream that validates against the canonical RunEventSchema.
- flagship — input -> agent -> human_gate -> output: in ONE run across a process
  boundary, the agent's forced provider error -> node retry (ADR-0040) -> failover to
  the second chain entry (1.K), per-attempt cost attributed to the fallback model;
  then a pause at the gate (the durable mid-run checkpoint persisted to the
  SQLite-shaped store); then a FRESH engine resumes via resumeFromCheckpoint, runs
  output to run:completed, and reproduces the final output with sequenceNumber
  continuing gap-free. The agent is NOT re-run on resume (its output is restored).
- determinism — a re-run yields an identical event signature + final output (the
  no-wall-clock/no-RNG ban the risk table binds to the harness).

Design decision (maintainer-approved): the resume demonstration uses a human gate as
the durable suspend point, because the Phase-1 engine resumes ONLY from a gate/budget
pause — a gate-less interrupted run is reconciled to run:failed (ADR-0036; verified by
the resume-model review + an adversarial refutation). The literal 3-node topology is
preserved by the happy-path member; the flagship adds the gate. Recorded as the §1.U
"Harness shape" clarification in the phase plan (no new ADR — composes decided
mechanisms). Exit criterion #1 annotated to point resume at the gated flagship.

Per-attempt cost is asserted as distinct cost:updated events (not only the terminal
cumulative); all LLM cost is incurred pre-gate, so the plain-human-gate cost-restore
deferral (deferred-tasks.md) is off this path.

1.U / M2 will be marked Done only after this PR merges (roadmap-done-after-merge).
Full gate (format/lint/typecheck/test/build) green — core 683 tests; Leakwatch clean.

Refs: §1.U, M2, ADR-0036, ADR-0040, ADR-0003

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cemililik added a commit that referenced this pull request Jun 16, 2026
…che)

A multi-dimensional Sonnet review (7 dimensions, adversarial refute-by-default verify)
surfaced 18 findings; 16 confirmed, 2 refuted. Fixed 15 (skipped 1 — see end). No product
behavior changed: test strengthening, code/doc comments, a CI cache step.

Test hardening (the meaningful ones):
- checkpoint.test.ts: the new node:completed cost-restore test was tautological for the
  Math.max reconciliation (a bare assignment would pass). Added two interaction tests over
  BOTH durable cost sources — incl. one (budget:paused 900 → node:completed 800 → 900) that
  gives Math.max teeth (a bare-assign would yield 800 and fail it). Clarified that the
  pre-existing "cost tallies" test exercises the fold's cost:updated arm (a defensive branch;
  cost:updated is streamed, not persisted — the production path is node:completed).
- m2-harness: tightened the under-constrained cost-count asserts to exact counts
  (happy-path === 2 tool+answer turns; flagship === 1 successful fallback — a double-charge
  or missing tool-turn cost would now fail); replaced the tautological node:retrying
  `.retryable === true` with the classified `.error.code === 'provider_unavailable'`; added a
  direct assertion that the checkpointed `work` node is NOT re-dispatched on resume; collapsed
  nodeOutput's double array scan to a single find.

Docs / comments (accuracy):
- checkpoint.ts: the budget:paused comment called cost-event persistence "the deferred
  general fix" — it landed; rewrote it + the CheckpointState JSDoc to describe both durable
  sources + the Math.max reconciliation.
- phase-1: exit criterion #1 no longer self-contradicts ("3-node" now names only the
  happy-path member; resume rides the gated flagship); added 1.AB to the §1.U composing-list
  (the harness needs the ExpressionSandbox). Same 1.AB addition in the harness header.
- CLAUDE.md: the status blurb was one giant **…** span with nested **…** that GFM can't
  render; scoped the bold to "Status:" so the inner emphases render.
- spec.ts: documented the toolLoop test's scope (asserts the call→result→continuation FLOW;
  the provider tool_result WIRE shape is asserted by the per-adapter unit tests).
- vitest.config.ts: corrected the stale "coverage not yet wired into CI / tracked in
  deferred-tasks" comments (it is now the advisory ci.yml job).

CI:
- The coverage job now restores the .turbo cache (like `ci`), so its build is a warm hit
  rather than a cold rebuild.

Skipped: the nit that commit 15a5b0e used a bare `test:` type without a scope — it is already
pushed; a history rewrite on a shared branch is unwarranted for a nit (future commits scope).

Full gate (format/lint/typecheck/test/build) green; `pnpm coverage` EXIT 0 (floor holds);
Leakwatch clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cemililik added a commit that referenced this pull request Jun 18, 2026
…ects (review HIGH #1/#2)

A multi-dimensional adversarial review of P1+P2 confirmed two HIGH defects on
the production (store-injected) de-inline path that the prior reviews missed:

- I3 BYTE LEAK (HIGH #1): deInlineMedia's rewrite only handled the canonical
  {type:'media'} part, so a non-canonical byte carrier in an opaque z.unknown()
  run-event position — a base64 data: URI string, a loose {kind:'base64'}
  source, a raw binary buffer — passed THROUGH and persisted/delivered (the
  with-store branch had no re-scan; the run-event positions have no byte
  backstop). Fix: deInlineMedia now HARD-FAILS on every non-canonical carrier
  (data: URI / loose base64 / raw buffer) and on an unknown source kind /
  unknown modality — it can only ever emit handles + text, never pass bytes.

- TERMINAL NOT TOTAL (HIGH #2): #emitDurable only rescued the
  media_store_unavailable throw on a terminal; a store.put rejection (disk full)
  or any other de-inline throw on a media-bearing terminal escaped the
  catch-less #loop → no terminal, consumer hang, unhandled rejection. Fix: the
  terminal catch now strips the best-effort media payload on ANY de-inline
  failure (re-throws only for non-terminal drafts), so the run always settles.

- url MEDIUM: add containsDurableUnsafeMedia (the byte scan + a url media part),
  used by the de-inline fast-path + the no-store guard, so a url-only payload
  is never silently passed through (it now hard-fails pending the D9 re-host).

Regression tests: non-canonical carriers + url-only hard-fail (no leak/put);
a data: URI node output fails the run with no bytes persisted even WITH a store;
a rejecting store.put yields exactly one terminal (no hang); decodeBase64 +
containsDurableUnsafeMedia direct unit tests; the ADR-0042 §2 reconcile
media-free backstop. Also fixes the stale #emitDurable ordering comment.

Refs: ADR-0042, ADR-0043

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
cemililik added a commit that referenced this pull request Jun 23, 2026
…xt pickup 2.C

PR #44 merged: durable local run history via @relavium/db (the SQLite RunStore writer +
read API + ADR-0050 at-rest posture) is live.

- phase-2-cli.md: §2.H header ✅ Done (PR #44); status line records 2.H Done (ADR-0050); the
  "Remaining build order" queue drops the completed 2.H row, renumbers (2.C is now #1), and
  the gate-closing backbone is 2.C → 2.E → 2.G → 2.I → 2.L (2.K + 2.H done).
- current.md: 2.H ✅ Done; "Next pickup: 2.C" (provider/keys).
- CLAUDE.md + README.md: Phase-2 status sentence records durable run history landed.

Next pickup is 2.C (provider/keys) — independent, unblocks 2.R + 2.M + live runs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cemililik added a commit that referenced this pull request Jun 23, 2026
…xt pickup 2.E

PR #45 merged. Provider/key commands (the `relavium provider` registry + API keys in the OS keychain
via @napi-rs/keyring, resolved keychain → RELAVIUM_<PROVIDER>_API_KEY env var → error) are shipped.
No new ADR (secrets.enc deferred past v1.0; @napi-rs/keyring pre-authorized by ADR-0019).

- phase-2-cli.md: 2.C heading + status header + Remaining-build-order status line all marked ✅ Done
  (PR #45); the build-order table drops the 2.C row, renumbers (2.E now #1), and flips 2.C → ✓ in the
  MCP/chat blocker cells; the gate-closing backbone shrinks to `2.E → 2.G → 2.I → 2.L` (2.C joins
  2.K + 2.H as done).
- current.md: 2.C added to the Landed list (behind ADR-0019 + ADR-0006); next pickup → 2.E; date bump.
- CLAUDE.md + README.md: status paragraphs updated (2.C landed; next pickup 2.E).

Refs: phase-2-cli.md 2.C, ADR-0019, ADR-0006
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cemililik added a commit that referenced this pull request Jun 24, 2026
…xt pickup 2.G

PR #46 merged. The ink streaming TUI is shipped — the third RunRenderer over the one event bus (live
per-node status + spinners, the active node's streaming tokens, a running cost footer, a persistent final
summary), with cooperative Ctrl-C cancel (the native-AbortController + persistent-SIGINT + abort→cancelled
chain). Behind ADR-0047 (ink ^6.8.0 + React 19, confined to apps/cli); no new ADR.

- phase-2-cli.md: 2.E heading + status header + Remaining-build-order status line all marked ✅ Done
  (PR #46); the build-order table drops the 2.E row, renumbers (2.G now #1), and flips 2.E → ✓ in the
  2.G + chat blocker cells; the gate-closing backbone shrinks to `2.G → 2.I → 2.L` (2.E joins
  2.K + 2.H + 2.C as done).
- current.md: 2.E added to the Landed list (behind ADR-0047); next pickup → 2.G; date bump (2026-06-24).
- CLAUDE.md + README.md: status paragraphs updated (2.E landed; next pickup 2.G).

Refs: phase-2-cli.md 2.E, ADR-0047
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cemililik added a commit that referenced this pull request Jun 24, 2026
…xt pickup 2.I

2.G (interactive human-gate prompt + `relavium gate` cross-process resume) merged via PR
#47, fully closing 2.K's deferred gate-resume half. Flip the status surfaces:

- phase-2-cli.md: §2.G heading → Done; status header + Remaining-build-order status line →
  add 2.G; the build-order table drops the 2.G row and renumbers (2.I now #1, 2.L #2, 2.S
  #3, …); the gate-closing backbone shrinks to `2.I → 2.L`; the §2.K deferred gate-resume
  note → landed.
- current.md: 2.G added to Landed; next pickup → 2.I.
- CLAUDE.md + README.md: 2.G landed; next pickup 2.I.

The structural views (dependency matrix, ordered waves, Mermaid graphs) are the
from-scratch plan, not a live tracker, so they keep 2.G as a graph node unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cemililik added a commit that referenced this pull request Jun 24, 2026
…nstall path

Two defects in the 2.L packaging (ADR-0051), each of which would block or spoil the first
publish; both surfaced after the tag-triggered Release CLI run.

1. `relavium --version` reported the hardcoded `0.0.0` sentinel, never the package version —
   it was never wired to package.json (the program.ts comment deferred it to "packaging (2.L)").
   tsup now injects the manifest version at build time via a `__RELAVIUM_CLI_VERSION__` esbuild
   `define`; program.ts reads it behind a `typeof` guard and falls back to `0.0.0-dev` on a
   source run (tsx/vitest, no define). Bundled `relavium --version` → `0.1.0`; source → `0.0.0-dev`.

2. The cross-OS install-smoke failed on ubuntu/macOS/Windows: `npm install -g
   artifact/relavium-X.tgz` — a slash-bearing arg without `./` — is read by npm as a GitHub
   `owner/repo` shorthand and git-cloned (`Permission denied (publickey)`), never as the local
   tarball. Prefix with `./` so npm classifies it as a file spec (verified via npm-package-arg:
   bare → git, `./` → file). The publish job is gated on green smoke, so nothing was published.

Also assert `relavium --version == package.json` in the smoke matrix so a version-wiring
regression is caught before publish — the old smoke only ran `--help`, which is why #1 slipped.

Refs: ADR-0051

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
cemililik added a commit that referenced this pull request Jun 25, 2026
…eck off discharged deferrals

PR #52 (2.S — media host-wiring) merged 2026-06-25. Post-merge follow-up (deliberately held per the
done-after-merge convention):

- current.md: 2.S added to the Landed list (✅ PR #52, behind ADR-0042–0046, no new ADR; read_media
  deferred to 2.M); next pickup flipped 2.S → 2.R.
- phase-2-cli.md: top status line, the 2.S section Status banner, the acceptance/outcome row, the
  remaining-build-order Status line + Next/Lane table (2.R now #1, 2.S moved to a ✅ row), the
  "four additive lanes" → three, and the 2.S-timing judgement-call prose all reflect 2.S Done + 2.R next.
- CLAUDE.md: status paragraph — 2.S landed (PR #52), next pickup 2.R.
- deferred-tasks.md: checked off the D-items 2.S discharged — durable fail-cost (node:failed/run:failed/
  run:cancelled), D15 (catalog load-check wired on run/gate), D17 (media_cost_estimate threaded), D8
  (resolveForEgress injected), the CAS-orphan sweep, and the clean-terminal reclaim-retry — each with PR #52;
  preamble updated. Still-open 2.S-created deferrals (save_to resumer-cwd, host-GC CLI-locality,
  media_gc_grace_days threading) left unchecked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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