Skip to content

Commit a570ab7

Browse files
DylanMerigaudclaude
andcommitted
Strip em-dashes from the codebase + lint rule to keep them out
The em-dash reads AI-written and it was all over the source (UI copy, comments, README, ~900 of them). Replaced every one (mostly " — " -> ", ", trailing " —" -> ",", and the "no value" glyph "—" -> "-"), then naturalized the few stiff semicolons in on-screen text. New custom rule no-emdash-in-text: bans the em/en-dash in all text including comments (it never appears in real code, so zero false positives) and the semicolon in JSX text (where it reads stiff; it stays legal in code/strings). Wired at error in the ESLint config. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 648c3bb commit a570ab7

132 files changed

Lines changed: 954 additions & 888 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

AGENT_BRIEF.md

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
# Agent brief read this first
1+
# Agent brief, read this first
22

33
You're working on **ledgerloop**, a procure-to-pay demo built as a job/freelance
44
asset for Didero (procurement-AI). Two surfaces: an **onboarding agent** that reads a
55
client's HRIS and derives an approval workflow, and a **pipeline** that runs invoices
66
through that workflow. This file is the context a fresh session needs so it doesn't
77
re-derive or break conventions. (`.product/*.md` has deeper strategy notes but is
8-
gitignored, so it may be absent in a worktree this committed brief is the source.)
8+
gitignored, so it may be absent in a worktree, this committed brief is the source.)
99

10-
## Current state (the two surfaces are LINKED done, don't re-derive)
10+
## Current state (the two surfaces are LINKED, done, don't re-derive)
1111

1212
The "complete loop" is built and on `main`. Key facts a fresh session must know:
1313

@@ -39,7 +39,7 @@ The "complete loop" is built and on `main`. Key facts a fresh session must know:
3939
- **e2e** (`pnpm e2e`, local-only, needs keys): `approval.e2e.ts` (HITL on the default) +
4040
`onboarding-to-pipeline.e2e.ts` (the flagship loop: discover → dept gate → post).
4141

42-
## Hard conventions (non-negotiable the user is strict about these)
42+
## Hard conventions (non-negotiable, the user is strict about these)
4343

4444
- **No `as` casts.** ESLint `@typescript-eslint/no-unsafe-type-assertion` is ON.
4545
Narrow with a type guard (`isRecord` in `lib/assert.ts`), validate with a Zod
@@ -53,10 +53,10 @@ The "complete loop" is built and on `main`. Key facts a fresh session must know:
5353
- **The API is oRPC.** Typed procedures in `lib/orpc/router.ts`, shared i/o schemas
5454
in `lib/orpc/schemas.ts`, browser client + TanStack Query in `lib/orpc/client.ts`,
5555
one handler at `app/rpc/[[...rest]]/route.ts`. Add a procedure there, not a new
56-
`app/api/*` route. (The only plain REST route left is `/api/pdf` binary.)
56+
`app/api/*` route. (The only plain REST route left is `/api/pdf`, binary.)
5757
- **"AI at the edge, deterministic core."** LLM calls do fuzzy intent (structured
5858
output); deterministic code does structure. The chat-edit is a hand-written
59-
bounded loop (`lib/workflow-edit-agent.ts`) over the Claude SDK NOT a Mastra
59+
bounded loop (`lib/workflow-edit-agent.ts`) over the Claude SDK, NOT a Mastra
6060
Agent (see its header comment for why). Mastra owns the P2P pipeline
6161
(`src/mastra/workflows/p2p.ts`) and the exception-investigator agent.
6262
- **Bounded persistence, not stateless.** The run writes ONE thing: an append-only
@@ -66,7 +66,7 @@ The "complete loop" is built and on `main`. Key facts a fresh session must know:
6666
A nightly Vercel Cron (`/api/reset`, `vercel.json`) truncates+reseeds Postgres so
6767
the demo stays pristine; the reset touches Postgres only, never the sandboxes.
6868
HITL resume stays REPLAY-based (recompute the deterministic prefix from the
69-
decisions), NOT Mastra snapshot/suspend keep it that way (the snapshot path has
69+
decisions), NOT Mastra snapshot/suspend, keep it that way (the snapshot path has
7070
a known Postgres-bloat footgun). Don't reintroduce writes to the document tables.
7171
- **The recorded HRIS fixture is SEED-BUILT**, not a live capture
7272
(`scripts/build-recorded-fixture.ts``pnpm fixture:build`). recorded == live ==
@@ -83,7 +83,7 @@ pnpm typecheck && pnpm lint && pnpm knip && pnpm test && pnpm format:check && pn
8383

