Skip to content

refactor: lay the v2 workspace foundation and add the forges boundary - #71

Merged
RedStar071 merged 19 commits into
mainfrom
feat/v2-foundation
Oct 20, 2026
Merged

RedStar071 merged 19 commits into
mainfrom
feat/v2-foundation

Conversation

@RedStar071

@RedStar071 RedStar071 commented Oct 18, 2026 •

Copy link
Copy Markdown
Member

Summary

Related to #5. First slice of the v2 restructuring in docs/plans/2026-10-17-code-zero-v2-brainstorm.md. Nothing here changes what a run does; it moves the workspace into the v2 shape and adds the next source-control boundary next to the old one.

  • Runtime packages move to packages/core/*. npm names stay the same, so no import changes.
  • apps/dashboard becomes apps/web (@code-zero/web).
  • Every package builds ESM only.
  • packages/ui holds the colour tokens, UnoCSS theme, RTL/a11y dev presets and a DESIGN.md. Web and marketing stop carrying copies.
  • packages/forge is the source-control boundary rebuilt on forges, for GitHub, GitLab, Gitea, Forgejo, Bitbucket Cloud and Azure DevOps. Nothing imports it yet.
  • The lockfile had five edges pointing at peer ids with no snapshot, so a clean aube ci left drizzle-orm dangling and the web build died with ENOENT. Same repair as 4ff2b5d on the old dashboard branch, which never made it to main.
  • The Nuxt Vitest projects get a 60 s hookTimeout; the app boot in beforeAll regularly took longer than 10 s on a cold cache.
  • 17 agent skills from skilld.dev, pinned to source commits. They are most of the line count.

Why

The plan's diagnosis is that the dashboard, auth and source-control edges need rewriting while the runtime holds up. Doing the moves first, as refactors that keep every check green, keeps the behaviour changes coming next small enough to review.

forges replaces sixteen hand-written adapter files with one maintained client that covers more forges, reports what each one can do through can(), and ships an in-memory fake for tests. packages/forge depends only on @code-zero/shared, so the adapter rule holds.

Verification

  • aube run check:repo
  • aube run lint:ci
  • aube run typecheck
  • aube test
  • aube run build

Safety and compatibility

  • I added or updated deterministic tests for changed behavior.
  • I preserved observe mode as read-only, or explained the policy change above.
  • Runtime commands and target-repository writes remain inside the runner boundary.
  • I did not expose secrets, tokens, personal data, or untrusted output in logs.
  • I updated documentation and Agent Skills when workflows or boundaries changed.

Packages no longer ship CommonJS. Everything in the repo that loads them is Node 24 or a Vite/Nitro build, but anything outside the repo that require()s them will break. Local setups move their env file from apps/dashboard/.env to apps/web/.env.

Agent context

  • Agent/tools used: Claude Code (Claude Opus 5.5) in T3 Code, plus one subagent for packages/forge.
  • What the agent did, and what you changed or verified yourself: the agent wrote the plan from my requirements and answers, did the moves, built packages/ui and packages/forge, and ran the checks after every commit. I made every decision recorded in §10 of the plan.

Reviewer notes

  • @code-zero/docs never finished building locally: the Docus prerender runs out of V8 heap on a 3.8 GB machine. CI built all 19 workspaces uncached, docs included.
  • The vendored github-actions-generator skill ships sample action.yml templates, and zizmor failed on them. zizmor now audits .github only, where every workflow and action of this repo lives.
  • One of the five lockfile edges is odd: unctx named an unplugin variant whose nested esbuild differs from the only snapshot, rather than a truncated id. It dangled on disk either way, so I repointed it. Worth a second look if you know why aube wrote it.
  • packages/source-control stays until api and web are wired to packages/forge. That and the rest (auth v2, billing, worker, the GitHub Action, the web pages, Docker and serverless deploys) come as separate PRs.

🤖 AI disclosure: Wolfstar Agent Kit modified this description. My AI open-source policy.

RetriggerView in GreptileConfidence Score: 5/5

No outstanding findings block merging this PR.

Reviews (6) · Last reviewed commit: "fix(web): keep the sign-in destination t..." · Reviewed by Greptile

Diagnoses the current dashboard, auth, source-control and deployment
problems, proposes the supastarter-style workspace layout, and records
the maintainer's answers on layout, ESM, licensing, billing, forges and
deployment targets.
Pins Better Auth, nuxt-better-auth, Vue, UnoCSS, Vitest, Vue testing,
Postgres/Drizzle, Stripe, taste, modern CSS, code review, GitHub Actions,
Dockerfile, Cloudflare and anti-slop skills to their source commits.
agent, runner, models, config and shared now live in packages/core/*.
Their npm names are unchanged, so imports stay identical; only relative
tooling paths, TypeScript project references, the workspace globs and
the documentation that names their directories change.
The deployable app becomes @code-zero/web in apps/web, matching the
v2 layout. Paths, the Turborepo task key, the Dockerfile, the CD
workflow, the Vercel build command, i18n tooling globs and the docs
follow. The September dashboard plan moves to docs/plans unchanged.
The shared tsdown configuration drops the CommonJS output and validates
with attw's esm-only profile. Package exports keep a single types and
default condition. forges, the next source-control client, ships no CJS
build, and every consumer is a Node 24 process or a Vite/Nitro build.
packages/ui owns the colour tokens, focus and accessibility media
queries (tokens.css), the brand theme, the RTL and a11y dev presets and a
defineCodeZeroUno factory. apps/web and apps/marketing drop their copies
and keep only their density shortcuts and page backgrounds. DESIGN.md
records the rules a UI change must respect.

The marketing site renders identically in both schemes; the dashboard
gains the reduced-motion rule the marketing site already had.
Four edges in the better-auth@1.6.26 subgraph named peer-qualified ids
truncated one level (prisma@7.9.1 instead of
prisma@7.9.1(better-sqlite3@12.11.1)), and one unctx edge named an
unplugin variant with no snapshot. aube hashes the id as written, so a
clean aube ci linked node_modules/.aube/@better-auth+drizzle-adapter*
/node_modules/drizzle-orm (and unctx's unplugin) at virtual-store
directories it never creates, and the web Nitro build failed with ENOENT.

Repointed the five edges at the snapshots already in the lockfile. A
clean aube ci now reproduces the file byte for byte and leaves no
dangling links.
@nuxt/test-utils boots the whole app in a beforeAll hook before the
first spec of each worker. On a cold cache or a loaded machine that boot
outlasts Vitest's default 10 s hook timeout and fails whole files before
any assertion runs. Raise hookTimeout to 60 s for the nuxt projects of
apps/web and apps/marketing.
packages/forge (@code-zero/forge) builds the source-control boundary on
the forges library for GitHub, GitLab, Gitea, Forgejo, Bitbucket Cloud
and Azure DevOps: connections and a registry, FORGES_* environment
parsing, signed webhook ingestion into review and issue events, open
change-request discovery, status publication with explicit degradation,
progress, evidence and issue-validation comments, and issue-to-PR.

Every delivery is untrusted: bad signatures and malformed payloads are
typed rejections, library errors are redacted against the connection's
credentials, and issue events start nothing unless policy opts in.
Tests run against forges' in-memory fake and signed fixtures, with no
network. Nothing imports the package yet; packages/source-control stays
until packages/api and apps/web are rewired.
@coldtea-pr-lens

coldtea-pr-lens Bot commented Oct 18, 2026 •

Copy link
Copy Markdown
  • Redraw · drawn at 6b5aac1, the branch has moved on

Architecture

Architecture diagram for wolfstar-project/code-zero at 6b5aac1

Play the walkthrough

Inside the changed components — 3 views

Component view — Web App Container

Internal modules and server route handlers of the renamed apps/web application.

Architecture view of Component view — Web App Container in wolfstar-project/code-zero

Component view — Core Runtime Packages

Execution boundary and state engine modules consolidated under packages/core/*.

Architecture view of Component view — Core Runtime Packages in wolfstar-project/code-zero

Component view — Multi-Forge Layer

The new packages/forge abstraction integrating multi-provider SCM interactions via the forges library.

Architecture view of Component view — Multi-Forge Layer in wolfstar-project/code-zero

Data flow

Data flow diagram for wolfstar-project/code-zero at 6b5aac1

Follow each request


Review

✨ Nothing flagged · reviewed 6b5aac1


Tip

The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change

🪧 More tips
  • Run npx skills add coldteadotai/pr-lens, then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Run npx @coldtea/pr-lens-cli analyze --base origin/main on a branch, then npx @coldtea/pr-lens-cli render .pr-lens/graph.json. Same lenses, your own model key, before the pull request exists
  • Click the link under each diagram to open it on a canvas you can zoom, pan and step through
  • Open a diagram on the canvas, then press W or click play to walk through the change one step at a time
  • The CLI's render reads .github/pr-lens.yml and applies your renames, exclusions and lane pins at draw time
  • Set github.comment.collapsed: true in .github/pr-lens.yml to fold the comment behind one View architecture and data flow row. Drawing still runs as before
  • Set github.draw: on-demand in .github/pr-lens.yml and PR Lens stops drawing pull requests on its own. Comment @pr-lens draw on a pull request when you want that one drawn
  • Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and your model provider's key as its api-key to run PR Lens from your own CI. Any /chat/completions endpoint works
  • After a push, tick Redraw to draw the latest commit
  • Switch GitHub to dark mode and the diagrams follow. The moving dots are this pull request's data in motion

Thanks for using PR Lens! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out on X, Bluesky, Mastodon, Reddit or LinkedIn

@vercel

vercel Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
agent-zero-marketing Ready Ready Preview Oct 18, 2026 9:47pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
agent-zero-docs Skipped Skipped Oct 18, 2026 9:47pm UTC

@RedStar071

Copy link
Copy Markdown
Member Author

Checked by hand, since CI cannot cover it:

  • Served the built marketing site and compared dark and light schemes after the packages/ui move. Background, ink, accent, the hero halo and fonts resolve to the same token values as before, and the page looks unchanged.
  • aube ci on a clean node_modules with the repaired lockfile rewrites pnpm-lock.yaml byte for byte and leaves zero dangling links under node_modules/.aube; before the repair it left @better-auth/drizzle-adapter pointing at a missing drizzle-orm directory.

The github-actions-generator skill vendors sample action.yml templates
under .agents/skills. zizmor scanned the whole checkout and failed the
pull request on template-injection findings in that sample code, which
nothing ever runs. Point it at .github, where every workflow and action
of this repository lives.
Comment thread packages/forge/src/registry.ts
connectionsFromEnvironment() builds factories from an arbitrary
environment object, but the registry only recorded credentials for
connections it built itself. When that object was not process.env, a
token matching no known secret pattern passed redaction untouched into
outgoing comments and ForgeRequestError messages.

Prepared connections now carry the credential values of their variable
set, PEM keys in both escaped and real-newline form, and the registry
registers them like any other connection. Regression tests use an opaque
token absent from process.env and fail without the fix.
greptile-apps[bot]
greptile-apps Bot previously approved these changes Oct 18, 2026
greptile-apps[bot]
greptile-apps Bot previously approved these changes Oct 18, 2026
Comment thread apps/web/server/auth.config.ts Outdated
Comment thread apps/web/app/auth.config.ts Outdated
Comment thread packages/core/config/src/settings.ts
…ceiling

With `execution.max_network` below `full` and no deployment sandbox, a repository choosing
`isolation: local` ran on the host network: `LocalRunner` carries the policy without enforcing
it, and a hosted provider may hand back a runner wider than the lease asked for. The ceiling
was a label, not a limit.

`runTask` now checks the runner it actually built: under a ceiling below `full` the run executes
only when the runner is isolated and its network is no wider than the run's effective policy (the
repository's own, narrowed to the ceiling), so a run that must have `none` gets exactly `none`.
A RunnerPool lease is released before refusing, and the task is recorded as `failed` with the
redacted reason, on the same terms as `ISOLATION_UNAVAILABLE`.

The settings page hint (EN/IT) and the deployment-settings guide now say that a ceiling below
Full needs the container sandbox or a hosted sandbox, and that local runs are refused.
`AUTH_ENABLE_MAGIC_LINK=true` or `AUTH_ENABLE_TWO_FACTOR_EMAIL_OTP=true` stopped the dashboard at
startup: `packages/auth` refuses either flag without its delivery callback, and the app supplied
neither `sendMagicLinkEmail` nor `sendTwoFactorOtpEmail`.

`packages/mail` gains two templates, `magicLink` (the sign-in link, named to no account) and
`twoFactorOtp` (the code printed once as text, never inside a link), registered beside the
existing four with the compiled artifact re-rendered. The app's delivery bindings move out of
`server/auth.config.ts` into `server/utils/auth-mail.ts`, which now wires every callback a
policy flag can require, so turning on an email sign-in option is a configuration change rather
than a startup error. Neither the link nor the code is ever logged.
A password sign-in on an account with two-factor authentication answered with
`twoFactorRedirect: true` and nothing happened: the sign-in page showed a success it could not
act on, and no page existed to take the code, so the sign-in could never finish.

`app/auth.config.ts` passes `onTwoFactorRedirect` to `twoFactorClient()`, which navigates to the
new `/two-factor` page (auth layout, guest-only like `/login`). The page takes the authenticator
code in a numeric `one-time-code` field, switches to a backup code, and, when `/api/capabilities`
reports mailed codes, sends one and verifies it; it offers to trust the device, refreshes the
session and opens the dashboard on success, keeps a rejected code on the page with a `role="alert"`
message through `useAuthErrorMessage`, and links back to sign-in. Copy is in the `auth` namespace
(EN/IT) with the schema regenerated.
Comment thread apps/web/app/auth.config.ts Outdated
Comment thread apps/web/app/pages/(auth)/two-factor.vue Outdated
Signing in to approve a CLI request starts at /login?redirect=/device?…,
but the two-factor hook opened /two-factor without it and a verified code
always went to /. The visitor ended up signed in on the dashboard while
the CLI kept waiting. The hook now carries the return address to the
challenge page, which goes back there after verification and keeps it on
its link back to sign-in. The address comes from the URL, so only a path
on this app is accepted: no //host or /\host, no control characters, and
not another sign-in page.

The method switch also stayed enabled while a code was being checked.
Switching changed which action the page read its pending state from, so
it re-enabled submission and dropped the first check's answer. Pending
now covers all four actions, and switching or mailing a code is disabled
until the running check answers.
@RedStar071
RedStar071 merged commit d1e0b99 into main Oct 20, 2026
15 checks passed
@RedStar071
RedStar071 deleted the feat/v2-foundation branch October 20, 2026 12:46
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