Skip to content

feat(agent): add default-off profile record producer and provider - #2150

Merged
Jurij89 merged 26 commits into
integration/2052-system-record-syncfrom
feat/2052-agent-profile-provider
Aug 8, 2026
Merged

feat(agent): add default-off profile record producer and provider#2150
Jurij89 merged 26 commits into
integration/2052-system-record-syncfrom
feat/2052-agent-profile-provider

Conversation

@Jurij89

@Jurij89 Jurij89 commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Prepare each agent profile once through an explicit canonical signed-profile fact model, then independently render immutable graphful publication and graphless signed-projection snapshots with a single timestamp; future legacy-only output belongs explicitly in the publication renderer and cannot enter the signed projection through graph stripping. This PR does not intercept or activate the existing profile publication path.
  • Add a default-off agent-profile record producer that fences one immutable profile, snapshots an independently verified confirmed graph-scoped publication binding before any asynchronous work, pins its UAL/chain/KAv10 deployment to the local lane, validates the exact canonical projection and identity, atomically reserves the expected store snapshot, installs materialized state, and advertises the new root last.
  • Add a bounded exact-object provider with one nonqueued stream permit, lifecycle-supplied frame admission, request-driven rate limiting, a three-second exchange deadline, response integrity checks, and deterministic resource release.
  • Harden the dormant composition surface: share the full profile RDF schema and canonical identity-fact contract between producer and materializer; bind verified projection identity facts to the authenticated signed head; reject malformed object terms, duplicate or conflicting identity triples, invalid timestamps/scalars, heads issued before their assertion finalized, future-dated heads, and already-expired local publication bindings against an independent verifier clock; serialize competing store writers, preserve verified authority-transition lineage across later heartbeats, isolate store snapshots, retain branded canonical signer addresses, separate producer-write and semantic provider-read contracts, preserve inventory root/path semantics across concurrent updates, and count every retained cache object.
  • Keep the stack default-off. It registers no protocol, requester, timer, lifecycle opener, or production cache. A later activation PR must own publication finality, construct the confirmed graph-scoped binding, and supply durable storage.

Related

Diagrams

Profile preparation

Before:

sequenceDiagram
    participant Lifecycle
    participant ProfileManager
    participant ProfileBuilder
    participant Publisher
    Lifecycle->>ProfileManager: publishProfile(config)
    ProfileManager->>ProfileBuilder: build profile RDF
    ProfileBuilder-->>ProfileManager: mutable result with separate clock reads
    ProfileManager->>Publisher: publish or update RDF
    Publisher-->>Lifecycle: PublishResult
Loading

After:

sequenceDiagram
    participant Lifecycle
    participant ProfileManager
    participant ProfileBuilder
    participant Publisher
    Lifecycle->>ProfileManager: publishProfile(config)
    ProfileManager->>ProfileBuilder: prepare exact profile once
    ProfileBuilder-->>ProfileManager: graphful publication and graphless projection snapshots
    ProfileManager->>Publisher: publish or update cloned exact RDF
    Publisher-->>Lifecycle: PublishResult
    Note over Lifecycle,Publisher: No system-record producer is activated here
Loading

Dormant producer composition API

Before:

sequenceDiagram
    participant Integrator
    participant Producer
    participant Materializer
    participant ProviderStore
    Integrator->>Producer: No profile-record producer available
    Note over Integrator,ProviderStore: No signed per-profile record can be composed
Loading

After:

sequenceDiagram
    participant Integrator
    participant Producer
    participant Materializer
    participant ProviderStore
    Integrator->>Producer: prepare(exact immutable profile)
    Producer->>Materializer: fence candidate
    Integrator->>Producer: complete(verified confirmed binding)
    Producer->>Producer: validate projection, seal, identity, timestamps, and caps
    Producer->>ProviderStore: reserve expected head and root snapshot
    Producer->>Materializer: install verified projection and head
    Producer->>ProviderStore: commit artifacts and advertise root last
    Producer-->>Integrator: signed publication artifacts
    Note over Integrator,ProviderStore: Callable foundation only; no production lifecycle wiring in this PR
Loading

Exact-object provider exchange

Before:

sequenceDiagram
    participant Peer
    participant Node
    participant Store
    Peer->>Node: System-record exact request
    Note over Peer,Store: No agents system-record provider exists
