agentic-app-scaffoldrun.md02_define/output/spec.mdThe agentic-layer architecture David approved calls for a separate app beside the platform —
living on top of and independently from the classic screens — and no such app exists. Until it
does, every agentic feature has nowhere to land: there is no seventh app in the monorepo, no
deploy target, and no signed-in surface to build the conversation into. This is the first stub of
the agentic-app-foundation batch (1 of 2; agentic-chat-interface builds inside the app this
one creates), and it advances Scale the bridge / Q2-2026 Objective 3 — Validate Technical
Infrastructure & Payout Flow: the agentic layer is new infrastructure, and this stub is the
smallest slice that proves it builds, deploys and authenticates on its own before any AI call is
made.
Create apps/agent (package @sustentus/agent), the agentic layer's home, as a minimal but
production-shaped Next.js 16 app in the monorepo:
apps/* workspace glob; catalogue versions only; a
dev script on port 3007 (the next free port after apps/console's 3006) backed by a real
@sustentus/agent#dev turbo task, since turbo resolves an undefined task to an empty graph and
a dev script without one silently does nothing; root agent:dev / agent:build scripts; a
globals block for apps/agent/** in the root ESLint config; vercel.json carrying the standard
npx turbo-ignore @sustentus/agent --fallback=main ignore command.proxy.ts (this repo's Next 16 middleware file) gating every
route on an authenticated session, deny-by-default at the edge rather than per-layout, so the
gate covers every route the app will ever have. The gate is "authenticated user" and nothing
finer — no roles, no metadata marker. The app runs against the same Clerk production instance
as the platform, so on a shared root domain a signed-in platform user is already signed in
here; on the Vercel preview domain, where the session is not shared, the app's own /sign-in
route issues one.@sustentus/ui, Geist, Tailwind 4, the platform's
light/dark treatment) confirming who is signed in: name, email, and a sign-out control. That is
the whole product surface; the conversation itself is stub 2.agentic-interface is re-pointed by the
operator at apps/agent; .icm/_shared/ci.md gains its commit status so the pipeline reads a
seventh Vercel project instead of six.No existing app is touched: no change to apps/web, apps/demo, apps/marketing, apps/docs,
apps/help, apps/storybook or apps/console beyond the docs pages Ship updates, and no change
to either shared package.
apps/agent exists as @sustentus/agent — a Next.js 16 App Router app whose dependency
versions all come from the pnpm catalogue (catalog:) where the catalogue defines them, and
which declares no dependency on @sustentus/services.Quality Project is green on the PR with apps/agent included — format, lint (within the
45-warning ceiling), typecheck and test all pass, and no existing app's build or lint output
changes.pnpm agent:dev starts the app on port 3007 via a @sustentus/agent#dev turbo task, and no
other app's dev command is affected (pnpm web:dev still starts apps/web on 3000)./ and an arbitrary unknown path
alike — redirects to sign-in rather than rendering; the redirect is issued by proxy.ts, not
by a page or layout./ renders the branded shell and displays the signed-in user's name and email
read from the Clerk session, with a working sign-out control.agentic-interface, root directory apps/agent)
and reports its own commit status on the PR; a commit touching only apps/agent leaves every
other turbo-ignore-guarded project skipped ("Canceled by Ignored Build Step"), and a commit
touching only apps/web leaves the agent project skipped..icm/_shared/ci.md lists the agent app's Vercel commit status alongside the existing six,
so a stage reading the CI contract accounts for it.docs-sync, in this PR).@sustentus/services data access
— stub 2 (agentic-chat-interface) and later.apps/web.ai.sustentus.com production domain cut-over and the Clerk production root-domain
verification — operator actions (see Operator preconditions), not feature work.CLERK_SECRET_KEY and
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, both already in turbo.json → globalEnv; the operator
mirrors their values into the Vercel project. An AGENT_APP_URL / authorized-parties allowlist
of the kind apps/console carries is deferred until something needs it, so globalEnv is
unchanged by this run.apps/web skip its own builds. The stub's rough criterion asked that an AI-only
change not rebuild the platform "nor the reverse". The first half is delivered; the second is
not, because apps/web/vercel.json deliberately sets no ignoreCommand — the platform builds
on every push by design (.icm/_shared/ci.md). Adding one would change the platform's deploy
behaviour and contradicts "the classic apps are untouched". Left as-is; raise it as its own
chore if the build minutes are worth it.clerkMiddleware and a route matcher, exercised by the Quality build and the signed-out
redirect check above. @sustentus/agent ships no test script this run; stub 2 adds one with
the first real logic.apps/agent (apps/console was taken by the tenant-management console
after this stub was cut, and agent was preferred over ai as a directory name), and the app
deploys through the existing agentic-interface Vercel project re-pointed at apps/agent
rather than a newly created one.Not build work — these are Jamie's/the operator's:
agentic-interfaceprj_u0liBVQaTAlGNaX1RsvBbjJHcHEh (team sustentus) is rooted at apps/agent, confirmed from
this PR's first deploy. Nothing left to do here.CLERK_SECRET_KEY and NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, the
same production instance as the platform — into that project for Preview and Production. Until
this is done the app builds but cannot authenticate, so the two sign-in criteria above are not
observable on the preview.sustentus.com, which is what makes the platform session shared with the agent app.Vercel – agentic-interface fails on every commit of this branch — and on main — with
The specified Root Directory "apps/agent" does not exist. That is the project waiting for the
directory this run creates, not a defect in the diff. It clears on the first Build push and must be
green before Verify hands off.
Context budget: within band. Two reads beyond the Inputs table, both targeted and both because the
stub's own notes were stale: apps/console's package/config shape (the stub assumed apps/console
was not in the repo — it is, and it is the tenant-management console), and the Vercel project list
(to confirm agentic-interface still exists and what state it is in).
Scope provenance: this batch has no scope.md. .icm/intake/agentic-app-foundation/breakdown.md
records why — it was cut from the approved agentic-layer architecture report (David, 2026-08-27) on
Jamie's instruction to produce a minimal first-win batch, without passing through
/pipeline scope → approve. The stub plus that breakdown are the settled source this spec traces
to; there are no Q-n numbers to carry.
03_build/output/notes.mdfeat: agentic-app-scaffold — apps/agent, the agentic layer's homeVercel – agentic-interface, which had been failing on every commit of this branch (and on main) with The specified Root Directory "apps/agent" does not exist. This push created it.apps/agent/** (new): the app. package.json (@sustentus/agent, catalogue versions,
dev/start on port 3007), next.config.ts (noindex headers, transpilePackages: ["@sustentus/ui"]),
tsconfig.json, postcss.config.mjs, vercel.json (turbo-ignore @sustentus/agent),
proxy.ts (the Clerk gate), components/providers.tsx (theme-aware ClerkProvider),
app/layout.tsx, app/page.tsx (the shell), app/(auth)/** (sign-in), AGENTS.md.turbo.json: added @sustentus/agent#dev, depending on @sustentus/ui#build only — the app
carries no @sustentus/services dependency. Reworded the neighbouring comment, which asserted
apps/web was the only package with a dev task; that stopped being true with this entry.package.json: agent:dev / agent:build root scripts.eslint.config.ts: browser + node globals block for apps/agent/**.pnpm-lock.yaml: the new workspace package. Purely additive (+55 lines) — CI runs
pnpm install --frozen-lockfile, which fails without it..icm/_shared/ci.md: the Vercel project table gains Vercel – agentic-interface.apps/agent exists as @sustentus/agent — Next.js 16 App Router, catalog: for every
dependency the catalogue defines (next 16.2.12, @clerk/nextjs ^7.0.0 and geist are not
in the catalogue and are pinned exactly as apps/web and apps/console pin them). No
@sustentus/services dependency.Quality Project green — passed on the pushed head, alongside Project run labels and
Review diff against CONVENTIONS.md; all three advisory jobs pass too.pnpm agent:dev on port 3007 via the @sustentus/agent#dev turbo task. No existing task
was edited, so pnpm web:dev is untouched.proxy.ts matches all non-static paths and
treats only /sign-in(.*) as public, so an unknown path redirects exactly as / does. The
redirect is issued at the edge, not by a page or layout./ renders the branded shell with the user's name and email from
currentUser(), and a SignOutButton-wrapped control.vercel.json carries the standard turbo-ignore command, so a
commit that does not affect @sustentus/agent skips this project. The agentic-interface
project is already rooted at apps/agent. Observable only on the preview (see below)..icm/_shared/ci.md lists the agent app's commit status.docs-sync), by design; not this stage.CLERK_SECRET_KEY, NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY) into the agentic-interface Vercel
project — spec → Operator preconditions #2. Without them the app builds but cannot
authenticate. Check that before reading a failed sign-in as a code defect.ci.md table was missing Vercel – tenant-management (apps/console), which has been
reporting on every PR since that app shipped. Adding the agent row to a table that was already
wrong by one would have left the contract misleading in the same edit, so both rows landed and
the counts in the surrounding prose were corrected with them.clerkMiddleware plus a route matcher. @sustentus/agent ships no
test script; turbo skips the package for test.eslint-config-next is deliberately not a dependency here. apps/web and apps/console
carry it without using it (neither has an app-level ESLint config — the root flat config
governs); copying that would have added a speculative dependency, which CONVENTIONS.md
forbids. apps/marketing and apps/demo do use it, via their own eslint.config.js.apps/agent/app/globals.css reproduces apps/console's @source lines verbatim.Context budget: within band. One read beyond the Inputs table — apps/console's app files, as
the closest sibling to model the Clerk gate and the theme-aware provider on.
04_verify/output/verify.md1655fb0 — the Verify fix push, settled via ci-status.sh after it. The final
commit on the branch edits only this file, so it re-runs the same checks against identical app
code; Ship must re-establish the verdict on whatever head it inherits, as its contract requires.1655fb0: Vercel – agentic-interface
(dpl_9jzCMN4bw6p6eLf4ajm96F9iv8jU, alias
agentic-interface-git-claude-agentic-app-scaff-d9dc26-sustentus.vercel.app) and
Vercel – web (unaffected by the change, built because the diff touches shared root config).
The other six projects are skipped for this diff — recorded as skipped, not quoted as green.
This closes the finding raised earlier in the stage: the Build head 0ba529d was an
.icm-only commit with no agent preview; the Verify fix push restored one.complexity: standard) — 2 findings, both fixed on branch. The CI
Review diff against CONVENTIONS.md check passed with zero posted comments, so /code-review
was run rather than triaged.The agent could not reach the preview at all — a preview exists, but it is not reachable
without Vercel credentials. agentic-interface has deployment protection
ssoProtection: all_except_custom_domains, so every path returns 302 → vercel.com/sso-api
before the app's own middleware runs:
| path | result |
|---|---|
/ |
302 → vercel.com/sso-api |
/sign-in |
302 → vercel.com/sso-api |
/some-unknown-path |
302 → vercel.com/sso-api |
So criteria 4 and 5 are operator-only by construction, not merely unverified.
apps/agent exists as @sustentus/agent, catalogue versions, no @sustentus/services —
demonstrated: apps/agent/package.json + pnpm-lock.yaml entry; grep confirms no services
import anywhere in the app (agent)Quality Project green with apps/agent included — demonstrated: check run on 213e8ad,
the commit that carries the app (agent)pnpm agent:dev on port 3007 via @sustentus/agent#dev — demonstrated: turbo.json task
block + root script; no existing task edited, so pnpm web:dev is untouched (agent)clerkMiddleware cannot initialise. Code path traced instead:
proxy.ts:17 redirects when userId is falsy, and the deploy's route table lists
ƒ Proxy (Middleware), so the middleware is genuinely deployed (agent — traced, not observed)app/page.tsx reads currentUser() (agent — traced, not observed)turbo-ignore isolation — demonstrated live: 213e8ad (touches
apps/agent) built agentic-interface; 0ba529d (.icm only) skipped it. The isolation
works in both directions on the evidence of this branch (agent).icm/_shared/ci.md lists the agent app's commit status — demonstrated: the file (agent)docs-sync), by design@sustentus/services
dependency, no Ably or Resend usage (agent)Fixed on this branch:
apps/agent/app/(auth)/sign-in/[[...sign-in]]/page.tsx — Clerk's default "Sign up" footer action
rendered, but this app has no /sign-up route and proxy.ts makes only /sign-in(.*) public, so
the link bounced the visitor straight back to /sign-in. apps/console hides footerAction for
exactly this reason and the guard was dropped in the copy. Now hidden, with the reason in the
file. — fixed.icm/_shared/ci.md — the six→eight project rename missed one line still quoting "all six
previews are green", so a stage reading the contract could call a PR done on six statuses. — fixedOperator actions — the gate should not pass as "demonstrated" until these are done:
CLERK_SECRET_KEY and NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY (platform production
instance) on the agentic-interface Vercel project, Preview and Production, then redeploy.
Vercel's runtime error table for that project currently shows
@clerk/nextjs: Missing publishableKey — count=41, routes=/middleware. That error is attributed
to the project's old production deployment, so it is not this branch's code — but it proves the
variable is absent from the project, and this branch needs the same one.
Without it the app builds and then 500s on every request, which is a worse production state
than the current "root directory does not exist", because it looks deployed.dpl_9LNEh853g6xJeVjtZ7Z8aYYsrsCP and report back.Accepted / routed elsewhere, not fixed here:
agentic-interface is set to 24.x while
apps/agent/package.json declares engines.node: 22.x. The build warns and honours engines, so
the runtime is right only because that field exists. Worth setting the project to 22.x.
tenant-management has the identical drift and is pre-existing — route both as a chore rather
than widening this run.proxy.ts redirects to a bare /sign-in and
the page hard-codes forceRedirectUrl="/". Invisible with one page; a real deep-link bug once
stub 2 adds conversation URLs. Intake note for agentic-chat-interface.globals.css @source paths resolve to non-existent directories (they are relative to the
CSS file). Copied verbatim from apps/console, latent there too, and Tailwind's automatic
detection covers app/ regardless. Not introduced by this PR — left alone deliberately.No HIGH or MEDIUM finding. What was checked, and why the obvious candidates are not findings:
apps/console pattern. The app serves exactly two routes (/,
/sign-in/[[...sign-in]]), neither matching an excluded extension, so no bypass path exists.
Worth re-checking when stub 2 adds routes.fullName / primaryEmailAddress from the Clerk
session, JSX-escaped. No dangerouslySetInnerHTML anywhere in the app.process.env directly, and
.gitignore covers /.clerk/.authorizedParties not set — apps/console carries an optional allowlist and leaves it
unset by default because previews need it that way. Matching the sibling; not a vulnerability.Context budget: within band. Beyond the Inputs table: the Vercel project/deployment/runtime-error reads that the production-readiness pass needed, and one anonymous HTTP probe of the preview.
05_ship/output/investor-update.mdWho it's for: Sustentus engineering — nothing persona-facing yet What shipped: A new app beside the platform, on its own deploy, gated on a signed-in Sustentus account. Why it matters: Agentic features now have somewhere to land, released without touching the classic screens — the first step of Scale the Bridge.
Dig deeper: https://github.com/sustentus/sustentus/pull/894
05_ship/output/release.mdci-status.sh after this stage's last push (the verdict
line below is written before that push, so the PR's own merged state is the record)technical/applications, technical/architecture,
technical/architecture/repository-structure, technical/architecture/system-diagram,
technical/deployment, technical/page.mdx and technical/development (the two port tables)business/** describes what users can do, and users can do nothing new.agentic-chat-interface, which puts a usable surface inside this app.ship-note.yaml)apps/docs/archive/pipeline-runs/agentic-app-scaffold/. The epic
agentic-app-foundation is not finished — agentic-chat-interface (2 of 2) is still in
intake — so the epic folder stays put.apps/agent exists as @sustentus/agent, catalogue versions, no @sustentus/services —
verified in Verify from package.json + pnpm-lock.yaml, and a grep for services importsQuality Project green with apps/agent included — verified in Verify on 213e8adpnpm agent:dev on port 3007 via @sustentus/agent#dev, no other app's dev affected —
verified in Verify from the turbo.json task block and the root scriptagentic-interface carries Vercel
deployment protection ssoProtection: all_except_custom_domains, so every preview path
returns 302 → vercel.com/sso-api before the app's own middleware runs. Code path traced in
Verify (proxy.ts:17, and the deploy's route table lists ƒ Proxy (Middleware)).
Operator-verifiable only.app/page.tsx reads currentUser(). Operator-verifiable only.turbo-ignore isolation in both directions — demonstrated live on this
branch in Verify: 213e8ad (touches apps/agent) built agentic-interface; 0ba529d
(.icm only) skipped it.icm/_shared/ci.md lists the agent app's Vercel commit status — the file, updated at BuildTwo of the eight criteria merge unverified, not verified. That is a deliberate, recorded
decision, not an oversight: they are the two the pipeline structurally cannot reach, Jamie
authorised the merge knowing it, and Verify's record carries the same statement. If the operator
exercises them and either fails, that is a bug against apps/agent, not a re-run of this stage.
Docs edits that go one line beyond this change, and why: the pages this change touched were each
already stale by one app — apps/console was added without them being updated. Adding agent to
a monorepo tree that omits console, or to a port table where 3006 reads as free, would have left
the very table being edited self-contradicting. console was brought to truth in the same lines.
Nothing else in those pages was rewritten. Pre-existing drift left alone deliberately: the docs
still call apps/demo "dashboards" (apps/dashboards) throughout — wrong before this run,
unrelated to it, and a chore of its own.
Checks: not run locally (block-local-checks.sh); the Vercel – docs preview build is what
proves the MDX compiles, and the verdict is read back from CI before the merge.
Context budget: within band.