docs(architecture): ADR set for agent-driven Frigg development#592
Draft
seanspeaks wants to merge 12 commits into
Draft
docs(architecture): ADR set for agent-driven Frigg development#592seanspeaks wants to merge 12 commits into
seanspeaks wants to merge 12 commits into
Conversation
Defines a three-tier model for what's pluggable in Frigg, distinguishing Core Plugins (required infrastructure with defaults — provider, queue, encryption), Application Extensions (optional cross-cutting features on appDefinition.extensions), and Integration Extensions (off-the-shelf handler bundles on IntegrationBase.Definition.extensions). Grounds the model in existing prototypes: the packages/core/extensions system on claude/frigg-netlify-exploration-aY2Bh for Tier 2, and the this.extensions pattern in the frigg-2.0 downstream repos for Tier 3. Calls out current shape mismatches (array vs object, constructor vs static Definition, vocabulary collision) and proposes resolutions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Builds on the three-tier plugins/extensions taxonomy on adr/extensions. Adds two sibling concepts that surfaced in the integration-overhaul design conversation: Artifacts — code or configuration the API module helps the developer generate (often via a vendor CLI like `hs project add` or `slack scaffold`) that runs outside Frigg on the target platform. Deliberately not a fourth tier: the three tiers describe pluggable code inside the Frigg runtime; Artifacts run outside it. Required (`base`) or optional per artifact. Lives on `apiModule.Definition.artifacts`. API Module Capability Declaration — a structured `capabilities` block that answers "what can I do with this API module?" Each capability is backed by a spec (OpenAPI/AsyncAPI/Arazzo/Fenestra) and implementedBy one of three mechanisms: the API class (atomic ops), a Tier 3 Integration Extension (Frigg-side composition), or an Artifact (extra-Frigg code). JSON-Schema-validatable; mirrors Fenestra's modular schema conventions. Also: refreshed comparison table to include Artifacts as a fourth column, added Phases 5 and 6 (Capability Declaration schema, Artifacts tooling), added Open Questions 5-8 (binding validation, vendor CLIs, capability- type set boundaries, defaultConfig.json scope), and extended references with the spec families and the Fenestra draft location. No code changes; documentation only. Phase 1-4 from the original ADR remain unchanged.
References Daniel Klotz's PR #590 (Tier 3 framework implementation) as the in-flight realization of Phase 2. Closes gaps the prior revision flagged: - **Framework load mechanism** subsection under Tier 3 documents the actual two-seam split #590 implemented — boot-time route claiming in integration-defined-routers.js, per-instance event merging via IntegrationBase._mergeExtensions() called from initialize(). Quotes the resolution-priority cascade, fail-loud conflict policy, and the two newly-added instantiation hooks (loadRouterFromObject's per-request closure and createQueueWorker's dry-instance branch). - **Deferred from the initial implementation** subsection captures the three Phase-2 items #590 explicitly defers (per-class merge cache, worker-side getExtensionWorkers consumption, declarative route middleware seam) plus the pre-existing IntegrationBase DI gap that extensions now inherit. - **Beyond { routes, events, queues, workers } — extending the contract** subsection enumerates primitives not yet in the extension contract: crons/schedules, user actions, config options, dynamic options. Calls out crons and user actions as highest-leverage v1.1 adds. - **Core / API module boundary — worked example** subsection uses #590's findIntegrationByPortalId as a concrete teaching case for the platform-neutral-primitive-in-core vs platform-vocabulary-wrapper-in- extension rule. Cross-references the comment posted on #590 proposing the rename to findIntegrationByEntityExternalId. Also: extends Phase 2 to reference #590's actual scope, adds Phase 7 for v1.1 contract extensions, adds Open Questions 9-14 (merge cache, worker consumption, route middleware, IntegrationBase DI, contract extensions, boundary-as-guideline), updates References with a new "Framework implementation (in flight)" section pointing at #590. No code changes; documentation only.
Proposes an integration-level Capability Declaration on IntegrationBase.Definition.capabilities, extending the API-module-level pattern from ADR-EXTENSIONS to the integration class. Capabilities are descriptive (not generative), use the same backedBy + implementedBy vocabulary as ADR-EXTENSIONS, and resolve via prototype chain with inherits/override semantics. Key additions specific to the integration layer: - Primitive taxonomy (dataSync, workflow, userAction, configOption, lifecycleHook, webhookHandler, fenestraComponent, cron, aiInference, apiProxy, mcpTool) - `surface` field on implementedBy (default / vendor-webhook / vendor-frontend / admin / internal) with auth model + route shape per surface - Surface-selection rule: prefer default-surface primitives (getConfigOptions, USER_ACTION events, /api/v2/integrations) over declaring new routes; vendor-namespaced surfaces reserved for cases where the external system literally cannot reach default - Pointer discipline — declarations point at code by name, never claim behavior Includes a worked PipedriveIntegration example showing 8 current routes collapsing to 2 own capabilities + 11 inherited (5 from BaseCRMIntegration, 6 from IntegrationBase). Status: PROPOSED. Draft committed to preserve work-in-progress on the overhaul branch while adversarial review is in flight. Known issues being addressed in the next revision: - Static validation of `implementedBy.events` requires either a static EventDefinitions field or admission that the lint is dynamic (this.events is constructor-wired today) - `implementedBy.extensions` cross-reference needs to pin to local binding keys, not extension class names - Multi-`via` capabilities need per-field discrimination (artifact surface vs Frigg-side backend) - `surface: vendor-frontend` discriminator should likely reframe around credential carrier (Bearer / vendor-JWT / vendor-signature / none) rather than "where the UI runs" - Companion ADRs (ontology-layers, agent-harness, evals) not yet drafted Not yet ready for merge or PR to next. https://claude.ai/code/session_01Wbyh477BTZHfMLQMzASnuc
…rial review Four parallel reviewers (architectural coherence, Frigg API alignment, agent-eval value, migration & drift) surfaced enough factual and design errors that the draft needed a substantial rewrite. Major corrections: - Replace single `consumedBy` with `surface` + `auth` split. Surface describes where the endpoint is mounted (default, vendor-webhook, vendor-namespaced, admin, internal, mcp); auth describes which credential carriers it accepts (bearer, adopter-jwt, shared-secret, admin-key, vendor-signature, vendor-jwt, none). The earlier single-dimension framing collapsed surface and auth and led to the hand-wavy "vendor-frontend" enum value (now dropped). - Fix all `/api/v2/...` references to actual current v1 paths. ADR-006 marks Phase 1-4 as accepted but no v2 router exists in the current checkout. Worked examples now cite the real v1 endpoints (`PATCH /api/integrations/:integrationId`, `/api/integrations/:id /actions/:actionId`, etc.). - Replace references to `loadUser` / `requireLoggedInUser` / `requireAdmin` middleware. Those files live on `feature/integration-router-v2-drop-modules-router`, not on this branch. Actual current code uses inline `authenticateUser.execute()` inside handlers (packages/core/user/use-cases/authenticate-user.js :49-99), supporting four user-context auth methods, not one. - Rebuild the Pipedrive worked example from the actual current four-route state (not the eight-route fiction from stale search results). Only `/uninstall` survives as a route after the cleanup per the May 25 #dev-feed thread; `callActivityDestination` and the admin script ride default-surface primitives with no new routes. Three own capabilities total; one route remaining. - Split Phase 2 into Phase 2 (framework-only, IntegrationBase declaration) and Phase 2.5 (adopter base classes such as BaseCRMIntegration and BaseOutboundIntegration, which live in adopter repos and are not framework deliverables). - Address the static-check viability gap. `this.events` is wired in constructors, so `validateCapabilityImplementation` cannot be purely static today. Propose a `static EventDefinitions` convention as a paired framework change; mark as Open Question 1. - Pin `implementedBy.extensions` cross-references to binding keys (the locally-unique identifier in Definition.extensions), resolving the ambiguity flagged in architectural review. - Drop multi-`via` as the default pattern. A capability with both Artifact and Frigg-side handler splits into sibling capabilities. Multi-via is now Open Question 4. - Constrain `description` to purpose-not-behavior. Every worked- example description rewritten. Behavior claims are forbidden in the Definition — that's the pointer discipline. - Add `extend` (array append) and `disinherit` to inheritance semantics. The earlier shape only supported `override` (shallow replace), which the architectural reviewer flagged as forcing authors to redeclare unchanged sibling fields when they only meant to add. - Gate Phase 2 on PR #590 merged + one prerelease cycle stable. Gate Phase 5 on eval falsification criteria from ADR-EVALS (capability-only condition <8pp lift at Sonnet OR Haiku <70% at all-three-enabled triggers reconsideration). - Add Revision history section documenting what changed and why, with provenance back to the four review findings. Open Questions 5, 6, 9, 10 added; 1-4 and 7-8 updated to reflect the corrected design. The shape of the design (capability array, primitive + backedBy + implementedBy, pointer discipline, inheritance via prototype chain) survives. The factual layer that referenced auth middleware, v2 paths, and an eight-route Pipedrive was wrong; this revision corrects it. Not yet PR-ready. Three companion ADRs (ontology, harness, evals) remain to draft.
Companion to ADR-INTEGRATION-CAPABILITIES. Defines the four-layer ontology model (L1 universal non-obvious / L2 Frigg-context reading discipline / L3 vendor and domain / L4 live-read instance) and the in-house Node compiler that renders task-scoped subsets into XML-tagged context blocks. Key design decisions captured: - Layer model stratifies by scope-of-applicability, not subject matter. More-specific layers override less-specific; locked constraints accumulate and survive overrides. - Authoring discipline: imperative-verb constraints; pointer-only references to live code via retrieve_from; no behavioral facts about code in the ontology (behavior is the property of code, surfaced live). - Node-based compiler shipped as @friggframework/ontology from the same monorepo. ~300 LOC core. CLI plus SDK. git+https URLs for remote ontology roots with version pinning at task start. - Session protocol: pin ontology version at task start, never refresh mid-task. Refresh happens at task boundaries. Patch/minor bumps auto-adopt; major bumps (locked-rule changes) surface for review via ontology diff. - Composition with ADR-INTEGRATION-CAPABILITIES is explicit and non-overlapping: capabilities answer what an integration DOES; ontology layers answer what an agent NEEDS TO KNOW to work on it. L4 entries are mostly pointers to capability declarations; the ontology teaches the agent how to find them, not what they say. - L2 captures the surface-selection rule that surfaced in the May 24-25 dev-feed thread on Pipedrive routes. That rule was previously implicit institutional knowledge with no home. - Adopter-portable: framework ships L1 + L2; adopter repos extend with L3 (vendor backstory) and L4 (instance pointers). Phases land sequentially: schema + validator -> compiler -> drift tooling -> seed framework L1+L2 -> adopter L3 -> harness wiring (ADR-AGENT-HARNESS) -> eval measurement (ADR-EVALS). Eight open questions captured; falsification criteria deferred to ADR-EVALS. Not yet PR-ready. ADR-AGENT-HARNESS and ADR-EVALS remain to draft; fourth adversarial reviewer (agent-eval value) still in flight.
Wires ADR-INTEGRATION-CAPABILITIES and ADR-ONTOLOGY-LAYERS into a Claude Code SessionStart hook plus an MCP server fallback. The harness has three responsibilities: 1. Session-start injection. Reads the repo's harness config, runs resolveCapabilities(IntegrationClass) and compileContext(), and emits a single <FRIGG-HARNESS-CONTEXT> block with <ONTOLOGY> and <CAPABILITIES> sub-blocks for Claude Code to prepend as a system- prompt overlay. 2. Task pinning. First run for a new task writes .frigg-harness/ state.json with the resolved ontology version + capability class hash + compiled block hash. Subsequent runs (including subagent invocations) reuse the pinned state. Mid-task drift is impossible by construction; default hash-mismatch policy is warn-and-recompile with stricter / laxer modes available. 3. Subagent propagation. spawnSubagentPrompt() helper templates the parent's pinned context into child prompts. A phase-executor subagent inherits the orchestrator's pinned ontology and capability versions; it never re-pins. Optional fourth responsibility: MCP server fallback exposing the same content via mcp__frigg-harness__get_capabilities(), get_ontology(), pin_task(), resolve_pointer() tool calls. Same content, pull-based instead of push-based, for agents outside Claude Code's SessionStart-hook contract. Active-integration detection is heuristic (auto-from-branch, auto- from-cwd, explicit override). Failure modes default to graceful degradation: missing config, unreachable ontology root, broken capability declaration all warn-and-proceed rather than block. The exception is locked-content budget overflow, which is a hard error because locked constraints cannot be elided. Two transports (SessionStart push vs MCP pull) ship together. The eval (ADR-EVALS) measures which produces better task accuracy at each model capability tier. The harness on/off is one of three independent variables in the eight-condition matrix. Phases land sequentially: package skeleton -> SessionStart hook -> task pinning -> subagent propagation -> MCP fallback -> failure-mode tests -> eval integration. Gates: Phase 2 of this ADR depends on the resolver from ADR-INTEGRATION-CAPABILITIES and the compiler from ADR-ONTOLOGY-LAYERS both shipping first. Eight open questions captured; relationship to the eval ADR's falsification criteria is forward-referenced. Not yet PR-ready. ADR-EVALS remains to draft; fourth adversarial reviewer (agent-eval value) still in flight.
Completes the four-ADR set. Defines the eight-condition factorial matrix that tests the three independent variables (capability declaration, ontology layers, agent harness) against a five-model ladder spanning Haiku-class through Opus-class plus cross-vendor and open-weights. Falsifiable hypothesis with six explicit criteria gating Phase 5 of ADR-INTEGRATION-CAPABILITIES (rolling migration of remaining integrations across adopter repos): 1. All-three at Haiku >=80% composite (weak-model promise) 2. Capability-only at Sonnet >=15pp lift over baseline 3. Ontology-only at Sonnet >=10pp lift over baseline 4. Harness-only at Sonnet >=10pp lift over baseline 5. Combined-effects monotonicity (no variable degrades score) 6. Locked-constraint adherence >=95% under prompt pressure Missed criteria 1-4 by >5pp = pause rolling migration; missed criteria 5-6 at all = stop and reconsider design. The shape of the design survives single missed thresholds (tuning available); deeper failures invalidate the value claim. Ten-task seed mixing three categories: - 5 generic tasks against synthetic fixture integrations - 3 real-bug-derived tasks (incl. the Pipedrive /settings smell from the May 24-25 dev-feed thread) - 2 adversarial locked-constraint pressure tests Tasks are scored on four independent dimensions (correctness, locality, constraint adherence, cost) and combined via weighted composite. Per-task weight override available for adversarial tasks where constraint adherence should dominate. Build on promptfoo (Node-native, MIT, mature) with a custom provider for the Frigg-agent-in-sandbox loop. ~1500 LOC total including tests, scorers, fixtures, custom provider. Three-layer ownership: - @friggframework/evals: scorers + fixture integrations + generic tasks; published from the Frigg monorepo - lefthookhq/quo--frigg/evals/ (and other adopters): real- integration tasks, importing scorers from the framework package - Framework eval numbers are load-bearing for generality claims; adopter numbers are illustrative real-world demonstration Cadence: - Every PR: smoke test only (parse, validate, compile - no model calls; ~free, fast) - On-demand: workflow_dispatch with --models, --tasks, --conditions knobs; ~$10-50 typical iteration - Canonical at milestones: full 8x5x10 = 400 runs; $50-150 per canonical; committed to evals/results/ and inserted into this ADR's Canonical Results section - Local dev: single-cell runs <$1 Rejected alternatives: - Python-based Inspect AI: cross-language toolchain tax - Adopter-only evals: can't make generality claims from one adopter's biased data - Skip eval, ship on intuition: how the original integration-definition.schema.json shipped with zero adopters - Eval on every PR: cost and latency untenable Ten open questions captured, including task-set evolution, model-version drift, scorer weight tunability, agent-loop architecture (single-loop vs multi-agent simulation), per-condition baseline (with vs without existing CLAUDE.md), and statistical methodology (effect size + significance, not just p-values). Canonical results section is templated; populated after first run following ADR-INTEGRATION-CAPABILITIES Phase 4. None of the four ADRs land on `next` until the canonical run exists. Not yet PR-ready. Fourth adversarial reviewer (agent-eval value) remains in flight; if/when it returns its findings inform a follow-up revision to this ADR specifically.
- Scrub client-specific (Quo) and private-repo references; generalize vendor examples to HubSpot / Pipedrive / Salesforce / Slack. - Add Module-exported ontology: api modules ship their own vendor L3 fragments; integration projects compose from installed modules. - Add Source adapters: compiler converts md / gdoc / notion / github / live sources to canonical records on the fly; distinguish source (authoring-time) from retrieve_from (runtime). - Add Validation subagent pattern: recommended pass that spawns a subagent with the same compiled block to review parent agent output. - Add Friction capture and ontology evolution: feedback loop that captures ambiguity / gaps / conflicts surfaced by agents and the validation subagent; backlog becomes the maintenance trigger. - Reframe Phase 5 around module-exported ontology; add Phase 6 (source adapters), Phase 8 (friction tooling), renumber accordingly. - Update Negative consequences to reference friction loop as the named defense against the "seed commits, ongoing edits stall" pattern. - Add open questions on friction-tool naming and module-ontology rollout.
ADR-AGENT-HARNESS:
- Add Lifecycle taxonomy subsection mapping the 9-phase agent lifecycle
(Freya ADR-008) onto Frigg touchpoints; clarify Frigg implements only
the two phases Claude Code's hook surface exposes (SessionStart for
parent pre_turn, SubagentStart for subagent pre_turn) and uses port
decorators or skill conventions for the rest.
- Add decorator-vs-hook framing (decorators wrap ports for structural
concerns; hooks punctuate the lifecycle for cross-cutting concerns).
- Add Shared friction pipeline subsection noting the @freyaframework/
friction package as a co-owned dependency.
ADR-ONTOLOGY-LAYERS:
- Revise Validation subagent pattern to use Freya's discriminated-union
return shape: {valid | fixable, correctionPrompt | friction, events}.
FRICTION classification emits events into the shared pipeline.
- Replace abstract friction-tooling section with explicit borrow from
Freya ADR-009 as @freyaframework/friction shared package. Itemize the
v1 consumed surface (typed FrictionEvent with 6 starting signals,
OntologyVcsPort + GitHubOntologyVcsAdapter, discriminated-union
validation, threshold+corroboration+decay) and the v1 deferred surface
(MigrationPlan, persisted FrictionCluster, confidence float, scheduled
aggregator, multiple separate detection hooks, eight domain events).
- Lift the five non-negotiable guardrails verbatim (harness-side-only
detection, human-approve-only, decay, rejection cooldown, cross-tenant
isolation).
- Add positioning: bottom-up schema synthesis as the structural inverse
of Hermes-style procedure synthesis.
- Update Open Q9 from "tool TBD" to "shared package decided; confirm
trimmed v1 surface with Freya ADR-009 roadmap."
…ion package - Generalize lefthookhq/quo--frigg and other client-repo references in ADR-INTEGRATION-CAPABILITIES, ADR-AGENT-HARNESS, and ADR-EVALS to "adopter repo / canary adopter project / participating adopter projects". The Frigg framework's ADRs are public; private client work doesn't belong inline. Vendor names (HubSpot, Pipedrive, Salesforce, Slack) preserved as examples since they're shipping api modules. - Rename transformPersonToQuo example to transformPersonToDestination. - Rename the second module in the worked example from "quo" to "destination" to preserve the renaming idiom without naming a client. - Add cross-link from ADR-EVALS to ADR-ONTOLOGY-LAYERS friction subsection, noting eval miss-cases feed the shared @freyaframework/friction package as FrictionEvents.
Tier 3 Integration Extensions is now Implemented (PR #590 + PR #596). Updates the ADR to reflect what actually shipped, while keeping Tier 1 (Core Plugins), Tier 2 (Application Extensions), Artifacts, and the Capability Declaration as Proposed. - Top-level Status: mixed; per-tier status spelled out - Tier 3 section: explicit Implemented marker linking #590 + #596 + EXTENSIONS.md; quick-start in code is now authoritative for shape - Extension contract example: useDatabase: false default added; route path updated to reflect binding-key namespacing - Framework load mechanism: rewritten to document the URL pattern /api/{integration}-integration/{bindingKey}{route.path}, dedicated per-binding Lambda handlers, useDatabase resolution order (binding ?? extension ?? false), false-default scope (extension routes only — createHandler legacy paths still default true) - Event vs route namespacing: clarified — routes are namespaced (since #596), events are not; same-event-name across bindings still throws; binding the same extension twice requires disjoint event sets - Fail-loud defaults: amended with the useDatabase boolean validation and the new "two routes with same method+path within a single binding" framing - Breaking change flagged for adopters: old un-namespaced webhook URLs must be re-pointed; HubSpot v3-style URL-signing schemes fail signature verification until updated
|
d-klotz
reviewed
Jun 8, 2026
| Add a `capabilities` array to `IntegrationBase.Definition` (and to subclass Definitions). Each entry declares: | ||
|
|
||
| - **`name`** — stable identifier for the capability, dot-namespaced by scope (`crm.initialContactSync`, `pipedrive.appUninstall`) | ||
| - **`primitive`** — taxonomy slot (see [Primitive taxonomy](#primitive-taxonomy)) |
Contributor
There was a problem hiding this comment.
There's no reference to primitive-taxonomy, please explain.
d-klotz
reviewed
Jun 8, 2026
|
|
||
| backedBy: { | ||
| spec: 'arazzo', | ||
| ref: '@friggframework/specs/crm/initial-contact-sync.arazzo.yaml', |
Contributor
There was a problem hiding this comment.
how would that yaml file look like?
d-klotz
reviewed
Jun 8, 2026
| }, | ||
| }, | ||
| { | ||
| name: 'pipedrive.adminScript', |
Contributor
There was a problem hiding this comment.
where does this name come from? Does the user define this?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Adds five cross-referenced ADRs proposing the architecture for agent-driven Frigg integration work. Each is dependent on the prior; intended to land together as one decision unit. Implementation is intentionally not in this PR — these are decision artifacts.
Four are forward-looking proposals. One — ADR-EXTENSIONS — has had its Tier 3 section reconciled to ratify what Daniel already shipped on
nextin PR #590 + PR #596; the other tiers in that ADR remain proposed.static Definition.capabilitiesdeclaration on integration classes with pointer discipline (capability surface, primitive, backedBy, implementedBy). Replaces ad-hoc "what does this integration do" knowledge with a typed graph.@friggframework/ontologyinto XML-tagged context blocks. Includes module-exported ontology (each api module ships its own L3 fragment), multi-source compilation, validation subagent pattern, and the friction-capture loop adopted from Freya as a shared@freyaframework/frictionpackage.@friggframework/harnesspackage wiring the capability resolver + ontology compiler into Claude Code's SessionStart and SubagentStart hooks. Lifecycle taxonomy borrowed from Freya ADR-008 maps Frigg's touchpoints onto the 9-phase agent lifecycle; decorator-vs-hook framing for separating port-wrapping concerns from loop-punctuating concerns.useDatabaseresolution, fail-loud defaults). Tier 1, Tier 2, Artifacts, and the Capability Declaration remain Proposed. Quick-start for shipped Tier 3 lives atpackages/core/integrations/EXTENSIONS.md.lefthookhq/lefthook--dev-toolkit:evals/PLAN.md— three-arm ablation (Raw / Skill / Skill+Ontology+Validation+Friction) × two pilot tasks (one sync, one non-sync) × three replications, with hypothesis section and per-arm score predictions.Test plan
/api/{integration}-integration/{bindingKey}{route.path},useDatabaseresolution order, event-vs-route namespacing asymmetry, fail-loud defaults including the boolean-validation throw added in feat(core,devtools): namespace extension routes + useDatabase flag #596@freyaframework/frictionpackage will actually shipOpen follow-ups not covered here
@freyaframework/frictionshared package — confirm trimmed v1 surface with Freya ADR-009 roadmap (cross-framework alignment, not Frigg-internal)nextonce their Proposed sections settlelefthookhq/lefthook--dev-toolkitonce these decisions settle (skill copy + judge calibration + 18 runs)Notes
release/prereleaselabels — this PR ships only docs. Add labels when promoting beyond ADR proposal stage.Generated by Claude Code