Loading

After:

sequenceDiagram
    participant Peer
    participant Provider
    participant Admission
    participant Store
    Peer->>Provider: Header-only exact request
    Provider->>Admission: Take request token and one stream permit
    Provider->>Admission: Reserve maximum legal response frame
    Provider->>Store: Resolve exact digest
    Store-->>Provider: Canonical bytes
    Provider->>Provider: Verify encoded response and charge exact bytes
    Provider-->>Peer: One bounded frame
    Provider->>Admission: Release frame and stream permit
    Note over Peer,Store: No queue, refill timer, or per-peer state
Loading

Files changed

File What
packages/agent/src/profile.ts Adds one canonical signed-profile fact list plus one-clock immutable preparation with independently rendered graphful publication and graphless signed-projection views, using core-owned canonical identity facts.
packages/agent/src/profile-manager.ts Publishes one prepared RDF snapshot, preserves the legacy path, and correctly treats KA ID zero as an existing profile.
packages/core/src/agent-profile-projection-schema-v1.ts Owns the frozen profile RDF schema, canonical identity facts, and signed-head identity binding shared by authors and verified materializers.
packages/core/src/system-record-v1.ts Re-exports the focused profile-schema contract from the dormant protocol entrypoint.
packages/storage/src/system-record-verified-replacement-v1-internal.ts Reuses the core schema validator and rejects projection identity facts that differ from the authenticated signed head before issuing materialization authority.
packages/storage/test/helpers/system-record-active-replacement-fixture.ts Keeps authentic replacement fixtures aligned with the required signed identity projection.
packages/storage/test/helpers/agent-profile-identity-projection-v1.ts Centralizes authenticated-head identity rows shared by storage test fixtures.
packages/storage/test/system-record-atomic-apply-executor-v1.test.ts Preserves derived-subject and exact-apply coverage with authenticated identity facts present.
packages/storage/test/system-record-next-state-v1.test.ts Preserves rotation, capacity, and 10,000-quad boundary coverage under the identity-bound projection contract.
packages/storage/test/system-record-verified-replacement-v1.test.ts Proves valid signed replacements remain accepted and fully re-signed projections with foreign peer, key, or wallet identity facts are rejected.
packages/agent/src/evm-message-signer-v1.ts Centralizes EIP-191 signing behind explicit custodial, chain-addressed, or chain-default modes, preserves the canonical address type, and verifies the recovered signer.
packages/agent/src/dkg-agent-rfc64-catalog-auto-publish.ts Selects the shared signer mode explicitly for existing RFC64 catalog authorship.
packages/agent/src/rfc64/recoverable-author-attestation-v1.ts Makes graph-scoped author-attestation recovery reusable by the profile producer.
packages/agent/src/system-records/artifact-v1.ts Defines the neutral content-addressed artifact and semantic repository contract shared by producers, stores, and providers, including exact inventory root/path lookups.
packages/agent/src/system-records/agent-profile-producer-v1.ts Implements strict preflight validation using shared profile/schema facts, an untrusted publication-result boundary narrowed to an immutable confirmed snapshot, independent-clock, assertion-finalization ordering, and live-validity verification, the fenced publication lease, signed head, copy-on-write inventory, expected-snapshot commit preconditions, post-install commit semantics that prevent materialized/advertised divergence, a typed publication artifact set, retained authority-history verification, and a separated write-store contract.
packages/agent/src/system-records/in-memory-agent-profile-publication-store-v1.ts Provides a bounded test/composition adapter that atomically reserves expected store state, consumes named publication artifacts, returns isolated snapshots, and retains content-addressed authority and advertised inventory-root history under the existing caps.
packages/agent/src/system-records/provider-v1.ts Implements bounded exact-object response serving through one reservation-owning send path, translates wire requests into neutral semantic lookups, and preserves exact inventory root/path coordinates.
packages/agent/src/system-records/transport-v1.ts Implements the nonqueued permit and request-driven dual token bucket.
packages/agent/test/profile-preparation-v1.test.ts Covers one-clock preparation, canonical fact parity between the graphful legacy publication and graphless signed projection for a representative profile, exact cloned publish bytes, and zero-valued KA identity.
packages/agent/test/evm-message-signer-v1.test.ts Covers custodial, addressed-chain, and default-chain signing, exact chain-as address selection, wrong-author refusal, and rejection when a chain signer returns another wallet's signature.
packages/agent/test/system-record-agent-profile-producer-v1.test.ts Covers ordering, duplicate, full RDF schema, realistic skills/offerings/hosting projection, signature rollback, and scalar preflight, every publication-binding predicate and publication lane, immutable binding under asynchronous caller mutation, identity/authority binding, post-transition heartbeats, signed tombstone refusal, servability of every committed artifact class and a prior advertised root after rollover, malformed stored heads, defensive prepared-profile snapshots, store snapshot isolation, stale inventory-root refusal, timestamp normalization/skew/finalization ordering, oversized bundles, concurrency, cache caps, prepared and completing abort/retry, rejected-fence cleanup/retry, post-install late-abort convergence, and seal binding under a deterministic verifier clock.
packages/agent/test/support/agent-profile-producer-v1-fixture.ts Holds reusable profile signing, publication, transition, deterministic-clock producer construction, and store-observation fixtures outside the behavior suite; publication seals are derived from the graph-stripped legacy publication view so renderer divergence fails producer tests.
packages/agent/test/system-record-provider-v1.test.ts Covers all exact-object routes, exact bundle/control repository lookup translation, repository misses/exceptions, unsupported request and cached-root networks, schema-invalid canonical frames before admission, ordinary-object and root-descriptor corruption proof, admission/rate limits, byte charging, busy/reset/deadline/shutdown/write-failure paths, and leak cleanup.

