Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ All notable architectural and code modifications are documented here.

## [Unreleased]

### Added
- **Layer 5 Diagnostic — AI bug detective (ADR-021).** `src/services/bugDetectiveService.ts`: advisory, bounded, fail-closed diagnostic that flags errors, assigns root-cause hypotheses and file:line pointers, and recommends remediation. Never writes to a target tree; any fix still runs VERIFY → REVIEW → COMMIT through L2 gates. `POST /api/bug-detective/diagnose` (RBAC `loop:read`). Adds `defect` failure class (with `DEFECT_*`/`BUG_*` reason patterns) and `bug-diagnosis-evidence` gate (advisory, never refuses). `test/bug-detective.test.ts` (7 tests, all pass). `scripts/verify-bug-detective.sh` gate.
- **Layer 6 Observability — verification gate.** `scripts/verify-observability.sh`: confirms `/factory/health`, `/factory/ready`, `/factory/metrics` surface real durable state, and blocked observability capabilities (`observability-dashboards`, `cycle-time-metrics`) name their operators.
- **Layer 2 Agency — preview plane promoted to live.** `src/services/previewPlaneService.ts` (session lifecycle: worktree, dev server, stop/stopAll), `src/api/routes/preview.routes.ts` (POST/GET/DELETE `/api/preview/sessions`, screenshot), `test/preview-plane.test.ts` (6 tests, all pass). `scripts/verify-preview-plane.sh` gate.

### Changed
- **Capability manifest.** `preview-plane`, `bug-detective`, and `dual-language-reporting` promoted from `planned` to `live`, each naming its proof command. `bug-diagnosis-evidence` gate id added to `doctrine/hooks/hooks.json` and `src/services/gateIds.ts`, mapped to `defect` class in `src/services/loopFailureClass.ts`. `defect` added to `LOOP_FAILURE_CLASSES` and `GATE_FAILURE_CLASSES`; `defect` next step added to `stuckReportService.ts`.
- **Architecture.** README Architecture section now describes seven layers (L1 Control through L7 Interface) with invariants, replacing the four-boundary model. Capabilities table regenerated: 17 live · 12 blocked · 1 planned.

### Fixed
- **Preview plane event loop.** Child dev-server processes are `unref`'d and stdio pipes destroyed on stop so the test process exits cleanly after sessions end.
- **Doctrine manifest hash.** `doctrine/manifest.json` re-pinned for the `bug-diagnosis-evidence` hook addition.
## [4.16.7] - 2026-10-19 — ADR documentation, test coverage, server key setup

### Added
Expand Down
45 changes: 36 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ npm run verify:host # the executor host is the one ADR-014 describes
npm run verify:layer1 # 36 checks against the built server
npm run verify:layer2 # 26 checks: tenant isolation
npm run verify:layer3 # 24 checks: error contract, writer lock
npm run verify:preview-plane # 6 checks: ephemeral worktree + dev server sessions
npm run verify:bug-detective # 7 checks: advisory diagnosis, deterministic output
npm run verify:observability # read-only metrics/health views, blocked capabilities name owners

