From b7430f17cb39aa0974b513336589dc64af8e5c61 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:33:05 +0200 Subject: [PATCH 01/18] docs: establish canonical c0py reconstruction masterplan --- docs/MASTERPLAN.md | 143 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 docs/MASTERPLAN.md diff --git a/docs/MASTERPLAN.md b/docs/MASTERPLAN.md new file mode 100644 index 0000000..e282548 --- /dev/null +++ b/docs/MASTERPLAN.md @@ -0,0 +1,143 @@ +# C0PY Masterplan — Canonical Web Product Reconstruction Engine + +**Status:** canonical +**Owner:** C0PY +**Rule:** this document and the C0PY IR contracts are the single source of truth for web/product capture and reconstruction across SIAX. + +## Mission + +C0PY turns an observed web product into an evidence-backed digital twin specification that can be reconstructed, verified and repaired autonomously. The system must cover visual fidelity, responsive behavior, assets, interactions, workflows, network contracts, motion, accessibility and product topology. + +## Non-negotiable architecture + +```text +Source product + -> discovery + -> deterministic capture + -> semantic exploration + -> Canonical Evidence Graph / IR + -> frozen reconstruction specs + -> builder adapters + -> preview deployment + -> multidimensional verification + -> repair loop + -> production candidate +``` + +No crawler, AI builder or upstream project owns the truth. The Canonical IR owns the truth. + +## Canonical layers + +1. **Discovery** — routes, sitemaps, links, navigation, semantic workflow discovery. +2. **Capture** — Playwright + CDP as primary runtime; DOM, CSSOM, computed styles, accessibility tree, screenshots, storage, network, WebSocket/SSE, canvas/media and performance. +3. **Evidence** — every assertion stores source, method, capture context, confidence and provenance. +4. **Product model** — entities, relationships, capabilities, permissions, workflows and state machines inferred from observed behavior. +5. **Specification** — deterministic page/component/workflow contracts generated from the evidence graph. +6. **Reconstruction** — adapters for v0, Lovable, Codex and generic agents. Builders consume specs; they do not inspect the source as authority. +7. **Verification** — geometry, typography, color, assets, routes, state, interaction, workflow, network, motion, accessibility and runtime health. +8. **Repair** — failures become typed root-cause work items and are repaired iteratively. + +## Primary technology decisions + +- Browser runtime: Playwright. +- Deep browser instrumentation: Chrome DevTools Protocol. +- Crawl orchestration: Crawlee-compatible request graph. +- Session/event replay: rrweb adapter. +- Semantic exploration: Browser Use / Browser Harness adapters. +- Visual comparison: pixelmatch-compatible deterministic diff plus computed-style root cause analysis. +- Optional WebGL forensics: Spector.js adapter. +- Optional archival: SingleFile and Browsertrix only behind process/service adapters due to copyleft boundaries. +- Output target: clean SIAX architecture, normally Next.js + React + TypeScript, regardless of source framework. + +## Upstream capability policy + +Every borrowed idea or implementation MUST be classified as one of: + +- `CORE` — implemented and owned inside C0PY. +- `DEPENDENCY` — consumed as a package/library. +- `CHERRY_PICK` — imported/adapted source with exact provenance and license notice. +- `ADAPTER` — isolated integration behind a C0PY contract. +- `REIMPLEMENT` — behavior/specification reproduced without copying source. +- `REFERENCE_ONLY` — studied, never included in runtime. +- `DROP` — rejected duplicate or lower-value implementation. + +See `docs/UPSTREAM-CAPABILITY-MATRIX.md`. + +## Canonical package topology + +```text +packages/ + types/ canonical shared contracts + c0py-core/ + discovery/ + capture/ + evidence/ + provenance/ + product-model/ + specification/ + verification/ + repair/ + adapters/ +``` + +As implementation grows, high-cohesion modules may graduate into their own workspace packages, but they must continue to consume the same IR contracts. + +## Evidence model + +Evidence confidence MUST use explicit semantics: + +- `measured`: deterministic machine measurement. +- `observed`: directly observed behavior/state. +- `inferred`: reasoned from evidence, not directly visible. +- `declared`: supplied by an authorized configuration/specification. +- `unknown`: insufficient evidence. + +`invented` is prohibited in clone mode. Adapt/blend mode may create new design/product choices, but they must be marked as synthetic and never confused with source evidence. + +## Operating modes + +- **clone** — maximize observable fidelity; no creative substitutions without an explicit evidence gap. +- **adapt** — preserve approved product semantics while transforming brand/design/technology. +- **blend** — combine explicitly selected capabilities/patterns from multiple references into a new product; every source lineage remains traceable. + +## Quality gates + +A single visual score is forbidden as the release criterion. C0PY uses a fidelity vector: + +- geometry +- typography +- colors +- assets +- responsive states +- route coverage +- interaction/state coverage +- workflow coverage +- network-contract parity +- motion parity +- accessibility semantics +- console/runtime health +- production build health + +Critical routes, contracted workflows and required interaction states must reach 100% coverage before a clone can be marked complete. Visual tolerances are profile-specific and recorded in the manifest. + +## Cross-repo rule + +Other SIAX repositories may consume C0PY capabilities, evidence and generated specs, but MUST NOT fork a parallel capture ontology, fidelity model or reconstruction masterplan. Cross-repo integrations point back to C0PY contracts/versioned schemas. + +## Delivery order + +1. Canonical IR + provenance. +2. Playwright/CDP capture. +3. route topology and deterministic extraction. +4. HAR/network evidence and authenticated capture profiles. +5. interaction/state delta engine. +6. rrweb replay/event timeline. +7. semantic workflow discovery adapters. +8. design-system extraction. +9. media/motion/WebGL adapters. +10. specification generator. +11. reconstruction adapters. +12. multidimensional QA. +13. autonomous repair loop. +14. clone/adapt/blend orchestration. +15. MCP/API contracts and fleet automations. From 8e44be0b6904746fd29be7d34a7372fa09791b9a Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:33:21 +0200 Subject: [PATCH 02/18] docs: add upstream capability adoption matrix --- docs/UPSTREAM-CAPABILITY-MATRIX.md | 52 ++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 docs/UPSTREAM-CAPABILITY-MATRIX.md diff --git a/docs/UPSTREAM-CAPABILITY-MATRIX.md b/docs/UPSTREAM-CAPABILITY-MATRIX.md new file mode 100644 index 0000000..fd7f991 --- /dev/null +++ b/docs/UPSTREAM-CAPABILITY-MATRIX.md @@ -0,0 +1,52 @@ +# C0PY Upstream Capability Matrix + +This matrix defines how C0PY consumes high-value upstream ideas without creating duplicate runtimes or conflicting sources of truth. + +| Upstream | Classification | Adopt | Do not adopt | +|---|---|---|---| +| Mahanaicoach/ai-site-cloner | CHERRY_PICK / REIMPLEMENT | deterministic extraction, compact state deltas, responsive probes, canvas capture patterns, spec generation/linting, pixel + CSS root-cause QA, resumable manifests | duplicate orchestration/runtime ownership | +| jongko54/webEmbedding | CHERRY_PICK / REIMPLEMENT | HAR capture/replay contracts, authenticated storage-state capture, evidence artifacts, replay-readiness, failure taxonomy, verification patterns, MCP surface | a second canonical evidence model | +| tentenco/ai-website-clone | REIMPLEMENT / REFERENCE_ONLY | clone/adapt/blend modes, evidence-confidence model, reference ledger, motion audit, deterministic acceptance gates | duplicate capture pipeline | +| Omerfaruk-aydn/sitecloner | CHERRY_PICK / REIMPLEMENT | media discovery, yt-dlp/ffmpeg integration patterns, animation extraction, interaction maps, source/clone recording and frame comparison | duplicate browser crawler and visual diff core | +| microsoft/playwright | DEPENDENCY | canonical browser automation/runtime | custom replacement browser runtime | +| Chrome DevTools Protocol | DEPENDENCY | DOMSnapshot, CSS, Animation, Network, Runtime, Accessibility, Performance, Coverage | undocumented browser scraping where a typed CDP domain exists | +| apify/crawlee | DEPENDENCY | request queue, crawl graph, browser crawl orchestration | separate canonical route ontology | +| browser-use/browser-use | ADAPTER | semantic exploration, task/workflow discovery | low-level deterministic measurement | +| browser-use/browser-harness | ADAPTER | authenticated real-browser/CDP exploration | canonical IR ownership | +| rrweb-io/rrweb | DEPENDENCY / ADAPTER | DOM mutation timeline, interaction record/replay | replacing C0PY evidence contracts | +| BabylonJS/Spector.js | ADAPTER | optional WebGL frame forensics | mandatory core dependency | +| mapbox/pixelmatch | DEPENDENCY | deterministic pixel diff primitive | single release score | +| dequelabs/axe-core | DEPENDENCY | accessibility verification | copied implementation | +| Google Lighthouse | DEPENDENCY / TOOL | performance/runtime comparison | product behavior truth | +| gildas-lormeau/SingleFile | ADAPTER | archival/reference snapshot only | copied AGPL code in C0PY core | +| webrecorder/browsertrix-crawler | ADAPTER | optional WARC/WACZ archival service | copied AGPL code in C0PY core | +| Stagehand | ADAPTER | semantic observe/extract/act where deterministic selectors are insufficient | source-of-truth capture engine | + +## Import rules + +1. Every source-derived implementation must record repository, commit SHA, source files, license, integration method and tests. +2. MIT/ISC/Apache components may be integrated according to their license and notices. +3. Copyleft components must stay behind a separately deployable adapter unless a deliberate licensing decision says otherwise. +4. Prefer dependencies over vendoring when the upstream public API is stable and sufficient. +5. Prefer reimplementation from behavior/specification when importing code would create architectural duplication. +6. No upstream project may define C0PY's schema, ontology or release criteria. + +## Provenance record example + +```yaml +capability: visual-css-root-cause +classification: CHERRY_PICK +source: + repository: Mahanaicoach/ai-site-cloner + commit: + files: + - scripts/compare.mjs +license: MIT +integration: + target: packages/c0py-core/src/verification + method: adapted +tests: + - geometry-diff + - typography-diff + - responsive-diff +``` From 982c7b19fcaea8d83d9ea8b2c4a596bc2a1595f6 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:33:43 +0200 Subject: [PATCH 03/18] docs: define c0py engineering and evidence standards --- docs/STANDARDS.md | 127 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 docs/STANDARDS.md diff --git a/docs/STANDARDS.md b/docs/STANDARDS.md new file mode 100644 index 0000000..980f0e4 --- /dev/null +++ b/docs/STANDARDS.md @@ -0,0 +1,127 @@ +# C0PY Standards + +## 1. Single-source-of-truth standard + +C0PY owns the canonical schemas for capture evidence, product topology, reconstruction specifications and fidelity verification. Other repositories may integrate with these contracts but may not create competing definitions. + +## 2. Evidence standard + +Every material claim about a source product must be represented with: + +- stable evidence id +- evidence kind +- source URL/route +- capture profile +- viewport/device context when relevant +- timestamp +- acquisition method +- confidence class +- provenance/source implementation +- payload or durable object reference + +Confidence classes: `measured`, `observed`, `inferred`, `declared`, `unknown`. + +In `clone` mode synthetic/invented facts are forbidden. In `adapt` and `blend`, synthetic values must be explicitly labeled. + +## 3. Capture standard + +Deterministic capture has precedence over AI interpretation. + +Preferred order: + +1. browser/browser-protocol measurement +2. runtime event/network observation +3. structured source metadata +4. semantic agent observation +5. inference + +Playwright is the standard browser automation layer. Raw CDP is used for capabilities that require deeper browser instrumentation. + +## 4. Route and workflow standard + +Routes and workflows are graph data, not prose. Each discovered route/action/state transition is uniquely identifiable and links to its supporting evidence. + +A workflow is complete only when its required preconditions, actions, transitions, resulting states, error paths and relevant network contracts are represented. + +## 5. Reconstruction standard + +Builders consume frozen, versioned C0PY specifications. v0, Lovable, Codex and future builders are adapters, not authorities. + +Generated implementations must preserve: + +- component contracts +- responsive contracts +- interaction/state contracts +- route contracts +- network/domain contracts where reconstruction scope includes them +- accessibility semantics +- fidelity thresholds + +## 6. Upstream standard + +Every external capability is classified as `CORE`, `DEPENDENCY`, `CHERRY_PICK`, `ADAPTER`, `REIMPLEMENT`, `REFERENCE_ONLY` or `DROP`. + +Any source-derived code must preserve required copyright/license notices and record exact provenance. + +AGPL/copyleft systems such as SingleFile/Browsertrix remain isolated adapters/services unless C0PY deliberately changes licensing strategy. + +## 7. Verification standard + +Do not reduce fidelity to one number. Required dimensions include: + +- geometry +- typography +- color +- assets +- responsive behavior +- route coverage +- interactions and states +- workflows +- network contracts +- motion +- accessibility +- runtime errors +- build health + +Release gates are profile/version controlled. Critical route/workflow/state coverage defaults to 100%. + +## 8. Failure standard + +Failures are typed and machine-actionable. Minimum families: + +- `CaptureFailure` +- `DiscoveryFailure` +- `EvidenceGap` +- `ReconstructionFailure` +- `VerificationFailure` +- `AuthorizationBoundary` +- `UnsupportedSurface` +- `DynamicContentVariance` +- `NetworkReplayLimited` +- `AuthSessionMissing` + +Every repair loop consumes typed failures rather than unstructured screenshots or generic prompts. + +## 9. Security and authorization standard + +Only capture resources and product states that the operator is authorized to access. Authentication state is supplied explicitly through capture profiles. Credentials and session material never enter source control. + +C0PY does not bypass access controls. Failed authorization is evidence and is represented as such. + +## 10. CI standard + +Changes to canonical schemas, evidence confidence semantics, capability taxonomy, release gates or adapter boundaries require: + +- schema/type checks +- unit tests +- provenance/license checks where applicable +- documentation update +- backward-compatibility note or explicit version bump + +## 11. Automation standard + +Automations must be idempotent, resumable and evidence-producing. A job may retry execution, but may not silently mutate evidence history or overwrite the lineage of an earlier capture. + +## 12. Cross-repo standard + +When another SIAX product wants website/product cloning, analysis or reconstruction, it must call/import C0PY instead of adding its own crawler/clone ontology. Shared automation and prompt systems reference this standard and the C0PY Masterplan. From 4a88f74627415097b8152ddfda16210b99f44ebd Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:34:03 +0200 Subject: [PATCH 04/18] docs: define c0py autonomous execution workflows --- docs/AUTOMATIONS.md | 98 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 docs/AUTOMATIONS.md diff --git a/docs/AUTOMATIONS.md b/docs/AUTOMATIONS.md new file mode 100644 index 0000000..0539a78 --- /dev/null +++ b/docs/AUTOMATIONS.md @@ -0,0 +1,98 @@ +# C0PY Automations + +## Automation principles + +C0PY automations are resumable, idempotent, versioned and evidence-producing. Every run emits a manifest, provenance and machine-readable failures. + +## Canonical pipeline + +```text +DISCOVER + -> CAPTURE + -> NORMALIZE TO IR + -> MODEL PRODUCT + -> FREEZE SPEC + -> RECONSTRUCT + -> DEPLOY PREVIEW + -> VERIFY + -> REPAIR (if failed) + -> VERIFY + -> RELEASE CANDIDATE +``` + +## Jobs + +### discover-target +Inputs: target URL, capture profile, scope policy. +Outputs: route graph, navigation graph, discovered workflows, crawl queue. + +### capture-target +Uses Playwright/CDP and optional adapters. Captures DOM/runtime HTML, styles, accessibility, media/assets, screenshots, network/HAR, storage metadata, events and performance. + +### interaction-sweep +Enumerates deterministic interactive states and records before/after deltas. Semantic agents may propose candidate flows; deterministic capture verifies them. + +### workflow-discovery +Uses semantic browser adapters to discover product tasks and translates them into explicit action/state graphs with evidence links. + +### normalize-evidence +Validates captured artifacts and writes the Canonical IR/Evidence Graph. Rejects untyped or provenance-free critical evidence. + +### generate-spec +Creates frozen reconstruction contracts for routes, components, design tokens, responsive states, workflows and network/domain behavior. + +### reconstruct +Dispatches versioned specs to selected builders (`v0`, `lovable`, `codex`, `generic`). Generated code is never treated as evidence about the source. + +### preview +Builds and deploys a preview target. Vercel is a supported deployment adapter; SIAX/Coolify remains supported for controlled infrastructure. + +### verify +Runs the fidelity vector: visual geometry/style, responsive, routes, interactions, workflows, network, motion, accessibility, runtime and build checks. + +### repair +Turns verification failures into typed repair tasks, applies the smallest justified patch and sends the result back through verification. Repair may not relax gates without an explicit versioned policy change. + +### upstream-reconcile +Scheduled/manual automation that checks registered upstream projects for high-value changes. It creates candidate capability records only; it never auto-merges foreign code without provenance/license/test gates. + +### schema-compatibility +On every IR/schema change, validates backward compatibility and requires a version bump for incompatible changes. + +### license-provenance +Checks all `CHERRY_PICK` and vendored/adapted source entries for repository, SHA, source path, classification and license/notice requirements. + +## Required run manifest + +Each automation run records at minimum: + +- run id +- target id +- C0PY commit/version +- schema version +- capture profile +- started/completed timestamps +- tool/adapter versions +- evidence object ids +- warnings and typed failures +- retry lineage +- output spec version +- verification result + +## Failure policy + +No automation may convert a failed measurement into an inferred success. Failed or inaccessible states remain explicit evidence gaps. + +## CI/CD gates + +Pull requests touching capture, IR, product model, reconstruction contracts or fidelity rules must run: + +1. typecheck +2. unit tests +3. schema validation +4. provenance validation +5. license boundary validation +6. representative deterministic fixture capture +7. reconstruction fixture verification when affected + +Production promotion is blocked when critical route/workflow/state gates fail. From 1e3abaf824edc9d97d8993fc40d0dce93a56dfce Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:34:23 +0200 Subject: [PATCH 05/18] feat(types): add canonical evidence and reconstruction contracts --- packages/types/src/index.ts | 186 ++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 6419723..c79af35 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -28,3 +28,189 @@ export interface Registry { createdAt: Date; updatedAt: Date; } + +export type CapabilityDisposition = + | "CORE" + | "DEPENDENCY" + | "CHERRY_PICK" + | "ADAPTER" + | "REIMPLEMENT" + | "REFERENCE_ONLY" + | "DROP"; + +export type EvidenceConfidence = + | "measured" + | "observed" + | "inferred" + | "declared" + | "unknown"; + +export type ReconstructionMode = "clone" | "adapt" | "blend"; + +export type EvidenceKind = + | "dom" + | "runtime-html" + | "computed-style" + | "stylesheet" + | "accessibility" + | "screenshot" + | "asset" + | "network-request" + | "network-response" + | "har" + | "websocket" + | "sse" + | "storage" + | "interaction" + | "state-transition" + | "workflow" + | "animation" + | "media" + | "canvas" + | "webgl" + | "performance" + | "semantic-observation"; + +export interface CaptureViewport { + width: number; + height: number; + deviceScaleFactor?: number; + isMobile?: boolean; + hasTouch?: boolean; +} + +export interface CaptureProfile { + id: string; + name: string; + authenticated: boolean; + role?: string; + locale?: string; + colorScheme?: "light" | "dark" | "no-preference"; + viewport?: CaptureViewport; + featureFlags?: Record; +} + +export interface ProvenanceSource { + repository?: string; + commit?: string; + sourcePaths?: string[]; + license?: string; + classification?: CapabilityDisposition; + adapter?: string; + tool?: string; + toolVersion?: string; +} + +export interface EvidenceRecord { + id: string; + targetId: string; + kind: EvidenceKind; + route?: string; + capturedAt: string; + method: string; + confidence: EvidenceConfidence; + captureProfileId: string; + viewport?: CaptureViewport; + source: ProvenanceSource; + payload: T; +} + +export interface RouteNode { + id: string; + path: string; + canonicalUrl?: string; + title?: string; + evidenceIds: string[]; +} + +export interface RouteEdge { + from: string; + to: string; + trigger: "link" | "redirect" | "action" | "script" | "semantic-discovery"; + evidenceIds: string[]; +} + +export interface StateTransition { + id: string; + fromState: string; + toState: string; + action: string; + evidenceIds: string[]; + networkEvidenceIds?: string[]; +} + +export interface ProductEntity { + id: string; + name: string; + attributes: Record; + evidenceIds: string[]; + confidence: EvidenceConfidence; +} + +export interface ProductRelationship { + id: string; + fromEntityId: string; + toEntityId: string; + type: string; + cardinality?: "one-to-one" | "one-to-many" | "many-to-one" | "many-to-many"; + evidenceIds: string[]; + confidence: EvidenceConfidence; +} + +export interface WorkflowStep { + id: string; + action: string; + preconditions?: string[]; + resultingState?: string; + evidenceIds: string[]; +} + +export interface ProductWorkflow { + id: string; + name: string; + steps: WorkflowStep[]; + errorPaths?: WorkflowStep[][]; + evidenceIds: string[]; + confidence: EvidenceConfidence; +} + +export interface FidelityVector { + geometry?: number; + typography?: number; + colors?: number; + assets?: number; + responsiveCoverage?: number; + routeCoverage?: number; + interactionCoverage?: number; + workflowCoverage?: number; + networkContractParity?: number; + motionParity?: number; + accessibilityPass?: boolean; + runtimeErrorCount?: number; + productionBuildPass?: boolean; +} + +export interface UpstreamCapabilityRecord { + id: string; + capability: string; + disposition: CapabilityDisposition; + source: ProvenanceSource; + targetModule?: string; + rationale: string; + tests: string[]; +} + +export interface ReconstructionSpec { + id: string; + targetId: string; + version: string; + mode: ReconstructionMode; + schemaVersion: string; + evidenceIds: string[]; + routes: RouteNode[]; + routeEdges: RouteEdge[]; + entities: ProductEntity[]; + relationships: ProductRelationship[]; + workflows: ProductWorkflow[]; + fidelityRequirements: FidelityVector; +} From b885a160bdf45624dd8fe5bd9800707700d4fb43 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:34:45 +0200 Subject: [PATCH 06/18] feat(core): add upstream provenance registry validation --- packages/c0py-core/src/provenance/registry.ts | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 packages/c0py-core/src/provenance/registry.ts diff --git a/packages/c0py-core/src/provenance/registry.ts b/packages/c0py-core/src/provenance/registry.ts new file mode 100644 index 0000000..9514c98 --- /dev/null +++ b/packages/c0py-core/src/provenance/registry.ts @@ -0,0 +1,50 @@ +import type { UpstreamCapabilityRecord } from "@siax/c0py-types"; + +const COPyleft_ISOLATED = new Set(["AGPL-3.0", "AGPL-3.0-only", "AGPL-3.0-or-later"]); + +export interface ProvenanceValidationResult { + valid: boolean; + errors: string[]; + warnings: string[]; +} + +export function validateUpstreamCapability( + record: UpstreamCapabilityRecord, +): ProvenanceValidationResult { + const errors: string[] = []; + const warnings: string[] = []; + const source = record.source; + + if (!record.capability.trim()) errors.push("capability is required"); + if (!record.rationale.trim()) errors.push("rationale is required"); + if (record.disposition !== "DROP" && record.tests.length === 0) { + errors.push("at least one verification test is required"); + } + + if (["CHERRY_PICK", "REFERENCE_ONLY", "REIMPLEMENT"].includes(record.disposition)) { + if (!source.repository) errors.push("source.repository is required"); + if (!source.commit) errors.push("source.commit is required"); + } + + if (record.disposition === "CHERRY_PICK") { + if (!source.sourcePaths?.length) errors.push("source.sourcePaths is required for CHERRY_PICK"); + if (!source.license) errors.push("source.license is required for CHERRY_PICK"); + } + + if (source.license && COPyleft_ISOLATED.has(source.license) && record.disposition === "CHERRY_PICK") { + errors.push("AGPL/copy-left source must remain behind an adapter/service boundary; do not cherry-pick into core"); + } + + if (source.license && COPyleft_ISOLATED.has(source.license) && record.disposition !== "ADAPTER") { + warnings.push("copyleft source should normally be classified as ADAPTER"); + } + + return { valid: errors.length === 0, errors, warnings }; +} + +export function assertUpstreamCapability(record: UpstreamCapabilityRecord): void { + const result = validateUpstreamCapability(record); + if (!result.valid) { + throw new Error(`Invalid upstream capability ${record.id}: ${result.errors.join("; ")}`); + } +} From 56e4b696f4841eeb1b5fdd3f31dc01f2172330c5 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:34:54 +0200 Subject: [PATCH 07/18] feat(core): export provenance validation --- packages/c0py-core/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/c0py-core/src/index.ts b/packages/c0py-core/src/index.ts index 528ed0a..a4651cf 100644 --- a/packages/c0py-core/src/index.ts +++ b/packages/c0py-core/src/index.ts @@ -3,3 +3,4 @@ export * from "./registry/registry"; export * from "./registry/analyzer"; export * from "./crawler/types"; export * from "./registry/types"; +export * from "./provenance/registry"; From 053b524fa4895ccac67d05e05a5a122b25700165 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:35:11 +0200 Subject: [PATCH 08/18] docs: redefine c0py as canonical reconstruction engine --- README.md | 70 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 92c5c7a..c64bd0a 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # C0PY -**Verktyg för att skapa fullständigt register över en hemsida ut alla aspekter.** +**Canonical SIAX engine for evidence-driven web product capture, digital-twin specification, reconstruction and verification.** -C0PY konsumerar en webbadress och producerar ett komplett register: sida-för-sida innehåll, struktur, prestanda, säkerhet, SEO, metadata och mer. Allt lagras som en tillförlitlig, återläsbar sammanställning. +C0PY consumes an authorized web target and produces a versioned Evidence Graph / Canonical IR covering routes, DOM/runtime state, styles, assets, responsive behavior, interactions, workflows, network contracts, motion, accessibility and product topology. Reconstruction builders consume frozen C0PY specs; they never become the source of truth. ## Snabbkommandon @@ -12,27 +12,61 @@ pnpm --filter @siax/c0py-api dev pnpm --filter @siax/c0py-web dev ``` -## Arkitektur +## Canonical architecture -``` -apps/api/ → Fastify/Next.js API — /v1/c0py/* endpoints -apps/web/ → Next.js UI — registerhantering, dashboard, visualisering -packages/c0py-core → crawling, registry-uppbyggnad, analysmotor -packages/config → Zod-validerad env-laddare -packages/types → delade TypeScript-typer -docs/spec/ → Digital Twin Spec (webbplats-analys och reproduktion) +```text +Source product + -> discovery + -> Playwright/CDP deterministic capture + -> semantic workflow exploration adapters + -> Evidence Graph / Canonical IR + -> frozen reconstruction specs + -> v0 / Lovable / Codex / generic builders + -> preview deployment + -> multidimensional QA + -> typed repair loop ``` -## Konsumerade kapabiliteter +## Repo structure -| Kapabilitet | Syfte | Status | +```text +apps/api/ -> Fastify/API surface +apps/web/ -> Next.js console and visualisation +packages/c0py-core -> discovery, capture orchestration, evidence/provenance, product model, verification +packages/config -> validated runtime configuration +packages/types -> canonical shared IR/contracts +docs/spec/ -> full Digital Twin Specification +docs/MASTERPLAN.md -> canonical execution plan +docs/STANDARDS.md -> mandatory engineering/evidence rules +docs/AUTOMATIONS.md -> autonomous pipeline contracts +``` + +## Capability adoption + +External technologies are classified as `CORE`, `DEPENDENCY`, `CHERRY_PICK`, `ADAPTER`, `REIMPLEMENT`, `REFERENCE_ONLY` or `DROP`. See [`docs/UPSTREAM-CAPABILITY-MATRIX.md`](docs/UPSTREAM-CAPABILITY-MATRIX.md). + +Primary integrations include Playwright/CDP, Crawlee-compatible crawl orchestration, rrweb, Browser Use/Browser Harness adapters, deterministic pixel/style verification, optional Spector.js WebGL forensics, and isolated archival adapters. Builders include v0, Lovable, Codex and generic agents. + +## Operating modes + +- `clone` — maximize observed fidelity; synthetic facts are prohibited. +- `adapt` — preserve approved semantics while transforming design/technology. +- `blend` — combine explicitly selected capabilities/patterns with complete provenance. + +## Quality + +C0PY does not use one visual score as a release verdict. It verifies a fidelity vector across geometry, typography, colors, assets, responsive states, routes, interactions, workflows, network contracts, motion, accessibility, runtime errors and production build health. + +## SIAX platform capabilities + +| Capability | Purpose | Status | |---|---|---| -| CL0UD | Autentisering, RBAC, tenant | live | -| AUD0 | Regeleveranshändelser | (ej live) | -| ST0RE | Objektlagring av registerdata | (ej live) | -| INF0 | Innehållsanalys | (ej live) | -| N0D | Asynkrone crawling-jobb | (ej live) | +| CL0UD | Authentication, RBAC, tenant | live | +| AUD0 | Audit/event delivery | planned integration | +| ST0RE | Evidence/object storage | planned integration | +| INF0 | AI/semantic analysis | planned integration | +| N0D | Async capture/reconstruction jobs | planned integration | ## Deploy -SIAX Cloud via Coolify. Se [`DEPLOY.md`](DEPLOY.md). +SIAX Cloud via Coolify. Vercel is supported as a reconstruction preview adapter. See [`DEPLOY.md`](DEPLOY.md). From be942285b1e892eb0a3ae0b3c1ac5112881fcc84 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:35:29 +0200 Subject: [PATCH 09/18] docs: align agent rules with canonical reconstruction architecture --- AGENTS.md | 82 +++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 65 insertions(+), 17 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 9adb7b8..7accae9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,19 +1,10 @@ # C0PY — AGENTS.md -## Repo-konventioner +## Canonical mandate -- **Package manager**: pnpm (frozen-lockfile) -- **Framework**: Next.js (apps/web), Fastify (apps/api) -- **TypeScript**: strict mode, bundler module resolution -- **CI**: Gitea Actions — `.gitea/workflows/ci.yml` -- **Deploy**: Coolify via `.gitea/workflows/deploy.yml` -- **Secrets**: Infisical (`vault.siax.io`) — ALDRIG i repo -- **Testing**: vitest (apps/api, packages/*) -- **Lint**: eslint flat config -- **OTel**: not yet wired — add bootstrap at apps/api/src/index.ts entry when available -- **Tenant**: bound to session via CL0UD, NEVER from client input +C0PY is the SIAX source of truth for web/product capture, evidence, digital-twin specifications, reconstruction contracts and fidelity verification. Agents MUST follow `docs/MASTERPLAN.md`, `docs/STANDARDS.md`, `docs/AUTOMATIONS.md` and `docs/UPSTREAM-CAPABILITY-MATRIX.md`. -## Drift (Coolify) +Do not create parallel capture ontologies, alternative evidence schemas or competing fidelity models in this or another SIAX repository. - **App UUID API**: `wvmn6eg40jofssvm3nigmav6`, server6 — `c0py-api.siax.io` - **App UUID Web**: `58pa82h4qlzcwsc4shreuwk0`, server6 — `c0py-web.siax.io` (`Dockerfile.web`) @@ -26,13 +17,31 @@ - **⚠️ `c0py.siax.io` apex är Worker-kapad** ("Hello World!") — ej åtgärdbar utan Workers-perms - **Coolify dockerfile+git-buildpack**: trasig för detta monorepo (build-context saknar repo-träd) — bygg manuellt -## Kontrakt +## Repo conventions -- API-kontrakt: `contracts/openapi.yaml` -- Schema-versionshantering: semantisk versionering i `packages/types` -- Digital Twin Spec: `docs/spec/DIGITAL-TWIN-SPEC.md` (fullständig specifikation för webbplats-analys och identisk reproduktion) +- Package manager: pnpm (frozen-lockfile) +- Framework: Next.js (`apps/web`), Fastify (`apps/api`) +- TypeScript: strict mode +- Canonical shared contracts: `packages/types` +- Core orchestration: `packages/c0py-core` +- CI: Gitea Actions under `.gitea/workflows/` +- Deploy: Coolify for C0PY runtime; reconstruction preview adapters may target Vercel +- Secrets: Infisical (`vault.siax.io`), NEVER in repo +- Testing: vitest +- Tenant: bound to trusted session via CL0UD, NEVER client-controlled -## Fällor +## Architecture rules + +1. Deterministic measurement beats AI interpretation. +2. Playwright is the canonical browser automation runtime; use CDP for deeper instrumentation. +3. All significant source-product assertions become typed evidence with provenance. +4. Builders (`v0`, `lovable`, `codex`, generic) consume frozen specs and may not redefine source truth. +5. Semantic agents discover candidate workflows; deterministic capture verifies them. +6. Upstream functionality is classified as `CORE`, `DEPENDENCY`, `CHERRY_PICK`, `ADAPTER`, `REIMPLEMENT`, `REFERENCE_ONLY` or `DROP` before integration. +7. Any source-derived code requires repository, commit SHA, source path, license and verification tests. +8. Copyleft/AGPL implementations stay behind isolated adapters/services unless an explicit licensing decision changes this. +9. Clone mode forbids invented facts. Evidence gaps remain explicit. +10. Verification produces a fidelity vector, never a single release score. - `NEXT_PUBLIC_*` ska ALDRI innehålla hemligheter - Alla writes till AUD0/ST0RE via klientskikt, aldrig direkt @@ -42,3 +51,42 @@ - Auth: preHandler hook kollar `Authorization: Bearer *`-header, returnerar 401 annars - **GitHub push**: använd `gh auth login` (keyring), INTE inbäddade tokens i URLs - **Coolify compose på disk kan vara stale** — labels/port regenereras ej vid misslyckad deploy; sed:a compose-filen + `docker compose up -d`, och `docker rm -f` gammal container (den lever kvar vid recreate) + +## Canonical evidence confidence + +Allowed values: + +- `measured` +- `observed` +- `inferred` +- `declared` +- `unknown` + +Synthetic values are allowed only in adapt/blend mode and must be explicitly marked as synthetic outside source evidence. + +## Capture profiles + +Authenticated or variant state must be explicit through capture profiles: role, locale, viewport/device, color scheme and feature flags. Never commit credentials, cookies, tokens or storage-state secrets. + +## Contract locations + +- API: `contracts/openapi.yaml` +- Shared IR/types: `packages/types/src/index.ts` +- Digital Twin Spec: `docs/spec/DIGITAL-TWIN-SPEC.md` +- Canonical Masterplan: `docs/MASTERPLAN.md` +- Engineering/evidence standards: `docs/STANDARDS.md` +- Automation contracts: `docs/AUTOMATIONS.md` +- Upstream adoption: `docs/UPSTREAM-CAPABILITY-MATRIX.md` + +## Drift prevention + +When a task proposes a new crawler, browser agent, screenshot comparer, product graph, capture schema or clone workflow, first map it onto existing C0PY contracts. Add a new implementation only when it contributes a distinct capability. Remove or reject duplicate sources of truth. + +## Security + +- Only capture targets/states the operator is authorized to access. +- Never bypass access controls. +- An authorization failure is evidence, not a prompt to evade the boundary. +- `NEXT_PUBLIC_*` must never contain secrets. +- Writes to platform services use their client/integration layers. +- Docker COPY across build stages can break pnpm symlinks; preserve the existing runtime-stage workaround unless replaced and verified. From 35f1a3ca668d729ea3b213daf9a49cf13c8b70e7 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:35:43 +0200 Subject: [PATCH 10/18] test(core): validate upstream provenance policy --- packages/c0py-core/tests/provenance.test.ts | 48 +++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 packages/c0py-core/tests/provenance.test.ts diff --git a/packages/c0py-core/tests/provenance.test.ts b/packages/c0py-core/tests/provenance.test.ts new file mode 100644 index 0000000..45a56d4 --- /dev/null +++ b/packages/c0py-core/tests/provenance.test.ts @@ -0,0 +1,48 @@ +import { describe, expect, it } from "vitest"; +import { validateUpstreamCapability } from "../src/provenance/registry"; + +const base = { + id: "visual-css-root-cause", + capability: "visual-css-root-cause", + disposition: "CHERRY_PICK" as const, + source: { + repository: "example/upstream", + commit: "0123456789abcdef", + sourcePaths: ["scripts/compare.mjs"], + license: "MIT", + }, + targetModule: "verification", + rationale: "Adds deterministic style-root-cause diagnostics", + tests: ["geometry-diff"], +}; + +describe("upstream provenance policy", () => { + it("accepts traceable permissive cherry-picks", () => { + expect(validateUpstreamCapability(base)).toEqual({ + valid: true, + errors: [], + warnings: [], + }); + }); + + it("rejects AGPL code cherry-picked into core", () => { + const result = validateUpstreamCapability({ + ...base, + source: { ...base.source, license: "AGPL-3.0" }, + }); + + expect(result.valid).toBe(false); + expect(result.errors.join(" ")).toMatch(/adapter\/service boundary/i); + }); + + it("requires exact provenance for source-derived implementations", () => { + const result = validateUpstreamCapability({ + ...base, + source: { license: "MIT", sourcePaths: ["compare.mjs"] }, + }); + + expect(result.valid).toBe(false); + expect(result.errors).toContain("source.repository is required"); + expect(result.errors).toContain("source.commit is required"); + }); +}); From 3687e87c7562ce4c49c8a04512732ab5834e3bfb Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:36:43 +0200 Subject: [PATCH 11/18] ci: add canonical architecture policy validator --- scripts/validate-canonical-architecture.mjs | 50 +++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 scripts/validate-canonical-architecture.mjs diff --git a/scripts/validate-canonical-architecture.mjs b/scripts/validate-canonical-architecture.mjs new file mode 100644 index 0000000..e3febc3 --- /dev/null +++ b/scripts/validate-canonical-architecture.mjs @@ -0,0 +1,50 @@ +import { readFile, access } from "node:fs/promises"; + +const requiredFiles = [ + "docs/MASTERPLAN.md", + "docs/STANDARDS.md", + "docs/AUTOMATIONS.md", + "docs/UPSTREAM-CAPABILITY-MATRIX.md", + "docs/spec/DIGITAL-TWIN-SPEC.md", + "packages/types/src/index.ts", +]; + +for (const path of requiredFiles) { + await access(path).catch(() => { + throw new Error(`Missing canonical C0PY artifact: ${path}`); + }); +} + +const types = await readFile("packages/types/src/index.ts", "utf8"); +const requiredContracts = [ + "CapabilityDisposition", + "EvidenceConfidence", + "EvidenceRecord", + "CaptureProfile", + "ProductWorkflow", + "FidelityVector", + "ReconstructionSpec", +]; + +for (const contract of requiredContracts) { + if (!types.includes(` ${contract}`)) { + throw new Error(`Missing canonical contract: ${contract}`); + } +} + +const masterplan = await readFile("docs/MASTERPLAN.md", "utf8"); +for (const disposition of [ + "CORE", + "DEPENDENCY", + "CHERRY_PICK", + "ADAPTER", + "REIMPLEMENT", + "REFERENCE_ONLY", + "DROP", +]) { + if (!masterplan.includes(`\`${disposition}\``)) { + throw new Error(`Masterplan is missing capability disposition: ${disposition}`); + } +} + +console.log("C0PY canonical architecture policy: OK"); From cfac4cc9137f3b6737472bf445fd1eb28de68308 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:36:51 +0200 Subject: [PATCH 12/18] ci: wire canonical architecture validation --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 455bc0f..576f115 100644 --- a/package.json +++ b/package.json @@ -1 +1 @@ -{"name": "c0py", "version": "0.1.0", "private": true, "description": "C0PY — SIAX Cloud. Verktyg för att skapa fullständigt register över en hemsida ut alla aspekter.", "type": "module", "scripts": {"build": "pnpm -r build", "typecheck": "pnpm -r typecheck", "test": "pnpm -r test", "lint": "eslint .", "dev:api": "pnpm --filter @siax/c0py-api dev", "dev:web": "pnpm --filter @siax/c0py-web dev", "start:api": "pnpm --filter @siax/c0py-api start"}, "devDependencies": {"typescript": "^5.7.2", "@types/node": "^24.0.0", "@eslint/js": "^9.18.0", "eslint": "^9.18.0", "eslint-config-prettier": "^10.0.0", "prettier": "^3.4.2", "typescript-eslint": "^8.20.0"}, "engines": {"node": ">=20.17.0"}, "pnpm": {"overrides": {"nanoid@<5.1.16": "5.1.16"}}, "packageManager": "pnpm@9.15.9"} \ No newline at end of file +{"name":"c0py","version":"0.1.0","private":true,"description":"C0PY — canonical SIAX web product capture, digital twin, reconstruction and verification engine.","type":"module","scripts":{"build":"pnpm -r build","typecheck":"pnpm -r typecheck","test":"pnpm -r test","lint":"eslint .","validate:architecture":"node scripts/validate-canonical-architecture.mjs","dev:api":"pnpm --filter @siax/c0py-api dev","dev:web":"pnpm --filter @siax/c0py-web dev","start:api":"pnpm --filter @siax/c0py-api start"},"devDependencies":{"typescript":"^5.7.2","@types/node":"^24.0.0","@eslint/js":"^9.18.0","eslint":"^9.18.0","eslint-config-prettier":"^10.0.0","prettier":"^3.4.2","typescript-eslint":"^8.20.0"},"engines":{"node":">=20.17.0"},"pnpm":{"overrides":{"nanoid@<5.1.16":"5.1.16"}},"packageManager":"pnpm@9.15.9"} \ No newline at end of file From ac797d3e4d73376d22a1cd3cc840a67967d46ecc Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:37:10 +0200 Subject: [PATCH 13/18] ci: enforce canonical architecture contracts --- .gitea/workflows/ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 81c3791..c96e7c6 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -13,6 +13,8 @@ jobs: version: 9.15.9 - name: Install run: pnpm install --frozen-lockfile + - name: Canonical architecture policy + run: pnpm run validate:architecture - name: Typecheck run: pnpm run typecheck - name: Test @@ -39,5 +41,7 @@ jobs: version: 9.15.9 - name: Install run: pnpm install --frozen-lockfile - - name: Check schema/contracts + - name: Canonical architecture policy + run: pnpm run validate:architecture + - name: Check schema/contracts and provenance policy run: pnpm --filter @siax/c0py-core test From 762b778ee2ce1c921d9f0a24a530e88fae430e71 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:37:59 +0200 Subject: [PATCH 14/18] feat(core): add reconstruction pipeline contracts --- .../c0py-core/src/reconstruction/contracts.ts | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 packages/c0py-core/src/reconstruction/contracts.ts diff --git a/packages/c0py-core/src/reconstruction/contracts.ts b/packages/c0py-core/src/reconstruction/contracts.ts new file mode 100644 index 0000000..c68945d --- /dev/null +++ b/packages/c0py-core/src/reconstruction/contracts.ts @@ -0,0 +1,92 @@ +import type { + CaptureProfile, + EvidenceRecord, + FidelityVector, + ReconstructionSpec, +} from "@siax/c0py-types"; + +export interface TargetDescriptor { + id: string; + url: string; + allowedOrigins: string[]; + mode: ReconstructionSpec["mode"]; +} + +export interface DiscoveryResult { + targetId: string; + routes: string[]; + candidateWorkflows: string[]; + evidence: EvidenceRecord[]; +} + +export interface CaptureRequest { + target: TargetDescriptor; + profile: CaptureProfile; + routes: string[]; +} + +export interface CaptureResult { + targetId: string; + profileId: string; + evidence: EvidenceRecord[]; + warnings: PipelineFailure[]; +} + +export interface VerificationRequest { + spec: ReconstructionSpec; + sourceEvidence: EvidenceRecord[]; + implementationUrl: string; +} + +export interface VerificationResult { + specId: string; + fidelity: FidelityVector; + failures: PipelineFailure[]; + passed: boolean; +} + +export type FailureKind = + | "CaptureFailure" + | "DiscoveryFailure" + | "EvidenceGap" + | "ReconstructionFailure" + | "VerificationFailure" + | "AuthorizationBoundary" + | "UnsupportedSurface" + | "DynamicContentVariance" + | "NetworkReplayLimited" + | "AuthSessionMissing"; + +export interface PipelineFailure { + id: string; + kind: FailureKind; + message: string; + route?: string; + evidenceIds?: string[]; + retryable: boolean; + details?: Record; +} + +export interface DiscoveryAdapter { + id: string; + discover(target: TargetDescriptor, profile: CaptureProfile): Promise; +} + +export interface CaptureAdapter { + id: string; + capture(request: CaptureRequest): Promise; +} + +export interface ReconstructionAdapter { + id: string; + reconstruct(spec: ReconstructionSpec): Promise<{ + artifactRef: string; + previewUrl?: string; + commitRef?: string; + }>; +} + +export interface VerificationAdapter { + id: string; + verify(request: VerificationRequest): Promise; +} From 52f51469404231e7fa585b0110a57ef3f3a026c0 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:38:08 +0200 Subject: [PATCH 15/18] feat(core): add deterministic fidelity release gate --- .../c0py-core/src/verification/fidelity.ts | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 packages/c0py-core/src/verification/fidelity.ts diff --git a/packages/c0py-core/src/verification/fidelity.ts b/packages/c0py-core/src/verification/fidelity.ts new file mode 100644 index 0000000..85c8e79 --- /dev/null +++ b/packages/c0py-core/src/verification/fidelity.ts @@ -0,0 +1,58 @@ +import type { FidelityVector } from "@siax/c0py-types"; + +export interface FidelityPolicy { + minimum: Partial>; + requireZeroRuntimeErrors?: boolean; + requireProductionBuild?: boolean; +} + +export interface FidelityGateResult { + passed: boolean; + failures: string[]; +} + +export const defaultClonePolicy: FidelityPolicy = { + minimum: { + routeCoverage: 1, + interactionCoverage: 1, + workflowCoverage: 1, + networkContractParity: 1, + responsiveCoverage: 1, + assets: 1, + accessibilityPass: true, + }, + requireZeroRuntimeErrors: true, + requireProductionBuild: true, +}; + +export function evaluateFidelity( + vector: FidelityVector, + policy: FidelityPolicy = defaultClonePolicy, +): FidelityGateResult { + const failures: string[] = []; + + for (const [dimension, requirement] of Object.entries(policy.minimum) as Array< + [keyof FidelityVector, number | boolean] + >) { + const actual = vector[dimension]; + + if (typeof requirement === "boolean") { + if (actual !== requirement) failures.push(`${dimension}: expected ${requirement}, got ${String(actual)}`); + continue; + } + + if (typeof actual !== "number" || actual < requirement) { + failures.push(`${dimension}: expected >= ${requirement}, got ${String(actual)}`); + } + } + + if (policy.requireZeroRuntimeErrors && vector.runtimeErrorCount !== 0) { + failures.push(`runtimeErrorCount: expected 0, got ${String(vector.runtimeErrorCount)}`); + } + + if (policy.requireProductionBuild && vector.productionBuildPass !== true) { + failures.push(`productionBuildPass: expected true, got ${String(vector.productionBuildPass)}`); + } + + return { passed: failures.length === 0, failures }; +} From cfa9a05ad8f63d1d10a32c409437f8c46aef4a78 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:38:19 +0200 Subject: [PATCH 16/18] feat(core): export reconstruction and fidelity contracts --- packages/c0py-core/src/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/c0py-core/src/index.ts b/packages/c0py-core/src/index.ts index a4651cf..73298ad 100644 --- a/packages/c0py-core/src/index.ts +++ b/packages/c0py-core/src/index.ts @@ -4,3 +4,5 @@ export * from "./registry/analyzer"; export * from "./crawler/types"; export * from "./registry/types"; export * from "./provenance/registry"; +export * from "./reconstruction/contracts"; +export * from "./verification/fidelity"; From e26398c49621c9ec9f00f27a82f1a6a774d26574 Mon Sep 17 00:00:00 2001 From: Simon Axelsson Date: Wed, 16 Sep 2026 15:38:28 +0200 Subject: [PATCH 17/18] test(core): add fidelity gate coverage --- packages/c0py-core/tests/fidelity.test.ts | 38 +++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 packages/c0py-core/tests/fidelity.test.ts diff --git a/packages/c0py-core/tests/fidelity.test.ts b/packages/c0py-core/tests/fidelity.test.ts new file mode 100644 index 0000000..a35db22 --- /dev/null +++ b/packages/c0py-core/tests/fidelity.test.ts @@ -0,0 +1,38 @@ +import { describe, expect, it } from "vitest"; +import { evaluateFidelity } from "../src/verification/fidelity"; + +describe("fidelity release gate", () => { + it("passes a complete clone vector", () => { + expect( + evaluateFidelity({ + assets: 1, + responsiveCoverage: 1, + routeCoverage: 1, + interactionCoverage: 1, + workflowCoverage: 1, + networkContractParity: 1, + accessibilityPass: true, + runtimeErrorCount: 0, + productionBuildPass: true, + }), + ).toEqual({ passed: true, failures: [] }); + }); + + it("fails rather than averaging away missing behavior", () => { + const result = evaluateFidelity({ + geometry: 0.999, + assets: 1, + responsiveCoverage: 1, + routeCoverage: 1, + interactionCoverage: 0.8, + workflowCoverage: 1, + networkContractParity: 1, + accessibilityPass: true, + runtimeErrorCount: 0, + productionBuildPass: true, + }); + + expect(result.passed).toBe(false); + expect(result.failures.join(" ")).toMatch(/interactionCoverage/); + }); +}); From 29ee39311d273c485e19974b6cf19156febbb66a Mon Sep 17 00:00:00 2001 From: Simon Date: Wed, 16 Sep 2026 21:54:22 +0200 Subject: [PATCH 18/18] chore(ci): remove broken Coolify auto-deploy (git-buildpack broken for monorepo, manual deploy per DEPLOY.md) --- .gitea/workflows/deploy.yml | 15 --------------- DEPLOY.md | 2 +- docs/PLATFORM.md | 6 +++--- 3 files changed, 4 insertions(+), 19 deletions(-) delete mode 100644 .gitea/workflows/deploy.yml diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml deleted file mode 100644 index f43506c..0000000 --- a/.gitea/workflows/deploy.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Deploy to Coolify -on: - push: - branches: [main] - workflow_dispatch: -jobs: - deploy: - runs-on: ubuntu-latest - steps: - - name: Trigger Coolify redeploy - env: - COOLIFY_TOKEN: ${{ secrets.COOLIFY_TOKEN }} - run: | - if [ -z "$COOLIFY_TOKEN" ]; then echo "::error::COOLIFY_TOKEN is not set"; exit 1; fi - curl -fsS -X POST "https://cloud.siax.io/api/v1/deploy?uuid=c0py&force=false" -H "Authorization: Bearer $COOLIFY_TOKEN" -o /dev/null -w 'coolify deploy HTTP %{http_code}\n' diff --git a/DEPLOY.md b/DEPLOY.md index 054bde2..f5a6727 100644 --- a/DEPLOY.md +++ b/DEPLOY.md @@ -3,7 +3,7 @@ ## SIAX Cloud Deploy - **Config**: [`siax.config.json`](siax.config.json) -- **CI/CD**: `.gitea/workflows/ci.yml` — körs vid push/PR till main (Gitea Actions, git.siax.io) +- **CI/CD**: `.gitea/workflows/ci.yml` — körs vid push/PR till main (Gitea Actions, git.siax.io). Deploy är **manuell** (se nedan) — CI triggar ej Coolify (git-buildpack trasig för detta monorepo, auto-deploy togs bort 2026-09-16). - **Runtime**: Node 22, port 3000 - **Domain**: `c0py-web.siax.io` (web) / `c0py-api.siax.io` (API) diff --git a/docs/PLATFORM.md b/docs/PLATFORM.md index 64a137c..63ec8ec 100644 --- a/docs/PLATFORM.md +++ b/docs/PLATFORM.md @@ -51,6 +51,6 @@ Skapa OIDC-app under projekt `c0py` (eller motsvarande). Client credentials flow 2. `pnpm run typecheck` 3. `pnpm run test` 4. `pnpm run build` -5. Pusha main → CI → Deploy via `.gitea/workflows/deploy.yml` -6. Verifiera `https://c0py.siax.io/health` → 200 OK -7. Verifiera fail-closed: `https://c0py.siax.io/v1/c0py/registries` → 401 utan token +5. Pusha main → CI (`ci.yml`); deploy sker manuellt enligt [`DEPLOY.md`](../DEPLOY.md) (Coolify git-buildpack är trasigt för detta monorepo — bygg `:latest` på server6 och kör `docker compose up -d` i appkatalogen) +6. Verifiera `https://c0py-api.siax.io/health` → 200 OK +7. Verifiera fail-closed: `https://c0py-api.siax.io/v1/c0py/registries` → 401 utan token