AI agent entrypoint for the FactoryWager monorepo (~/Projects).
Git remotes: origin → project-R-score (this monorepo). cascade → private nested product cascade-mover-v3 (git remote only — do not default-push there). Runtime identity: lib/github-repository-ref.ts (owner/name/host/remote — not REPO_URL); parts SSOT in CANONICAL_REMOTES.
Remote SSH: Reasonix remote hosts live in ~/.reasonix/config.toml under [remote]. Active: factorywager-staging (internal.staging, ~/.ssh/id_ed25519, workspace ~/Projects). cloudflare-pages (API-based, no SSH — deploy via bash scripts/cloudflare-pages-deploy.sh). Cascade Mover host is placeholder (uncomment when IP known). Tunnel: scripts/cloudflared-reasonix.yml → reasonix.factory-wager.com. CLI: reasonix remote test/connect/list. First-time bootstrap: bun run remote:setup. Reasonix binary: /Applications/Reasonix.app/Contents/MacOS/reasonix.
Cloudflare MCP (.mcp.json): cloudflare (account/API) · cloudflare-docs (search) · cloudflare-bindings (Workers bindings) · cloudflare-builds (Workers Builds CI — not Pages deploy history) · cloudflare-observability (logs/metrics). Token: CLOUDFLARE_API_TOKEN in ~/.reasonix/.env. Pages project pins: bun run cloudflare:env. Token scope probe (bun run cloudflare:env:validate) proves harness operational confidence — not MCP runtime authorization (dashboard token policy only). Not a TOC/partner desk: Soft Balance, rails, MessageLog, phones, and package Telegram stay in toc-ops-repo (ct); Pages exposes the baked board at /portal/toc/ · docs/harness/tenants/toc-ops.md.
| Role | Doc |
|---|---|
| This file (agent entry) | AGENTS.md |
| Full agent guide | docs/AGENTS.md (aligned to this entry + UNIFIED / WIRE_BOUNDARY) |
| Harness JIT index | docs/harness/README.md (when NFR unresolved → one owner) |
| Authority / lanes | docs/harness/AUTHORITY.md |
| Repository review (JIT) | docs/harness/REVIEW.md |
| Proof / install journey | docs/harness/PROOF.md · bun run proof:install |
| Docs index | docs/README.md |
| Human hub | README.md |
| Workspace map | STRUCTURE.md |
| Coding standards | .custom-instructions.md · docs/DEVELOPMENT-STANDARDS.md |
| Bun install policy | docs/UNIFIED.md |
| Import boundaries | docs/IMPORT_BOUNDARIES.md |
| Wire boundary (parse once) | docs/WIRE_BOUNDARY.md |
| Portal foundation (static UI) | docs/portal-foundation.md · bun run verify:portal:static · serve:public:hot |
| TOC Ops portal board (fixture) | docs/harness/tenants/toc-ops.md · /portal/toc/ · bun run ops:seed:toc · bun test tests/toc-ops-fixture.test.ts |
| Ops loop throughput | docs/harness/tenants/ops-loop-throughput.md · bun run ops:loop:baseline / ops:loop:post / ops:outbox:requeue · claim ops-loop-throughput |
| Factory Telegram | docs/harness/tenants/telegram-factory.md · bun run telegram:verify · telegram:ops:consume · lib/telegram/ |
| Platform routing (local vs Pages) | docs/platform-routing.md · bun run check:routes · bun run verify:pages-edge |
| Bun native capabilities | docs/BUN_NATIVE_CAPABILITIES.md (WebView, markdown.ansi, Terminal/PTY, Bun.Image, cron, UDP) |
| Bun token/catalog operate | docs/BUN_DOCS_OPERATE.md (bun run docs:refresh) |
| TokenRef (interior) / BunToken (export) | lib/docs/token-ref.ts · lib/docs/bun-token.ts |
| Projects triage | projects/README.md |
| Path SSOT (code) | lib/docs/repo-docs.ts |
| Cloudflare / R2 / Pages | config/r2-env.ts · bun run cloudflare:env / :assert / :assert-apex / :assert-live / :validate · cloudflare:preflight · cloudflare:deploy:verify · docs/harness/tenants/cloudflare-pages.md |
| Harness thesis | lopopolo/harness-engineering |
Do not append an unrequested caveat, counterargument, or moralizing endcap to a sharp claim merely to demonstrate balance. If a boundary condition changes the truth of the claim, put it in the mechanism or scope the claim correctly. If it does not, cut it. Accuracy belongs in the argument; model self-protection does not.
Terminology (harness): prefer artifact over codebase for what is maintained, delivered, or proven; use repository / source tree for the git tree. Domain-valued strings use brands, not bare string, after the boundary — see .custom-instructions.md and lopopolo/harness-engineering.
Do not declare domain IDs as bare string. This is enforced by pre-commit (--staged --strict has no baseline — new code always fails). Bare id: string / _id: string is also flagged; suppress only with an explicit // brand-ok decision — the detector no longer auto-suppresses opaque primary keys.
| Wrong | Right |
|---|---|
sessionId: string |
sessionId: SessionId + asSessionId / trySessionId / parseSessionId |
userId?: string |
userId?: UserId |
function f(accountId: string) |
function f(accountId: AccountId) |
id: string (opaque DTO PK) |
id: string; // brand-ok — opaque entity primary key |
'' as AccountId |
never — use try* or throw |
bun tools/brand-catalog.ts SessionId # which constructor + mint authority
bun run check:brands # repo-wide (baseline may grandfather legacy only)
bun tools/branded-id-check.ts --staged --strict # what pre-commit runs on your diff
Import brands from lib/types/branded.ts. Map: lib/types/branded/README.md. Manifest: lib/types/brand-manifest.json. Skill: .agents/skills/branded-ids/. Intentional opaque passthrough only: // brand-ok on that line.
Full map: docs/WIRE_BOUNDARY.md — what is edge vs interior, path/name allowlists, suppressions.
| Interior (default) | Boundary only |
|---|---|
| Domain types / brands | unknown fun args |
| No re-decode | decodeUnknownSync / decodeUnknown* |
Trusted SessionId, structs |
parse* / is* / type guards |
harness/no-decode-unknown-outside-boundary (error), harness/no-unknown-function-param (error on harness paths)config/eslint/plugin-harness/boundary.ts (BOUNDARY_POLICY)eslint.harness.config.tsdocs/harness/AUTHORITY.md · status: bun run harness:statusgit status for files dirty from other sessions. Claim disjoint lanes (files/directories nobody else is touching), name the lane split in commit messages, never sweep another session’s dirty files into your commit (hook-generated formatting re-wraps excepted).lib/types/branded/README.md + lib/types/branded.ts + bun run check:brands (mandatory for any *Id field)unknown / decode → docs/WIRE_BOUNDARY.mddocs/harness/README.md · docs/harness/REVIEW.md · bun run harness:status · bun run proof:installdocs/harness/tenants/ops-loop-throughput.md · bun run ops:settle · ops:outbox:requeue · bun test tests/ops-loop-hardening.test.tsdocs/harness/tenants/telegram-factory.md · loadTelegramEnv in lib/telegram/telegram-config.ts · bun run telegram:verifybun run cloudflare:env · claim cloudflare-pages-env-ssotbun tools/bun-doc-refs.ts suggest "<api>" (tools/bun-doc-refs.ts)bun tools/bun-doc-refs.ts suggest --audit "<q>" · docs/audit/README.md · claim audit-findings-catalogbun run docs:map:check (also pre-commit when SSOT docs staged)lib/verification/types.ts · lib/verification/README.md · docs/platform-routing.md · bun run verify:proof-taxonomy:save · bun run check:release-tracker · bun run verify-all.custom-instructions.md*.test.ts / tests/ exemplar (e.g. tests/console-depth.test.ts, tests/wire-boundary-policy.test.ts)Bun install policy (machine + workspace): docs/UNIFIED.md
Machine SSOT is ~/.bunfig.toml (linker = "isolated", globalStore = true, frozenLockfile = true, minimumReleaseAge = 259200, absolute [install.cache].dir); env in ~/.config/shell/bun.sh (BUN_INSTALL, NO_PROXY — no BUN_INSTALL_GLOBAL_STORE); PATH in ~/.config/shell/path.sh. Full component table: docs/UNIFIED.md.
bunfig.toml holds project-specific overrides only (frozenLockfile = true hardened, scopes, [test], etc.) — do not duplicate linker, globalStore, or cache.dir unless intentionally overriding. Intentional dep edits: temporarily set frozenLockfile = false, then restore.BUN_INSTALL_CACHE_DIR or BUN_INSTALL_GLOBAL_STORE in shell or IDE — fails bunfig-policy / bun_verify.bun run install:verify · bun run audit:bunfig · kimi-doctor --gate bunfig-policy · bhealth / bmachine.Before using an unfamiliar Bun API, resolve its canonical doc instead of guessing the signature:
bun tools/bun-doc-refs.ts suggest "Bun.secrets" # → catalog DOC + SHIP/FIX/BLOG/NOTE when known
bun tools/bun-doc-refs.ts url "Bun.stringWidth" # → canonical URL
bun tools/bun-docs-catalog.ts get Bun.WebView # full catalog entry
bun run docs:catalog:export # compact TSV for agents
Commands: url list suggest (catalog → canonical map → index) · catalog · check/annotate (find/insert @see refs) · audit (map anchors vs index) · deepcheck (repo links vs index) · validate (HTTP links) · integrity (4-layer proof; --fix self-heals taxonomy aliases, --fix-dry previews) · status (includes tier-A coverage) · schedule (Bun.cron daemon; --once for single runs) · export (hierarchical llms-full.txt)
Operate loop (RSS → reference index → scrape → catalog → integrity): docs/BUN_DOCS_OPERATE.md · bun run docs:refresh · strict tracked-token gate: bun run verify:docs-coverage:save
Rules:
Bun.* API in code, add // @see <canonical-url> from the url/suggest output to the file header (or run bun tools/bun-doc-refs.ts annotate --write <files> to do it automatically).lib/console-depth.ts header for the pattern); Bun silently ignores several Node util.inspect-style options.tools/bun-docs-index.json → tools/bun-docs-catalog.json (NOTE/SHIP/FIX/BLOG) → tools/bun-doc-refs.ts CANONICAL_REFS. Refresh: bun run docs:refresh (or bun tools/bun-docs-index-gen.ts && bun tools/bun-doc-refs.ts integrity).Mandatory for agents. Domain *Id values are never bare string after the boundary (see section above).
Stable import: lib/types/branded.ts · Domains: lib/types/branded/{session,identity,documents,security,deployment,audit,operations}.ts · Manifest: lib/types/brand-manifest.json · Agent map: lib/types/branded/README.md
Each domain module repeats the same pattern: type + as* + try* + parse* + *_BRAND_SPECS. Agents learn the invariant from structure.
| Tier | Use |
|---|---|
asXId |
Required string → brand or throw |
tryXId |
Optional → brand or undefined (never empty forge) |
parseXId |
Wire unknown → brand or throw |
Mint authority is documented per brand in the manifest (system-internal · user-input · wire-input). Optional audit: BRAND_PROVENANCE=1.
bun tools/brand-catalog.ts # JIT brand discovery (domain|BrandName)
bun run check:brands # actionable unbranded IDs (manifest-driven + baseline)
bun run check:brands:types # tsc proof: SessionId ≠ UserId
bun run check:brands:all # manifest + smart + types
bun tools/brand-manifest.ts # regenerate institutional record
bun tools/brand-manifest.ts --check # fail if manifest stale (pre-commit)
bun tools/branded-id-check.ts --write-baseline # only when expanding detector (owners)
Skill: .agents/skills/branded-ids/ · Type proof: tests/branded-types.test-d.ts
--staged --strict on added lines (no baseline — mid-line params included) + repo-wide --smart --strict// brand-oklib/security/r2-credentials.ts (soft try* merge)Object-inspection depth is controlled project-wide via lib/console-depth.ts (wrapper over Bun.inspect / .table / .custom). Precedence: --console-depth=N flag > BUN_CONSOLE_DEPTH env (set in root .env) > default 4. Prefer wrapper helpers (inspect / logDepth / logTable / inspectCustom) over raw console.log(obj) / console.table; forward to children with depthArgs() / withConsoleDepth(). Hashing wrapper: lib/security/index.ts SecurityUtils (claim security-hash-boundaries). Full wrapper inventory: docs/harness/PROOF.md · BUN_NATIVE_WRAPPERS · bun run harness:status. Note: Bun’s runtime does not read BUN_CONSOLE_DEPTH itself and util.inspect.defaultOptions.depth is a no-op in Bun — only bun --console-depth=N and Bun.inspect({depth}) work.
| Kind | References |
|---|---|
| Repo | claim console-depth-boundaries · wrapper lib/console-depth.ts · tests/console-depth.test.ts · tools/benchmarks/console-depth-perf.ts · wrappers map PROOF.md · hash wrapper security-hash-boundaries |
| Bun | runtime/console · runtime/utils (inspect · .table · .custom · stringWidth) · hashing |
| Other external | bun-types pin |