8484
- `pnpm test` = node:test, all faked (free, no API).
8585
- Evals: `pnpm eval:edit --dry-run` and `pnpm eval:edit-agent --dry-run` are free
86-
(stubs). Live evals cost Anthropic tokens only run a live eval to PROVE a model
86+
(stubs). Live evals cost Anthropic tokens, only run a live eval to PROVE a model
8787
change works, never casually. The user's rule: don't waste tokens.
8888
- Screenshots: the dev server hits live BambooHR if the key is set (~12s). For fast,
8989
deterministic screenshots run dev with `BAMBOO_HR_API_KEY= BAMBOO_HR_SUBDOMAIN=`
@@ -100,23 +100,23 @@ pnpm typecheck && pnpm lint && pnpm knip && pnpm test && pnpm format:check && pn
100100

101101
## Where things are
102102

103-
- `lib/approval-workflow.ts` the workflow DAG model, conditions, `humanizeCondition`,
103+
- `lib/approval-workflow.ts`, the workflow DAG model, conditions, `humanizeCondition`,
104104
`diffWorkflows`.
105-
- `lib/approval-engine.ts` executes the DAG (AND-join, skipped = pass-through).
106-
- `lib/workflow-validate.ts` structural + AP-best-practice checks (the validator).
107-
- `lib/workflow-edit.ts` / `-agent.ts` / `-model.ts` the chat-edit ops, the
105+
- `lib/approval-engine.ts`, executes the DAG (AND-join, skipped = pass-through).
106+
- `lib/workflow-validate.ts`, structural + AP-best-practice checks (the validator).
107+
- `lib/workflow-edit.ts` / `-agent.ts` / `-model.ts`, the chat-edit ops, the
108108
bounded agent loop, the Claude planner.
109-
- `lib/onboarding.ts` / `-model.ts` derive the workflow from an org.
110-
- `lib/hris.ts` BambooHR adapter (live + recorded) + the mapper.
111-
- `lib/erp.ts` two seams: the reconciliation POST stub (fake-netsuite) AND the
109+
- `lib/onboarding.ts` / `-model.ts`, derive the workflow from an org.
110+
- `lib/hris.ts`, BambooHR adapter (live + recorded) + the mapper.
111+
- `lib/erp.ts`, two seams: the reconciliation POST stub (fake-netsuite) AND the
112112
PO PULL (QuickBooks live + recorded fixture, same shape as HRIS). `defaultErp()`
113113
picks live/recorded by env; `loadRunBundle` matches invoices against pulled POs.
114-
- `src/mastra/` the P2P pipeline + investigator agent + run-stream generator.
115-
- `components/` onboarding, workflow-editor, workflow-graph (React Flow),
114+
- `src/mastra/`, the P2P pipeline + investigator agent + run-stream generator.
115+
- `components/`, onboarding, workflow-editor, workflow-graph (React Flow),
116116
dashboard, trace-timeline.
117117

118118
## Your task
119119

120-
Ask the user the link-workflow / department / live-graph work (see "Current state"
120+
Ask the user, the link-workflow / department / live-graph work (see "Current state"
121121
above) is done and merged. There may be a `TASK.md` in this folder from a past branch;
122122
treat it as scaffolding, not a live instruction, unless the user points you at it.

0 commit comments

Comments
 (0)