Skip to content

Add CCL#58

Open
branarakic wants to merge 3 commits intomainfrom
add-ccl-language-extension
Open

Add CCL#58
branarakic wants to merge 3 commits intomainfrom
add-ccl-language-extension

Conversation

@branarakic
Copy link
Copy Markdown
Contributor

Migrated from dkg-v9 PR #229

CCL (Corroboration & Consensus Language) is a deterministic DSL for expressing how a paranet decides whether shared DKG facts are sufficient to support, reject, or promote a claim. We need it so agents and nodes can evaluate the same approved policy over the same snapshot, produce the same result, and turn paranet governance into something replayable, auditable, and domain-specific instead of relying on ad hoc reasoning.

Summary

Adds CCL (Corroboration & Consensus Language) support as a paranet-scoped governance and adjudication layer for the DKG.
CCL is a deterministic policy DSL for defining how a paranet interprets shared DKG facts and decides whether a claim is sufficiently corroborated, contradicted, promotable, or acceptable under its own approved rules. Instead of relying on agent-specific reasoning or informal coordination, CCL lets a paranet define explicit decision rules that every node and agent can evaluate the same way.
This matters because the DKG already provides shared facts, scoped paranets, and publish/finalization flows, but it does not by itself define how a paranet should turn facts into decisions. CCL fills that gap by making adjudication programmable, replayable, and auditable. The intended flow is:

  1. agents communicate and publish relevant facts into the DKG
  2. a paranet resolves its approved CCL policy
  3. nodes evaluate that policy against a fixed fact set or snapshot
  4. evaluation produces deterministic derived predicates and decisions
  5. the result can then be published and used by normal DKG workflows
    This PR makes that flow concrete by adding policy management, deterministic evaluation, structured result publishing, and owner-only policy approval. It allows each paranet to define its own governance logic while keeping policy execution consistent across agents and nodes.
flowchart TD
    A[Agent coordination<br/>messages / skill calls]
    B[Shared DKG facts<br/>claims, supports, contradictions, quorum]
    C[Approved paranet policy<br/>CCL policy name + version + hash]
    D[Deterministic evaluation<br/>same policy + same facts = same output]
    E[Structured result publication<br/>CCLEvaluation / CCLResultEntry / CCLResultArg]
    F[Paranet governance outcome<br/>accept, reject, promote, or continue review]
    A --> B
    B --> D
    C --> D
    D --> E
    E --> F  
Loading

Example Agent Interaction

sequenceDiagram
    participant A as Agent A
    participant B as Agent B
    participant C as Agent C
    participant DKG as DKG Paranet
    participant CCL as Approved CCL Policy
    participant EVAL as CCL Evaluator
    A->>B: Request verification for claim c1
    A->>C: Ask for independent evidence
    A->>DKG: Publish claim facts for c1
    B->>DKG: Publish support evidence e1
    C->>DKG: Publish support evidence e2
    A->>DKG: Resolve active approved policy
    DKG-->>A: Return policy reference/version/hash
    A->>EVAL: Evaluate policy against fixed fact set
    EVAL->>CCL: Apply deterministic adjudication rules
    CCL-->>EVAL: Derived facts and decisions
    EVAL-->>A: propose_accept(c1)
    A->>DKG: Publish structured evaluation result
    DKG-->>A: Result available for downstream governance/finalization
Loading

In this flow, agent communication is used only to coordinate evidence gathering. The actual agreement step happens through shared DKG facts plus an approved CCL policy. Because the policy is fixed and the fact set is explicit, every node can replay the same evaluation and arrive at the same outcome.