Test plan

  • pnpm --filter @origintrail-official/dkg-agent build
  • pnpm --filter @origintrail-official/dkg-core build && pnpm --filter @origintrail-official/dkg-storage build
  • pnpm --filter @origintrail-official/dkg-core exec vitest run test/system-record-objects-v1.test.ts (31 passed, 1 skipped)
  • pnpm --filter @origintrail-official/dkg-storage exec vitest run test/system-record-verified-replacement-v1.test.ts test/system-record-atomic-apply-executor-v1.test.ts test/system-record-next-state-v1.test.ts test/system-record-apply-command-v1.test.ts (66 passed)
  • pnpm --filter @origintrail-official/dkg-agent exec vitest run test/system-record-agent-profile-producer-v1.test.ts test/system-record-provider-v1.test.ts test/profile-preparation-v1.test.ts test/evm-message-signer-v1.test.ts test/agent-rotate-encryption-key.test.ts test/encryption-key-rdf-recovery.test.ts test/swm-publish-profile-mutex.test.ts test/profile-manager-meta-skip.test.ts test/rfc64-dkg-agent-native-wiring.integration.test.ts (143 passed)
  • Maximum legal profile-bundle response remains within SYSTEM_RECORD_MAX_FRAME_BYTES.
  • Provider active streams peak at one, queued work stays zero, and frame/byte reservations return to zero on timeout and shutdown.
  • Duplicate profile triples, invalid scalar fields, identity/lane mismatches, expired bindings, and cache-cap overflow fail before state commit.
  • git diff --check
  • Confirm the outbound diff contains no ignored/local files, generated deployment state, or secrets.
  • Decompose the producer object-construction pipeline into smaller pure stage helpers before activation; this is maintainability work and does not change this default-off contract.
  • Consolidate profile fact authoring and the declarative V1 vocabulary/type tables behind one core specification before activation; current author output is fail-closed through the shared schema validator.
  • Split the 1,521-line producer behavior suite into concern-focused files before adding activation coverage; reusable fixture mechanics already live under test/support.
  • Add a multi-level inventory fixture that proves successful non-empty path traversal before provider activation; current coverage proves root lookup plus wrong-path rejection.
  • Split provider exchange policy and response planning into smaller pure stages before activation; current default-off outcomes and accounting are fully covered.
  • Durable provider storage, a lifecycle owner for confirmed publication binding, protocol registration, restart recovery, and feature flags remain required before enabling this path.

Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts
* runtime is created here; lifecycle supplies the B4 fence/install closures.
*/
export function createAgentProfileProducerV1(
options: CreateAgentProfileProducerOptionsV1,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Split the producer’s monolithic publication pipeline before it becomes the canonical shape

What's wrong
This new producer puts too many protocol concepts into one closure. That makes the lifecycle state (active, abort controller, commit lease) interleaved with deterministic object construction, which will be hard to extend for tombstones, authority transitions, or durable stores without adding more branches to the same busy path.

Example
A reader trying to change only inventory behavior has to understand projection validation, EVM/peer signing, bundle limits, install ordering, and commit lease cleanup in the same function body.

Suggested direction
Make the producer read as a small orchestration pipeline over named immutable values. The code-judo move is to move protocol-object construction and inventory/store mutation into separate pure helpers so the lease lifecycle is the only stateful code left in createAgentProfileProducerV1.

For Agents
In packages/agent/src/system-records/agent-profile-producer-v1.ts, preserve the existing prepare/complete behavior but split completePrepared into explicit stages such as validatePublicationBinding, buildProfileRecordObjects, buildSignedHeadEnvelope, buildInventoryCommit, and commitPreparedPublication. Keep the tests proving successful publish, update, abort, and capacity failure passing after the decomposition.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: The profile producer is carrying too many responsibilities in one orchestration function

What's wrong
The new producer concentrates several independent concepts in one long closure and one file. That makes the implementation hard to scan and raises the cost of future authority-transition or fork-resolution work because new branches will naturally be bolted into the same flow.

Example
To understand one ordinary profile heartbeat, a reader must follow snapshot validation, seal checks, owned-subject derivation, bundle encoding, head signing, inventory COW updates, root signing, verification-closure materialization, install ordering, commit leasing, and cache accounting in one module.

Suggested direction
Use a smaller orchestration shell that calls named pure phases such as validatePublicationBinding, buildProfileRecordArtifacts, advanceInventoryRoot, and commitInstalledProfileRecord. Move createInMemoryAgentProfilePublicationStoreV1 out of the producer file so repository concerns do not live beside record-authoring logic.

For Agents
Split agent-profile-producer-v1.ts by responsibility while preserving behavior: extract pure builders for projection/seal/head/artifacts, an inventory-advance helper, and move the in-memory publication store into its own repository module. Tests should still prove initial publish, heartbeat update, failed install rollback, and provider resolution.

@Jurij89 Jurij89 Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid maintainability finding. I reduced the immediate conceptual load by moving the store adapter out and replacing loose lifecycle hooks with a typed transaction, but I am intentionally deferring the larger no-behavior-change decomposition to a follow-up before activation. It is now an explicit unchecked PR item under #2052; mixing that broad rewrite into this correctness push would enlarge review risk without changing the default-off contract.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still valid and intentionally open. bcd7a4f removed the unrelated ProfileManager coordinator and split the store contracts, but the pure-stage decomposition remains an explicit pre-activation follow-up in the PR checklist. This PR stays default-off, so the refactor can land before any runtime caller relies on the orchestration shape.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The deferred producer decomposition is now durably tracked in #2156 with explicit pre-activation acceptance criteria.

Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts
}