python3 scripts/verify-k8s.py # 57 manifest assertions
```
Expand Down Expand Up @@ -162,8 +165,20 @@ surfaces — jobs, approvals, releases, outcomes — are described under **Opera
| Live GitHub pull request | blocked | blocked — owner: operator |
| Sandboxed execution in the shipped image | live | `npm run verify:image node` |
| External cloud runtime | blocked | blocked — owner: operator |

**14 live · 4 blocked · 0 planned.** Every live entry names the command that
| Preview plane | live | `npm run verify:preview-plane` |
| AI bug detective (advisory, bounded, fail-closed) | live | `npm test -- test/bug-detective.test.ts` |
| Dual-language reporting (technical + founder/CEO) | live | `npm test -- test/dual-language-report.test.ts` |
| Tool-agnostic IDE/CLI boundary | planned | `npm run verify:tool-agnostic-boundary` (planned) |
| Dashboards, alerts, on-call | blocked | blocked — owner: operator |
| Post-deployment health check and rollback | blocked | blocked — owner: operator |
| Container / microVM executor for untrusted code | blocked | blocked — owner: operator |
| Hosted deployment target with isolated secret injection | blocked | blocked — owner: operator |
| External identity provider / interactive login | blocked | blocked — owner: operator |
| Horizontal scale via shared store | blocked | blocked — owner: engineering |
| Founder jobs and client-like dry runs with evidence packs | blocked | blocked — owner: operator |
| Cycle time, defect rate, repair rate, recovery time, product outcomes | blocked | blocked — owner: operator |

**17 live · 12 blocked · 1 planned.** Every live entry names the command that
demonstrates it; every blocked entry names the operator who must unblock it. A capability appears
here only when it is declared in `src/services/capabilityManifest.ts` — this table is generated by
`npm run render:readme`, so it cannot describe a capability the code does not.
Expand All @@ -188,14 +203,26 @@ The result is a durable operating memory for product work rather than another tr

## Architecture

Software Factory is a modular TypeScript/Express application with a React operations surface and a durable local ledger. The architecture is organized around four boundaries:
Software Factory is organized into seven layers, each with a single responsibility and a strict boundary:

| Layer | Responsibility | Boundary rule |
|-------|---------------|---------------|
| L1 Control | Constitution, ADRs, doctrine, approval policies, capability manifest | No runtime writes; doctrine loads from outside the target repo |
| L2 Agency | Unattended loop (PLAN→IMPLEMENT→VERIFY→COMMIT→REPORT), branches, previews | The loop is the only writer of a target tree |
| L3 Runtime | Tenant-scoped jobs, durable ledger, outcomes, audit, recovery | Single writer; tenant-scoped; fail-closed readiness |
| L4 Adapter | Verification profiles, execution sandbox, deployment, model providers | Provider-specific behavior behind explicit ports |
| L5 Diagnostic | AI bug detective: error flagging, root-cause, remediation advice | Advisory only; never writes to a target tree; fail-closed |
| L6 Observability | Dashboards, alerts, on-call, metrics, health, cycle-time/defect/repair | Read-only views of durable records |
| L7 Interface | Frontend tabs, dual-language reporting, tool-agnostic IDE/CLI boundary | Every output has a technical and a founder/CEO rendering |

1. **Control layer** — Constitution, ADRs, product briefs, implementation plans, completion tasks, approval policies, and evidence contracts.
2. **Agency layer** — Repository preparation, explicit branch modification, verification, previews, context refresh, release preparation, and bounded autonomy.
3. **Runtime layer** — Tenant-scoped jobs, durable persistence, failure records, audit events, quality snapshots, outcomes, and recovery state.
4. **Adapter layer** — Verification profiles, filesystem release, future hosted deployment, execution sandboxes, model providers, and domain-specific integrations.
Key invariants carried across all layers:

The core domain is kept separate from replaceable infrastructure so local-first operation can grow into hosted execution without changing the product contract.
- **Fail closed.** A check that cannot run refuses; it never degrades to "allowed".
- **No fabricated claims.** Every capability names the command or route that proves it (capability manifest).
- **No second writer.** Only the loop writes to a target tree; the diagnostic layer never writes.
- **Advisory diagnostics.** The bug detective emits diagnoses, never edits; any fix still runs VERIFY → REVIEW → COMMIT through L2 gates.
- **Dual vocabulary.** Every durable record renders in both technical and founder/CEO language; no figure appears without a named command that reproduces it.
- **Tool-agnostic.** The doctrine, gates, and evidence boundary live outside Cursor/Cline/any IDE; editors are clients of the boundary, not authors of it.

## Quick start

Expand Down Expand Up @@ -318,7 +345,7 @@ What makes it safe to leave alone:
- **Failure is bounded, classified, and visible.** Three attempts per unit, each quoting the previous refusal
back to the model and rolling the tree back first; then STUCK, and the run continues with the
next independent unit. Every failed attempt carries a machine-readable class — `security`,
`verification`, `review`, `model`, `environment`, `policy`, or `unknown` — derived purely from
`verification`, `review`, `model`, `defect`, `environment`, `policy`, or `unknown` — derived purely from
its refusal code and stage (no model), persisted on the record so it survives `--resume`, and
summarised in the report's **Failure classes** section. A STUCK unit is also reported on the
settlement webhook: the `loop.run.settled` payload carries a `stuckUnits` entry naming the unit's
Expand Down
47 changes: 47 additions & 0 deletions docs/adr/ADR-021-seven-layer-architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# ADR-021 — Seven-layer architecture for Software Factory

## Status

Accepted

## Context

Software Factory's README already describes four boundaries (Control, Agency, Runtime, Adapter). The product is expanding into new surfaces — a preview plane (visual rendering per commit), an AI bug detective (advisory diagnostics), observability (dashboards, alerts, on-call), and dual-language reporting (technical + founder/CEO). Four boundaries cannot cleanly hold these concerns without coupling governance to rendering, or diagnostics to the execution loop. A seven-layer model separates concerns so each layer can evolve, be tested, and be gated independently.

## Decision

Software Factory is organized into seven layers, each with a single responsibility and a strict boundary:

| Layer | Responsibility | Boundary rule |
|-------|---------------|---------------|
| L1 Control | Constitution, ADRs, doctrine, approval policies, capability manifest | No runtime writes; doctrine loads from outside the target repo |
| L2 Agency | Unattended loop (PLAN→IMPLEMENT→VERIFY→COMMIT→REPORT), branches, previews | The loop is the only writer of a target tree |
| L3 Runtime | Tenant-scoped jobs, durable ledger, outcomes, audit, recovery | Single writer; tenant-scoped; fail-closed readiness |
| L4 Adapter | Verification profiles, execution sandbox, deployment, model providers | Provider-specific behavior behind explicit ports |
| L5 Diagnostic | AI bug detective: error flagging, root-cause, remediation advice | Advisory only; never writes to a target tree; fail-closed |
| L6 Observability | Dashboards, alerts, on-call, metrics, health, cycle-time/defect/repair | Read-only views of durable records |
| L7 Interface | Frontend tabs, dual-language reporting, tool-agnostic IDE/CLI boundary | Every output has a technical and a founder/CEO rendering |

Key invariants carried across all layers:

- **Fail closed.** A check that cannot run refuses; it never degrades to "allowed".
- **No fabricated claims.** Every capability names the command or route that proves it (capability manifest).
- **No second writer.** Only the loop writes to a target tree; the diagnostic layer never writes.
- **Advisory diagnostics.** The bug detective emits diagnoses, never edits; any fix still runs VERIFY→REVIEW→COMMIT through L2 gates.
- **Dual vocabulary.** Every durable record renders in both technical and founder/CEO language; no figure appears without a named reproducing command.
- **Tool-agnostic.** The doctrine + gates + evidence boundary lives outside Cursor/Cline/any IDE; editors are clients of the boundary, not authors of it.

## Consequences

- New capabilities are registered in `src/services/capabilityManifest.ts` with a `proves` command/route (live) or an owner (blocked).
- L5 adds `src/services/bugDetectiveService.ts`, a `bug-diagnosis-evidence` gate, and a `defect` failure class — all advisory, fail-closed, measured.
- L2 gains the preview plane (ephemeral worktree + dev server + iframe/screenshot proxy, commit→preview mapping) as an additive tab; it does not alter the loop, doctrine, or any gate.
- L7 wires dual-language rendering into every API/CLI/frontend output; founders and engineers read the same record in different vocabularies.
- `README.md` and `AGENTS.md` are updated in the same change as any behavior-altering code.

## Related

- ADR-010 (isolated execution boundary)
- ADR-011 (one model-egress door)
- ADR-017 (RBAC on mutation routes)
- README Architecture section (four boundaries → seven layers)
31 changes: 25 additions & 6 deletions docs/audit/CODEBASE-INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@
> Generated by `npm run render:codebase-index` from `git ls-files`. Do not edit by hand;
> `npm run render:codebase-index -- --check` fails when this file and the tree disagree.

**Tracked files:** 469. **Services:** 69. **API route modules:** 18. **Tests:** 87. **Scripts:** 46. **Doctrine files:** 7. **ADRs:** 16. **Documented pages under docs/:** 43. **Sprint records:** 34.
**Tracked files:** 497. **Services:** 71. **API route modules:** 20. **Tests:** 92. **Scripts:** 50. **Doctrine files:** 7. **ADRs:** 21. **Documented pages under docs/:** 48. **Sprint records:** 34.

## Tracked files by top-level directory

| Directory | Files |
|---|---:|
| `test` | 156 |
| `src` | 125 |
| `scripts` | 46 |
| `docs` | 43 |
| `test` | 161 |
| `src` | 130 |
| `scripts` | 50 |
| `docs` | 48 |
| `sprints` | 34 |
| `(root files)` | 21 |
| `deploy` | 11 |
| `skills` | 11 |
| `runs` | 8 |
| `doctrine` | 7 |
| `tasks` | 5 |
| `tasks` | 6 |
| `artifacts` | 4 |
| `.github` | 3 |
| `site` | 3 |
Expand All @@ -32,6 +33,7 @@
- `src/services/appwriteService.ts`
- `src/services/auditEventService.ts`
- `src/services/autonomyService.ts`
- `src/services/bugDetectiveService.ts`
- `src/services/capabilityManifest.ts`
- `src/services/clientDeliveryService.ts`
- `src/services/commitService.ts`
Expand Down Expand Up @@ -68,6 +70,7 @@
- `src/services/outcomeService.ts`
- `src/services/parallelWorktreeService.ts`
- `src/services/pipelineOrchestrator.ts`
- `src/services/previewPlaneService.ts`
- `src/services/prFlowService.ts`
- `src/services/productEvaluationService.ts`
- `src/services/qualityGateService.ts`
Expand Down Expand Up @@ -98,6 +101,7 @@
## API route modules (`src/api/routes/`)

- `src/api/routes/agents.routes.ts`
- `src/api/routes/bugDetective.routes.ts`
- `src/api/routes/client.routes.ts`
- `src/api/routes/context.routes.ts`
- `src/api/routes/deployment.routes.ts`
Expand All @@ -107,6 +111,7 @@
- `src/api/routes/loop.routes.ts`
- `src/api/routes/operations.routes.ts`
- `src/api/routes/operator.routes.ts`
- `src/api/routes/preview.routes.ts`
- `src/api/routes/proof.routes.ts`
- `src/api/routes/schemas.routes.ts`
- `src/api/routes/telemetry.routes.ts`
Expand All @@ -123,11 +128,13 @@
- `test/appwrite-integration.test.ts`
- `test/audit-event-schema.test.ts`
- `test/bench-fixtures.test.ts`
- `test/bug-detective.test.ts`
- `test/capability-manifest.test.ts`
- `test/context-quality.test.ts`
- `test/delivery-loop.test.ts`
- `test/deploy-contract.test.ts`
- `test/diagnose-on-stuck.test.ts`
- `test/dual-language-report.test.ts`
- `test/durable-store-writer-lock.test.ts`
- `test/egress-confinement.test.ts`
- `test/enforcement-mode.test.ts`
Expand Down Expand Up @@ -177,6 +184,8 @@
- `test/parallel-execution.test.ts`
- `test/pr-config-preflight.test.ts`
- `test/pr-flow.test.ts`
- `test/preview-plane.test.ts`
- `test/rbac-routes.test.ts`
- `test/rbac-service.test.ts`
- `test/readiness-evidence.test.ts`
- `test/readme-truth.test.ts`
Expand All @@ -189,6 +198,7 @@
- `test/skills-bridge.test.ts`
- `test/skills-registry.test.ts`
- `test/storage-backend.test.ts`
- `test/tenant-provisioning.test.ts`
- `test/tool-applier.test.ts`
- `test/trial-report.test.ts`
- `test/unrelated-writes-report.test.ts`
Expand Down Expand Up @@ -226,12 +236,14 @@
- `scripts/run-factory-loop.ts`
- `scripts/set-secret.sh`
- `scripts/set-server-secret.sh`
- `scripts/setup-server-keys.sh`
- `scripts/trial-note.ts`
- `scripts/trial-report.ts`
- `scripts/unrelated-writes-report.ts`
- `scripts/vendor-skill.ts`
- `scripts/verify-appwrite-scopes.sh`
- `scripts/verify-argv-leak-control.sh`
- `scripts/verify-bug-detective.sh`
- `scripts/verify-deploy.sh`
- `scripts/verify-docs.sh`
- `scripts/verify-env.sh`
Expand All @@ -249,7 +261,9 @@
- `scripts/verify-layer4.sh`
- `scripts/verify-loop.sh`
- `scripts/verify-no-secrets.sh`
- `scripts/verify-observability.sh`
- `scripts/verify-pr-config.ts`
- `scripts/verify-preview-plane.sh`
- `scripts/verify-release.sh`
- `scripts/verify-secret-gate-control.sh`
- `scripts/verify-slo.ts`
Expand Down Expand Up @@ -283,3 +297,8 @@
- `docs/adr/ADR-014-executor-host-operator-owned-private.md`
- `docs/adr/ADR-015-horizontal-scale-requires-a-shared-store.md`
- `docs/adr/ADR-016-delete-the-rust-runtime.md`
- `docs/adr/ADR-017-enforce-rbac-on-mutation-routes.md`
- `docs/adr/ADR-018-self-serve-tenant-provisioning.md`
- `docs/adr/ADR-019-niche-completion.md`
- `docs/adr/ADR-020-backup-restore-drill-in-ci.md`
- `docs/adr/ADR-021-seven-layer-architecture.md`
2 changes: 1 addition & 1 deletion doctrine/hooks/hooks.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
},
"report": {
"before": ["doctrine-integrity"],
"after": ["evidence-is-machine-derived"]
"after": ["evidence-is-machine-derived", "bug-diagnosis-evidence"]
}
}
}
2 changes: 1 addition & 1 deletion doctrine/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"DOCTRINE.md": "sha256:6f71f374aca64b05b60d9556ef91d104a69a997de2d20f5fb75d77038f05aacb",
"README.md": "sha256:9cf9938e7fab8e0ee30df1d7de2f8f7b97d21fe7a5713193144327932cfc30c2",
"agents/models.json": "sha256:85c12e4f460e3a31e5e301c7e1d5d4a9fdc77f795124582c634680276f261ed3",
"hooks/hooks.json": "sha256:7013aa8f3ac2c389a1245e642aaaeaa22f73fdb3abed6bc943de126697e693b1",
"hooks/hooks.json": "sha256:a35e73310f145cfe9179784902c5d7c275a8700bf3f3beacca98963204ce1d8e",
"loop.json": "sha256:565a0d93817db3e161a56ea9f7b704b2bba314f44e9443c466058a2cab29f433",
"rules/rules.json": "sha256:303c8b21f2f2769de9fea15060a8a38bb88c306d82f76c754b8b7c4f3e606b2a"
}
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
"trial:note": "tsx scripts/trial-note.ts",
"unrelated-writes:report": "tsx scripts/unrelated-writes-report.ts",
"verify:loop": "bash scripts/verify-loop.sh",
"verify:preview-plane": "bash scripts/verify-preview-plane.sh",
"verify:bug-detective": "bash scripts/verify-bug-detective.sh",
"verify:observability": "bash scripts/verify-observability.sh",
"verify:tool-agnostic-boundary": "echo 'Planned: tool-agnostic IDE/CLI boundary. No implementation yet; owner: engineering.'",
"verify:deploy": "npm run build && bash scripts/verify-deploy.sh",
"verify:fundios": "tsx scripts/verify-fundios-e2e.ts"
},
Expand Down
Loading
Loading