Changes

  • Added a JavaScript/TypeScript CCL evaluator for deterministic execution of canonical CCL policies over fact tuples
  • Added paranet-scoped CCL policy lifecycle support:
    • publish a policy proposal
    • approve a policy for a paranet
    • resolve the active approved policy
    • support stricter per-context overrides
  • Added support for evaluating approved policies through agent and CLI flows
  • Added support for publishing evaluation outputs back into the graph as typed CCL evaluation records
  • Added structured RDF result arguments so derived facts and decisions are queryable by tuple element instead of being stored as opaque blobs
  • Removed legacy JSON tuple storage and made structured RDF the only result representation
  • Added owner-only approval enforcement so only the paranet creator can activate policies
  • Added CLI and daemon APIs for:
    • policy publish
    • policy approve
    • policy resolve
    • policy evaluation
    • published result listing/querying
  • Added CCL skill documentation and examples showing how agents should use CCL in practice
    Why It Works
  • Policies are versioned and published into the graph, so the network can reference explicit approved rule sets instead of hidden local logic
  • Evaluation uses an approved policy plus a declared fact set, which makes outcomes deterministic and replayable
  • Result publication stores evaluation metadata and tuple arguments as structured RDF, so adjudication outputs can be queried, inspected, and reused by other workflows
  • Owner-only approval provides a simple first governance boundary so policy activation is controlled at the paranet level
    Test Plan
  • Tests pass locally (pnpm test)
  • Build succeeds (pnpm build)

Related Issues

@branarakic branarakic changed the base branch from main to v10-rc April 3, 2026 13:55
lupuszr added 3 commits April 3, 2026 15:58
…y approval

CCL (Corroboration & Consensus Language) is a deterministic DSL for expressing how a paranet decides whether shared DKG facts are sufficient to support, reject, or promote a claim. We need it so agents and nodes can evaluate the same approved policy over the same snapshot, produce the same result, and turn paranet governance into something replayable, auditable, and domain-specific instead of relying on ad hoc reasoning.
@branarakic branarakic force-pushed the add-ccl-language-extension branch from 856f515 to 46a5a33 Compare April 3, 2026 13:59
if (!record) return null;
const bindings = await this.listCclPolicyBindings({ paranetId: opts.paranetId, name: record.name });
const latestByScope = this.selectLatestNonRevokedBindings(bindings);
const active = this.resolveCclPolicyBinding(latestByScope, opts.paranetId, record.name, opts.contextType);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Bug: getActiveCclPolicyBinding() reuses resolveCclPolicyBinding(), which falls back to the default binding when there is no exact contextType match. In revokeCclPolicy() that lets --context-type ... revoke the default policy for every context instead of failing. For revocation, require an exact-scope binding whenever a context type was supplied.

}

if (invalidBindings.size === 0) return quads;
return quads.filter(q => !invalidBindings.has(q.subject));
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Bug: this only strips quads whose subject is the invalid binding. approveCclPolicy() also gossips policyStatus / approvedBy / approvedAt on the policy URI, so a forged approval still mutates stored policy metadata even though the binding is rejected. Reject the whole payload, or also remove the companion policy-subject quads for invalid bindings.

if (Array.from(latestByScope.values()).some(binding => binding.policyUri === policyUri)) {
return 'approved';
}
if (bindings.some(binding => binding.policyUri === policyUri)) {
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: any policy that ever had a binding but is no longer the latest active one is reported as revoked here, even when it was only superseded by a newer approval. That makes the status field misleading and breaks status=revoked filtering. Distinguish explicit revocation from superseded/inactive bindings.

return {
facts,
factSetHash: hashFacts(facts),
factQueryHash: hashString(`${profile.id}\n${query}`),
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: factQueryHash only hashes the static SPARQL text, while snapshotId, view, and scopeUal are applied later in JS. Different resolution scopes can therefore publish the same query hash even though they selected different fact sets. Include the effective filters in the hashed query, or push them into the SPARQL itself.

Comment thread packages/cli/src/cli.ts
};
}

if (!payload || !Array.isArray(payload.facts) || payload.facts.length === 0) {
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: this hard-requires a non-empty facts array, so the new snapshot-resolved evaluation path is unreachable from dkg ccl eval even though the agent/API support omitting facts. Allow --snapshot-id/--view/--scope-ual without --case or --facts-file, and only require facts for explicit manual mode.

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