/**
* Author one local profile record. No protocol, timer, queue, or independent

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Avoid landing a production subsystem that is only reachable from tests

What's wrong
This adds a substantial new subsystem to production source without a production entrypoint. That is codebase-health debt because future readers have to maintain, review, and reason about APIs whose lifecycle and ownership are not established by the production code graph.

Example
The PR adds production modules under src/system-records, but a maintainer cannot tell from the production graph when these components are supposed to run, which lifecycle owns them, or whether the hook API is the intended integration point.

Suggested direction
Make the ownership boundary explicit now: integrate the system-record components into the agent lifecycle, or stage them as non-production/test support. That will keep the source tree from accumulating large, unowned protocol implementations whose real runtime contract is unclear.

Confidence note
This is based on current source references: the new system-record producer/provider are referenced by tests but not wired into the production agent lifecycle in the changed branch.

For Agents
Either wire createAgentProfileProducerV1 / createSystemRecordProviderV1 into the production lifecycle in this PR, or keep the new implementation outside production src until the lifecycle integration lands. If hooks are the intended path, pass a concrete typed coordinator from the agent construction site and make that ownership visible in production code.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Do not land this much production surface without a runtime owner

What's wrong
This diff introduces a sizeable production subsystem that is only exercised by tests. That is a code-health problem even if the individual pieces work: the API shapes, lifecycle hooks, and storage boundaries can drift before any production caller proves they are the right abstractions.

Example
A future reader sees a 673-line producer, a provider, a transport limiter, and ProfileManager hooks, but there is no lifecycle composition showing which store, fence, install, and provider objects are the canonical runtime path. That leaves the design effectively documented by tests rather than by production ownership.

Suggested direction
Make the integration boundary explicit in this PR: a single lifecycle-owned coordinator should compose profile preparation, legacy publication, producer completion, store, and provider registration. If the integration is intentionally deferred, keep these modules as test/internal scaffolding rather than exported production-shaped APIs.

Confidence note
Assumes the supplied diff is complete; repository search found no production references to the new system-record producer/provider factories.

For Agents
Look at packages/agent/src/system-records/*, packages/agent/src/profile-manager.ts, and the agent lifecycle construction. Either wire the system-record pipeline through the real lifecycle behind one narrow coordinator or keep this code out of production until that owner exists. Preserve existing profile publish/update behavior; add a small production-composition smoke test or remove the unowned surface.

@Jurij89 Jurij89 Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated and intentionally deferred to the later lifecycle composition stack. This PR is chained into the integration branch and remains default-off: it registers no protocol, opener, timer, or production cache. Wiring it now would activate an incomplete path before the durable store and storage-owned authenticated issuer exist. The PR summary, diagram, and checklist now make that ownership boundary and the #2052 follow-up explicit.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still intentionally open for the activation PR. bcd7a4f removes the misleading ProfileManager integration seam, and the PR description now shows the producer only as a dormant callable foundation. Production lifecycle wiring must arrive together with a durable store and a trustworthy confirmed-binding issuer; enabling a partial owner here would violate that boundary.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The production lifecycle ownership requirement remains Stack D scope; #2156 now records the accompanying no-behavior-change decomposition without prematurely activating this foundation.

Comment thread packages/agent/src/profile-manager.ts Outdated
Comment thread packages/agent/src/system-records/provider-v1.ts Outdated
Comment thread packages/agent/src/system-records/provider-v1.ts Outdated
Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts Outdated
Comment thread packages/agent/src/evm-message-signer-v1.ts Outdated
Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts Outdated
Comment thread packages/agent/src/system-records/in-memory-agent-profile-publication-store-v1.ts Outdated
Comment thread packages/agent/src/system-records/provider-v1.ts
Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts Outdated
if (!Object.isFrozen(prepared) || !Object.isFrozen(prepared.quads)) {
throw new Error('prepared profile must be immutable');
}
const projected = prepared.quads.map((quad) => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Do not duplicate the agent-profile projection schema in the producer

What's wrong
This puts schema ownership in two places. The agent producer now has its own interpretation of what a valid profile projection is, while storage/core already own related system-record validation. That is architectural drift and makes future schema changes harder to reason about.

Example
Adding a new profile-derived subject or predicate now requires updating this producer-side subset and the storage/materialization validator. The two layers can drift because there is no shared projection-preparation model.

Suggested direction
Centralize profile projection preparation in the canonical system-record layer and have the producer consume that result instead of reimplementing a partial schema pass locally.

For Agents
Look at validateAndProject and the existing system-record projection validation in storage/core. Extract or export one canonical prepareAgentProfileProjectionV1/assertAgentProfileProjectionSchemaV1 helper that returns graphless canonical quads plus the owned-subject table; update producer tests to prove the producer and storage validator accept the same fixtures.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Do not duplicate profile RDF identity rules in the system-record producer

What's wrong
The producer now knows private details of how buildAgentProfile serializes agent identity triples. That leaks profile-format ownership into the system-record layer and creates a second source of truth for the same RDF shape.

Example
buildAgentProfile emits dkg:peerId, optional dkg:publicKey, and dkg:agentAddress; assertAdvertisedIdentity reconstructs those exact quoted object strings from independent signer inputs. Any later change to literal escaping, predicate constants, or public-key normalization requires remembering to update this separate parser-like check.

Suggested direction
Move the identity extraction/binding into the profile preparation layer, or expose canonical predicate/literal helpers from the profile module. The producer should consume a typed prepared identity instead of filtering raw quads with hard-coded namespace strings and hand-built quoted literals.

For Agents
Look in profile.ts and agent-profile-producer-v1.ts. Preserve the identity binding checks, but make prepareAgentProfileV1 return structured identity metadata or a typed AgentProfileProjectionV1 produced by the same profile builder. Tests should prove mismatched peer id, public key, and EVM address are still rejected without duplicating RDF literal construction in the producer.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed as the remaining pre-activation schema-ownership refactor. This default-off PR keeps the strict identity checks intact; moving canonical identity extraction into profile preparation is explicitly listed in the PR checklist together with the pure-stage/schema centralization work, before any runtime activation. Leaving this thread open intentionally.

Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts Outdated
Comment thread packages/agent/src/system-records/in-memory-agent-profile-publication-store-v1.ts Outdated
Comment thread packages/agent/src/profile.ts
Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts
Comment thread packages/agent/src/system-records/in-memory-agent-profile-publication-store-v1.ts Outdated
Comment thread packages/agent/src/evm-message-signer-v1.ts
Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts Outdated
Comment thread packages/agent/src/system-records/provider-v1.ts Outdated
assertedAtKav10Address: `0x${'44'.repeat(20)}`,
}) as unknown as CatalogSealDeploymentProfileV1;

describe('agent-profile system-record producer V1', () => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Decompose the new producer test file before it settles past 1k lines

What's wrong
The PR introduces a test file over the 1k-line threshold with many unrelated concerns and heavy inline fixtures. That is a maintainability smell even for tests: failures and fixture changes will be harder to localize, and future cases will naturally accumulate in the same oversized file.

Example
A reader changing publication fixture generation has to scan the same 1k-line file that also contains concurrency, capacity, identity, timestamp, and lineage scenarios. That is already past the size boundary where targeted review gets harder.

Suggested direction
Keep the high-value coverage, but split by concern: happy path/update flow, concurrency/capacity, authority lineage, and projection/identity rejection. Put shared fixture builders in a helper module so each scenario file is small enough to scan.

For Agents
Split packages/agent/test/system-record-agent-profile-producer-v1.test.ts into focused scenario files, and move reusable signing/publication fixture builders into a dedicated test helper. Preserve the same assertions; this is a decomposition-only cleanup.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid test-maintainability follow-up, but not a merge blocker for the default-off runtime contract. The PR checklist now requires splitting the producer suite by concern with shared fixtures before activation coverage is added. Keeping this as a separate decomposition change avoids mixing a large test-only move with the two safety regressions in this round.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Decompose the new producer test file before it hardens past 1k lines

What's wrong
This PR introduces a test file over the 1000-line threshold. Even though the cases are useful, the file already combines many behavior clusters and fixture machinery, which will make future producer changes harder to review and easier to patch with more local sprawl.

Example
The same file contains producer behavior scenarios, authority-transition envelope builders, publication seal construction, projection digest helpers, request builders, and observing-store wrappers. A reader changing one fixture helper has to scan a thousand-line suite to understand the blast radius.

Suggested direction
Extract the fixture DSL and signing/publication builders into support modules, then split the scenario cases into focused test files. The goal is for each file to explain one behavior cluster instead of becoming the permanent home for all producer cases.

For Agents
Split system-record-agent-profile-producer-v1.test.ts before merging. Move reusable fixture/building helpers to packages/agent/test/support/, and divide the cases into smaller suites by concern such as publication flow, rejection/preflight, authority lineage, and store interaction. Preserve the existing assertions; this is decomposition, not coverage expansion.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Decompose the new producer test file before it hardens past 1k lines

What's wrong
This crosses the 1000-line threshold on introduction. Even though it is test code, it creates a large mixed-responsibility file that will be expensive to navigate and easy to grow further as the producer evolves.

Example
The same file contains the happy-path producer test, COW inventory update tests, stale writer tests, authority-transition lineage setup, capacity/commit lease tests, schema projection rejection tests, and all signing/publication fixture helpers.

Suggested direction
Extract the large fixture/signing helpers and split scenarios by behavior area so each file has one reason to change.

For Agents
Split system-record-agent-profile-producer-v1.test.ts into smaller focused specs and move shared fixture builders into a local test helper module, for example producer fixtures/signing helpers in test/helpers/system-record-agent-profile-fixture.ts, lifecycle/commit tests in one spec, and validation/rejection tests in another. Preserve the existing assertions; this is decomposition, not reduced coverage.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Substantially addressed in d39fc1e: all signing, publication, transition, digest, lookup, and observing-store fixture mechanics moved to test/support/agent-profile-producer-v1-fixture.ts, reducing the behavior suite from 1,193 to 959 lines. A further concern-based scenario split is explicitly retained in the pre-activation checklist; it is test-only decomposition and does not affect this default-off runtime contract.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Decompose the new 1100-line producer test suite

What's wrong
This PR introduces a test file over the 1k-line threshold. Even though the assertions are useful, the file now combines several independent behavioral areas, which makes the suite harder to navigate and encourages future additions to pile into the same broad bucket.

Example
The store snapshot immutability case around line 565, the authority-transition case around line 363, and projection-schema rejection cases near line 961 are unrelated maintenance concerns but live in one very large suite.

Suggested direction
Break the suite by responsibility instead of continuing to grow one mega-file. This keeps future failures local and makes the test structure mirror the production boundaries the PR is introducing.

For Agents
Split packages/agent/test/system-record-agent-profile-producer-v1.test.ts into focused suites, for example producer publication/update, authority lineage, projection/identity validation, and store/commit behavior. Keep the existing fixture module and preserve the same assertions.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated and intentionally deferred as decomposition-only follow-up. The behavior suite is 1,137 lines after the new completing-abort regression; reusable mechanics are already extracted under test/support, and the PR checklist now records the exact current size and requires concern-focused splitting before activation coverage. This default-off correctness round does not move existing tests without changing behavior.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Decompose the new producer test file before it settles above 1k lines

What's wrong
This PR introduces a test file over the 1k-line threshold without a strong structural reason. Even though it is test code, the file is already carrying several independent behavioral domains.

Example
A reader looking for authority-transition coverage has to scan the same file that also owns cache rollover, duplicate triples, clock skew, commit rollback, and identity mismatch cases.

Suggested direction
Keep the fixture module, but move scenario groups into separate test files named by behavior. That makes failures easier to localize and keeps future additions from turning this into the dumping ground for every producer concern.

Confidence note
Line count verified with wc -l: packages/agent/test/system-record-agent-profile-producer-v1.test.ts is 1137 lines.

For Agents
Split packages/agent/test/system-record-agent-profile-producer-v1.test.ts into focused suites, for example lifecycle/commit, publication binding, authority history, schema/identity, and cache capacity. Keep shared setup in test/support/agent-profile-producer-v1-fixture.ts.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated again and retained as an explicit pre-activation maintainability follow-up. This round added the requested tombstone integrity regression, taking the suite to 1,212 lines; the PR checklist records that exact size and requires concern-focused decomposition before activation coverage. Splitting existing green scenarios is not a merge blocker for this default-off contract.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The remaining concern-based producer test split is now durably tracked in #2156 and required before activation.

Comment thread packages/agent/src/system-records/in-memory-agent-profile-publication-store-v1.ts Outdated
Comment thread packages/agent/src/system-records/provider-v1.ts Outdated
Comment thread packages/agent/src/evm-message-signer-v1.ts
Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts
Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts Outdated
Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts Outdated
Comment thread packages/core/src/system-record-objects-v1.ts Outdated
Comment thread packages/agent/test/system-record-agent-profile-producer-v1.test.ts
Comment thread packages/agent/src/system-records/provider-v1.ts Outdated
Comment thread packages/agent/test/evm-message-signer-v1.test.ts Outdated
Comment thread packages/agent/src/profile.ts Outdated
Comment thread packages/storage/test/system-record-verified-replacement-v1.test.ts Outdated
Comment thread packages/core/src/agent-profile-projection-schema-v1.ts
Comment thread packages/agent/test/support/agent-profile-producer-v1-fixture.ts
Comment thread packages/agent/test/system-record-provider-v1.test.ts
Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts
const PROV = 'http://www.w3.org/ns/prov#';
const SKILL = 'https://dkg.origintrail.io/skill#';

const IRI_OBJECT_PREDICATES = new Set<string>([

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Collapse the profile schema’s parallel lookup tables into one canonical schema model

What's wrong
This PR successfully moves projection validation into core, but it still leaves the profile schema split across several unlinked tables and files. That makes schema evolution brittle and forces readers to mentally join multiple sources of truth to understand what V1 permits.

Example
Adding a new derived subject or root link now requires coordinating multiple scattered schema fragments: the owned-subject classifier/predicate table, the IRI-vs-literal table, the allowed rdf:type table, and the link-target logic. Missing any one leaves the schema hard to reason about.

Suggested direction
Replace the separate predicate, term-kind, rdf:type, and link-target mechanisms with one typed schema descriptor that both object codecs and projection validation consume.

For Agents
Consolidate the agent profile schema metadata near AGENT_PROFILE_PREDICATES_V1/AGENT_PROFILE_LINK_PREDICATES_V1, or export a single declarative schema table keyed by subject kind. It should describe allowed predicates, object term kind, allowed rdf:type objects, and link target kind. Keep existing validation behavior unchanged and update storage/producer callers to use the shared table.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated as real maintainability work before activation, but not a blocker for this default-off composition API. The current author output is fail-closed through the core validator and now has positive coverage for real capability/offering/hosting facts. The PR checklist explicitly requires consolidating fact authoring plus predicate, term-kind, type, and link-target policy behind one declarative core specification before activation; doing that here would substantially widen a behavior-neutral layer without changing its dormant runtime surface.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: Keep profile schema policy in one canonical table

What's wrong
The PR improves reuse by sharing projection validation, but it also creates parallel schema tables. That is a maintainability trap: future schema changes now require coordinated edits in multiple places, and the code gives no structural guarantee they stay aligned.

Example
Adding a new profile-owned predicate requires updating the allowed-predicate table in system-record-objects-v1.ts, then remembering to update this module's object-term-kind/type policy as well. Missing the second update leaves the schema inconsistent even though the classifier says the predicate is allowed.

Suggested direction
Move predicate allow-list, object term kind, allowed rdf:type objects, and link target kind into one exported profile-schema descriptor, then have both classification and projection validation consume that descriptor.

For Agents
In packages/core/src/agent-profile-projection-schema-v1.ts and packages/core/src/system-record-objects-v1.ts, consolidate profile schema metadata into one canonical table keyed by owned-subject kind/predicate. Preserve current validation behavior and keep producer/storage projection schema tests passing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated as a real maintainability follow-up, but not an activation or correctness blocker for this default-off PR. The PR checklist already requires centralizing the duplicated profile/preparation schema boundary before activation; keeping that work separate avoids expanding this provider/producer review scope.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Issue: The shared projection schema is encoded as parallel tables plus special-case branches

What's wrong
The PR successfully moves schema validation into a canonical core module, but the implementation still spreads one schema across several independent data structures and conditional blocks. That makes the canonical layer harder to extend safely and obscures the invariant each predicate is supposed to enforce.

Example
Adding one new derived subject kind or link predicate requires updating multiple parallel structures and conditionals, then remembering which branch enforces object term kind, linked-subject ownership, rdf:type allowance, and derived-subject validation.

Suggested direction
Use a single table-driven schema model so each predicate’s rules live in one place. That would remove the Object.entries(...).find(...) link inference and most of the predicate-specific branching from the validator.

Confidence note
This is a structural recommendation; the current logic may be behaviorally correct, but the shared schema module is likely to become the place future profile predicates are added.

For Agents
In packages/core/src/agent-profile-projection-schema-v1.ts, consider replacing the parallel sets and branch chain with a table keyed by AgentProfileOwnedSubjectKindV1, where each predicate declares its object kind, allowed rdf:type values, optional root-link target kind, and optional derived-subject validator. Preserve existing accepted/rejected projections.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Validated again as the same non-blocking maintainability follow-up already recorded in the PR's explicit pre-activation checklist and discussed earlier in this thread. The current shared validator has full positive/negative behavioral coverage and this subsystem remains default-off; converting it to a declarative table is best done as a no-behavior-change follow-up before activation rather than expanding this producer/provider PR. Leaving the thread open intentionally.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The declarative single-owner projection-schema refactor is now durably tracked in #2156 and required before activation.

Comment thread packages/agent/src/system-records/agent-profile-producer-v1.ts
Comment thread packages/agent/test/support/agent-profile-producer-v1-fixture.ts Outdated
@Jurij89
Jurij89 changed the base branch from feat/2052-system-record-runtime to integration/2052-system-record-sync August 8, 2026 02:07
@Jurij89
Jurij89 merged commit b971d25 into integration/2052-system-record-sync Aug 8, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants