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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions cmd/canvas-harness/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"errors"
"fmt"

agentsuite "github.com/agent-primitives/suite"
"github.com/agent-primitives/suite/core"
)

type inventory struct {
Expand All @@ -25,7 +25,7 @@ func decodeInventory(data []byte) (inventory, error) {
Version int `json:"version"`
Entries []json.RawMessage `json:"entries"`
}
if err := agentsuite.Unmarshal(data, &wire); err != nil {
if err := core.Unmarshal(data, &wire); err != nil {
return inventory{}, fmt.Errorf("invalid inventory: %w", err)
}
if (wire.Version != 1 && wire.Version != 2) || len(wire.Entries) == 0 || len(wire.Entries) > 32 {
Expand All @@ -40,24 +40,24 @@ func decodeInventory(data []byte) (inventory, error) {
Bundle string `json:"bundle"`
Address string `json:"address"`
}
err = agentsuite.Unmarshal(raw, &legacy)
err = core.Unmarshal(raw, &legacy)
e.Bundle, e.Address = legacy.Bundle, legacy.Address
} else {
var fields map[string]json.RawMessage
err = agentsuite.Unmarshal(raw, &fields)
err = core.Unmarshal(raw, &fields)
if err == nil {
err = agentsuite.Unmarshal(fields["kind"], &e.Kind)
err = core.Unmarshal(fields["kind"], &e.Kind)
}
if err == nil {
switch e.Kind {
case "bundle":
err = agentsuite.Unmarshal(raw, &e)
err = core.Unmarshal(raw, &e)
case "simulated-announcement":
var fixed struct {
Kind string `json:"kind"`
Address string `json:"address"`
}
err = agentsuite.Unmarshal(raw, &fixed)
err = core.Unmarshal(raw, &fixed)
e.Address = fixed.Address
default:
err = errors.New("unknown entry kind")
Expand Down
4 changes: 2 additions & 2 deletions cmd/canvas/runtime_mode.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"os"
"syscall"

agentsuite "github.com/agent-primitives/suite"
"github.com/agent-primitives/suite/core"
)

var errRuntimeMode = errors.New("runtime mode binding is invalid or incompatible; use separate state without changing existing history")
Expand Down Expand Up @@ -90,7 +90,7 @@ func readRuntimeMode(root *os.Root) (string, bool, error) {
}
raw, err := io.ReadAll(io.LimitReader(file, 513))
var record runtimeModeRecord
if err != nil || len(raw) > 512 || agentsuite.Unmarshal(raw, &record) != nil || record.SchemaVersion != "canvas.runtime-mode/v1" || record.Mode != "fixture" && record.Mode != "real" {
if err != nil || len(raw) > 512 || core.Unmarshal(raw, &record) != nil || record.SchemaVersion != "canvas.runtime-mode/v1" || record.Mode != "fixture" && record.Mode != "real" {
return "", false, errRuntimeMode
}
return record.Mode, true, nil
Expand Down
2 changes: 1 addition & 1 deletion docs/generic-canvas.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ intents only.

## Identity and evaluation boundaries

`github.com/agent-primitives/suite v0.4.0` validates the captured directory and
`github.com/agent-primitives/suite v0.7.0` validates the captured directory and
matching local OCI layout. Both views must have equal full-inventory content
identity; the layout must match the configured artifact pin. Canvas delegates graph validation and evaluation verification to the shared library.
It bounds transport and decompression before validation and does not parse kmx private receipts.
Expand Down
9 changes: 5 additions & 4 deletions examples/northwind-released/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ isolation/rollback limitations, and mock disclosure. These are transport/proof/
export consistency fixtures, not model-quality or complete Northwind evaluations.

The successful label is **evaluation consistent; unsigned**. It means that
`agentsuite.VerifyEvaluation` matched the retained layout, independently reviewed
`evidence.VerifyEvaluation` matched the retained layout, independently reviewed
expectations, case/run coverage and passing claims. It does not establish who
made those claims, whether observations were real, clock authenticity, freshness,
Canvas runtime equivalence or deployment readiness. Replay is a different check.
Expand All @@ -57,9 +57,10 @@ Both select `linux/amd64`, the unprofiled/native composition, and its
Orka runtime or this Canvas harness**. No associated images ran. The newly
authored model is `northwind-mock`; the original Northwind model was not overridden.

The library module is `github.com/agent-primitives/suite v0.4.0`; the authored
schema version remains `1.0.0-draft`. Neither version is an artifact, graph,
member, composition, build-profile, evidence or execution-archive digest.
Canvas verifies these retained fixtures with
`github.com/agent-primitives/suite v0.7.0`; the authored schema version remains
`1.0.0-draft`. Neither version is an artifact, graph, member, composition,
build-profile, evidence or execution-archive digest.

Producer details:

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ toolchain go1.27.3
require (
github.com/agent-primitives/sessions v0.2.1-0.20261019224537-f18a2cb1454d
github.com/agent-primitives/sessions/integrations/substrate v0.0.0-20261019224537-f18a2cb1454d
github.com/agent-primitives/suite v0.6.0
github.com/agent-primitives/suite v0.7.0
github.com/agent-substrate/substrate v0.4.1-0.20261013053953-96dffb287919
github.com/coreos/go-oidc/v3 v3.17.0
github.com/google/jsonschema-go v0.4.3
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ github.com/agent-primitives/sessions v0.2.1-0.20261019224537-f18a2cb1454d h1:5R4
github.com/agent-primitives/sessions v0.2.1-0.20261019224537-f18a2cb1454d/go.mod h1:DZCwTLhJb6bltufqRqKK7IOEsx+s6isnMK7PMiaR7Ts=
github.com/agent-primitives/sessions/integrations/substrate v0.0.0-20261019224537-f18a2cb1454d h1:jf7ic/0UjUu8Q+G9poQqeUUdLze/pW6ptT7zfQIxmd8=
github.com/agent-primitives/sessions/integrations/substrate v0.0.0-20261019224537-f18a2cb1454d/go.mod h1:4RZd3LCiXwGVYAvPDvRS3F/zjgh5SbHWHIeHkrMPqkc=
github.com/agent-primitives/suite v0.6.0 h1:bRGzbZTq+6ApAPiMS3pmbJCLG0RLA+dqGOhWMinQq9M=
github.com/agent-primitives/suite v0.6.0/go.mod h1:61Z9uzfg7z/DdWSzHxY3kcDq1SAKcEXEOX6qNmD6MC0=
github.com/agent-primitives/suite v0.7.0 h1:4Ks7PXdsSo5BWfAgmb6PErl/Pcqbo9yswAr0lzdcnBo=
github.com/agent-primitives/suite v0.7.0/go.mod h1:61Z9uzfg7z/DdWSzHxY3kcDq1SAKcEXEOX6qNmD6MC0=
github.com/agent-substrate/substrate v0.4.1-0.20261013053953-96dffb287919 h1:RP19jHZ/bv7AcknDgut2SW9btWbYnpOeT41M5bjOVAY=
github.com/agent-substrate/substrate v0.4.1-0.20261013053953-96dffb287919/go.mod h1:XVQwhYEmOlb+ILs9BvSCHXYhgo2F6/N2qN4DmRwogQI=
github.com/coreos/go-oidc/v3 v3.17.0 h1:hWBGaQfbi0iVviX4ibC7bk8OKT5qNr4klBaCHVNvehc=
Expand Down
4 changes: 2 additions & 2 deletions internal/canvas/announcement_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"net/http"

"github.com/agent-primitives/canvas/internal/sessionclient"
agentsuite "github.com/agent-primitives/suite"
"github.com/agent-primitives/suite/core"
)

type announcementRequest struct {
Expand All @@ -35,7 +35,7 @@ func (c *Canvas) announcementRoutes(mux *http.ServeMux, send func(http.ResponseW
mux.HandleFunc("POST /api/announcement/", func(w http.ResponseWriter, r *http.Request) {
raw, err := io.ReadAll(http.MaxBytesReader(w, r.Body, 16<<10))
var object map[string]json.RawMessage
if err != nil || agentsuite.Unmarshal(raw, &object) != nil || object == nil {
if err != nil || core.Unmarshal(raw, &object) != nil || object == nil {
send(w, 400, map[string]string{"error": "Invalid local announcement action."})
return
}
Expand Down
4 changes: 2 additions & 2 deletions internal/canvas/changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"errors"
"unicode/utf8"

agentsuite "github.com/agent-primitives/suite"
"github.com/agent-primitives/suite/core"
)

const maxProposalChanges = 32
Expand Down Expand Up @@ -60,7 +60,7 @@ func (d *CompiledDefinition) Changes(agent, output string) (map[string]string, e
Content *string `json:"content"`
} `json:"changes"`
}
if agentsuite.Unmarshal([]byte(output), &envelope) != nil || len(envelope.Changes) == 0 || len(envelope.Changes) > maxProposalChanges {
if core.Unmarshal([]byte(output), &envelope) != nil || len(envelope.Changes) == 0 || len(envelope.Changes) > maxProposalChanges {
return nil, errors.New("invalid bounded change envelope")
}
result := map[string]string{}
Expand Down
8 changes: 4 additions & 4 deletions internal/canvas/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (

"github.com/agent-primitives/canvas/internal/contract"
"github.com/agent-primitives/canvas/internal/sharedspace"
agentsuite "github.com/agent-primitives/suite"
"github.com/agent-primitives/suite/core"
"github.com/google/jsonschema-go/jsonschema"
"go.yaml.in/yaml/v3"
)
Expand Down Expand Up @@ -433,7 +433,7 @@ func loadGenericDefinition(filename string, resolver *contract.ReleaseResolver,
loadFlowSchema := func(source string) (*jsonschema.Resolved, error) {
resolved, err := loadSchema(source)
var value any
if err != nil || agentsuite.Unmarshal(schemas[source], &value) != nil || !preservesJSONNumbers(value) {
if err != nil || core.Unmarshal(schemas[source], &value) != nil || !preservesJSONNumbers(value) {
return nil, errDefinition
}
return resolved, nil
Expand Down Expand Up @@ -464,7 +464,7 @@ func loadGenericDefinition(filename string, resolver *contract.ReleaseResolver,
}
func compileDocumentSchema(raw []byte) (*jsonschema.Resolved, error) {
var value any
if agentsuite.Unmarshal(raw, &value) != nil || !localSchemaRefs(value) {
if core.Unmarshal(raw, &value) != nil || !localSchemaRefs(value) {
return nil, errDefinition
}
var schema jsonschema.Schema
Expand Down Expand Up @@ -506,7 +506,7 @@ func validateDocument(doc compiledDocument, content string) error {
// Public strict decoding uses json.Number, which jsonschema-go v0.4.3
// classifies as a string. After strict/lossless validation, decode into
// standard JSON values so numeric types reach schema validation intact.
if agentsuite.Unmarshal([]byte(content), &instance) != nil || json.Unmarshal([]byte(content), &instance) != nil || doc.schema.Validate(instance) != nil {
if core.Unmarshal([]byte(content), &instance) != nil || json.Unmarshal([]byte(content), &instance) != nil || doc.schema.Validate(instance) != nil {
return errors.New("document does not satisfy schema")
}
}
Expand Down
4 changes: 2 additions & 2 deletions internal/canvas/flow_definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"strconv"
"strings"

agentsuite "github.com/agent-primitives/suite"
"github.com/agent-primitives/suite/core"
"github.com/google/jsonschema-go/jsonschema"
"go.yaml.in/yaml/v3"
)
Expand Down Expand Up @@ -85,7 +85,7 @@ func (d *CompiledDefinition) ValidateFlowInputs(id string, raw []byte) error {
}
var value any
// Preserve strict JSON checks, then give schema validation native numbers.
if agentsuite.Unmarshal(raw, &value) != nil || !preservesJSONNumbers(value) || json.Unmarshal(raw, &value) != nil {
if core.Unmarshal(raw, &value) != nil || !preservesJSONNumbers(value) || json.Unmarshal(raw, &value) != nil {
return errDefinition
}
if _, ok := value.(map[string]any); !ok || flow.inputs.Validate(value) != nil {
Expand Down
4 changes: 2 additions & 2 deletions internal/canvas/flow_http.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"slices"

"github.com/agent-primitives/canvas/internal/sharedspace"
agentsuite "github.com/agent-primitives/suite"
"github.com/agent-primitives/suite/core"
)

// Polling omits exact historical inputs and private command/reservation journals.
Expand Down Expand Up @@ -192,7 +192,7 @@ func (c *Canvas) registerFlowRoutes(mux *http.ServeMux) {
func decodeFlowAction(w http.ResponseWriter, r *http.Request, limit int64, q any) bool {
raw, err := io.ReadAll(http.MaxBytesReader(w, r.Body, limit))
var object map[string]json.RawMessage
if err != nil || agentsuite.Unmarshal(raw, &object) != nil || object == nil {
if err != nil || core.Unmarshal(raw, &object) != nil || object == nil {
sendJSON(w, 400, map[string]string{"error": "A bounded JSON flow request is required.", "code": "FLOW_INVALID"})
return false
}
Expand Down
37 changes: 19 additions & 18 deletions internal/contract/evaluation.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,24 @@ import (
"os"
"strings"

agentsuite "github.com/agent-primitives/suite"
"github.com/agent-primitives/suite/core"
"github.com/agent-primitives/suite/evidence"
)

// EvaluationInfo is a checked release claim, never proof of the current Canvas run.
type EvaluationInfo struct {
Status string `json:"status"`
Reason string `json:"reason,omitempty"`
EvidenceDigest string `json:"evidenceDigest,omitempty"`
ExpectedDigest string `json:"expectedDigest,omitempty"`
Cases int `json:"cases,omitempty"`
Runs int `json:"runs,omitempty"`
CompletedAt string `json:"completedAt,omitempty"`
Unsigned bool `json:"unsigned"`
TestedExecution *agentsuite.EvidenceExecution `json:"testedExecution,omitempty"`
Status string `json:"status"`
Reason string `json:"reason,omitempty"`
EvidenceDigest string `json:"evidenceDigest,omitempty"`
ExpectedDigest string `json:"expectedDigest,omitempty"`
Cases int `json:"cases,omitempty"`
Runs int `json:"runs,omitempty"`
CompletedAt string `json:"completedAt,omitempty"`
Unsigned bool `json:"unsigned"`
TestedExecution *evidence.EvidenceExecution `json:"testedExecution,omitempty"`
}

func verifyReleaseEvaluation(layout string, a releasedArchive, manifest releaseDescriptor, identity *SuiteIdentity, agent agentsuite.Agent) EvaluationInfo {
func verifyReleaseEvaluation(layout string, a releasedArchive, manifest releaseDescriptor, identity *SuiteIdentity, agent core.Agent) EvaluationInfo {
result := EvaluationInfo{Status: "not verified", Reason: "missing"}
digest := func(data []byte) string { sum := sha256.Sum256(data); return fmt.Sprintf("sha256:%x", sum) }
if len(a.Expected) > 0 {
Expand All @@ -42,28 +43,28 @@ func verifyReleaseEvaluation(layout string, a releasedArchive, manifest releaseD
if len(a.Expected) == 0 || len(a.Evidence) == 0 {
return result
}
var expected agentsuite.ExpectedEvaluation
if !validExpectedShape(a.Expected) || agentsuite.Unmarshal(a.Expected, &expected) != nil || expected.Judges == nil {
var expected evidence.ExpectedEvaluation
if !validExpectedShape(a.Expected) || core.Unmarshal(a.Expected, &expected) != nil || expected.Judges == nil {
result.Reason = "malformed"
return result
}
parts := strings.Split(a.Platform, "/")
platform := agentsuite.EvidencePlatform{}
platform := evidence.EvidencePlatform{}
if len(parts) >= 2 {
platform.OS = parts[0]
platform.Architecture = parts[1]
}
if len(parts) == 3 {
platform.Variant = parts[2]
}
selected := agentsuite.EvidenceSubject{Manifest: agentsuite.EvidenceDescriptor{MediaType: manifest.MediaType, Digest: a.Pin, Size: manifest.Size}, MemberID: a.Member, MemberDigest: identity.MemberDigest, CompositionDigest: identity.Release.CompositionDigest, BuildProfileDigest: identity.Release.BuildProfileDigest, Platform: platform}
selected := evidence.EvidenceSubject{Manifest: evidence.EvidenceDescriptor{MediaType: manifest.MediaType, Digest: a.Pin, Size: manifest.Size}, MemberID: a.Member, MemberDigest: identity.MemberDigest, CompositionDigest: identity.Release.CompositionDigest, BuildProfileDigest: identity.Release.BuildProfileDigest, Platform: platform}
if expected.Subject != selected || expected.Execution.Model.ID != agent.Model.Model || expected.Execution.Model.Protocol != agent.Model.Protocol {
result.Reason = "subject"
return result
}
verified, err := agentsuite.VerifyEvaluation(layout, expected, bytes.NewReader(a.Evidence))
verified, err := evidence.VerifyEvaluation(layout, expected, bytes.NewReader(a.Evidence))
if err != nil {
var refused *agentsuite.EvidenceRefusal
var refused *evidence.EvidenceRefusal
if errors.As(err, &refused) {
result.Reason = refused.Code
} else {
Expand Down Expand Up @@ -135,7 +136,7 @@ func readEvaluationFile(filename string) ([]byte, error) {
// Strictly decode an independent expectation's outer shape, including explicit judges[].
func validExpectedShape(data []byte) bool {
var fields map[string]json.RawMessage
if agentsuite.Unmarshal(data, &fields) != nil || len(fields) != 4 {
if core.Unmarshal(data, &fields) != nil || len(fields) != 4 {
return false
}
for _, name := range []string{"subject", "execution", "evaluator", "judges"} {
Expand Down
Loading
Loading