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
35 changes: 32 additions & 3 deletions .agent-runtime/goals/no-unenforced-ceremony.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"schema_version": "v1alpha1",
"revision": 12,
"revision": 13,
"goal": {
"id": "no-unenforced-ceremony",
"intent": "Every retained contract field buys enforcement and trust tooling resolves without ambient paths",
Expand Down Expand Up @@ -45,9 +45,38 @@
"non_goals": [
"Weaken any fail-closed signature or provenance check"
],
"state": "active",
"state": "completed",
"current_phase": "closure",
"receipts": {
"closure": {
"phase": "closure",
"summary": "Merged as PR #59 after a first attempt was rejected by CI for a umask-dependent fixture, which is recorded as evidence on the omission audit rather than quietly amended.",
"evidence": [
{
"type": "link",
"reference": "https://github.com/NDDev-it-com/agent-runtime/pull/59",
"result": "Merged to main with all four required checks green."
}
],
"recorded_at": "2026-08-15T00:22:12.263885496Z",
"closure": {
"achieved_outcome": "No contract field is retained without enforcement, the trust path has one definition that never reads PATH, and the GDS anchor states how the module is actually consumed.",
"cleanup": "Task branch deleted locally and on origin.",
"remaining": [
{
"kind": "risk",
"summary": "Nix and Guix hosts cannot run signature or provenance verification, because their tools sit outside every absolute directory the resolver will search. Any mechanism covering them is an ambient input into the trust path; the constraint and its reason are stated in SECURITY.md."
}
],
"next_work": [
{
"type": "issue",
"reference": "v0.2.0",
"result": "Cut the release the control plane needs in order to consume any of this work, since it pins by release tag."
}
]
}
},
"completeness_omission_audit": {
"phase": "completeness_omission_audit",
"summary": "Nix and Guix hosts still cannot verify, because their tools are outside every absolute directory the resolver will search and any mechanism covering them is an ambient input into the trust path. Stated in the security model with the reason and the failure message that names what was searched.",
Expand Down Expand Up @@ -139,6 +168,6 @@
}
},
"created_at": "2026-08-15T00:12:44.224755101Z",
"updated_at": "2026-08-15T00:18:10.11806904Z"
"updated_at": "2026-08-15T00:22:12.263885496Z"
}
}
255 changes: 115 additions & 140 deletions CHANGELOG.md

Large diffs are not rendered by default.

8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ protocol, scheduler, or operating-system sandbox.
Requires Go 1.25 or newer.

```sh
go install github.com/NDDev-it-com/agent-runtime/cmd/agent-runtime@v0.1.3
go install github.com/NDDev-it-com/agent-runtime/cmd/agent-runtime@v0.2.0
agent-runtime task validate --manifest examples/basic/agent.json --workspace examples/basic
agent-runtime task run --manifest examples/basic/agent.json --workspace examples/basic
```
Expand Down Expand Up @@ -92,13 +92,17 @@ The canonical distributable schema is
The project is released as a Go module/source product. It does not publish
prebuilt platform binaries.

The current release is `v0.1.3`. `v0.1.2` was the first published one.
The current release is `v0.2.0`. `v0.1.2` was the first published one.
`v0.1.0` and `v0.1.1` were tagged but never published — the first pinned a Go
toolchain below the module's own directive, the second read a repository setting
its token cannot access, and both failed before building an asset. Those tags
and their Go module proxy entries are immutable, so they are left in place
carrying no release assets and no attestations. Use `v0.1.2` or later.

`v0.2.0` breaks the manifest contract deliberately: a Task manifest that states
a zero timeout, output or context bound is now refused rather than silently
widened to a default. Manifests that omit a bound are unaffected.

Each tag-only release will contain one deterministic tracked-source archive, an
SPDX 2.3 JSON SBOM, canonical release notes, a release manifest, and
`SHA256SUMS`. The annotated signed tag identifies the exact `main` commit;
Expand Down
24 changes: 12 additions & 12 deletions docs/releasing.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Releasing the Go module/source product

`release/v1alpha1.json` is the only release source of truth. The version it
currently names is `v0.1.3`; the compatibility declaration is Go 1.25. `v0.1.2`
currently names is `v0.2.0`; the compatibility declaration is Go 1.25. `v0.1.2`
was the first published release. `v0.1.0` and `v0.1.1` were tagged but never
published — the first pinned a Go toolchain below the module's own directive,
the second read the immutable-releases setting, which the publishing token
Expand All @@ -16,10 +16,10 @@ matrix.

The exact release asset set is:

- `agent-runtime-v0.1.3-source.tar.gz`
- `agent-runtime-v0.1.3.spdx.json`
- `release-notes-v0.1.3.md`
- `release-manifest-v0.1.3.json`
- `agent-runtime-v0.2.0-source.tar.gz`
- `agent-runtime-v0.2.0.spdx.json`
- `release-notes-v0.2.0.md`
- `release-manifest-v0.2.0.json`
- `SHA256SUMS`

The builder reads the exact Git commit tree. It rejects symlinks, gitlinks,
Expand Down Expand Up @@ -132,10 +132,10 @@ covers every other asset and deliberately does not checksum itself.
`gh api repos/NDDev-it-com/agent-runtime/immutable-releases --jq '.enabled'`,
that no tag or release exists, and that the clean local `main` equals
`origin/main`. Nothing later re-checks the first of these.
9. Create an annotated SSH-signed `v0.1.3` tag on that exact commit, verify it
9. Create an annotated SSH-signed `v0.2.0` tag on that exact commit, verify it
locally with `go run ./cmd/check-signature --tag "$(git rev-parse
'v0.1.3^{tag}')" --expected-commit "$(git rev-parse
'v0.1.3^{commit}')"`, and push only the tag.
'v0.2.0^{tag}')" --expected-commit "$(git rev-parse
'v0.2.0^{commit}')"`, and push only the tag.

The tag workflow rejects reruns, wrong refs or versions, lightweight or
unverified tags, a tag not equal to current `main`, an existing release,
Expand All @@ -160,10 +160,10 @@ Download all five assets, then run:

```sh
sha256sum -c SHA256SUMS
gh attestation verify agent-runtime-v0.1.3-source.tar.gz -R NDDev-it-com/agent-runtime
gh attestation verify agent-runtime-v0.1.3.spdx.json -R NDDev-it-com/agent-runtime
gh attestation verify release-notes-v0.1.3.md -R NDDev-it-com/agent-runtime
gh attestation verify release-manifest-v0.1.3.json -R NDDev-it-com/agent-runtime
gh attestation verify agent-runtime-v0.2.0-source.tar.gz -R NDDev-it-com/agent-runtime
gh attestation verify agent-runtime-v0.2.0.spdx.json -R NDDev-it-com/agent-runtime
gh attestation verify release-notes-v0.2.0.md -R NDDev-it-com/agent-runtime
gh attestation verify release-manifest-v0.2.0.json -R NDDev-it-com/agent-runtime
gh attestation verify SHA256SUMS -R NDDev-it-com/agent-runtime
```

Expand Down
6 changes: 5 additions & 1 deletion internal/releasecontract/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -711,7 +711,11 @@ func fixtureRepo(t *testing.T) string {
mustWrite(t, filepath.Join(d, "go.sum"), []byte(canonicalGoSum(testContract())))
mustWrite(t, filepath.Join(d, "main.go"), []byte("package agentruntime\n"))
mustWrite(t, filepath.Join(d, "LICENSE"), []byte("AGPL-3.0-only\n"))
mustWrite(t, filepath.Join(d, "CHANGELOG.md"), []byte("# Changelog\n\n## [0.1.3] - 2026-08-14\n\n### Added\n\n- Initial source release.\n"))
// Derived from the contract rather than restated, so a version bump does
// not silently leave the fixture describing a release that is not the one
// under test.
version := strings.TrimPrefix(testContract().Version, "v")
mustWrite(t, filepath.Join(d, "CHANGELOG.md"), []byte("# Changelog\n\n## ["+version+"] - 2026-08-14\n\n### Added\n\n- Initial source release.\n"))
gitRun(t, d, "add", ".")
gitRun(t, d, "commit", "-q", "-m", "fixture")
return d
Expand Down
12 changes: 6 additions & 6 deletions release/v1alpha1.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"schema_version": "v1alpha1",
"version": "v0.1.3",
"version": "v0.2.0",
"module_path": "github.com/NDDev-it-com/agent-runtime",
"go_compatibility": "1.25",
"license": "AGPL-3.0-only",
Expand All @@ -18,14 +18,14 @@
{"module_path": "github.com/dlclark/regexp2", "version": "v1.11.0", "license": "MIT"}
],
"source_commit": "HEAD",
"archive_prefix": "agent-runtime-v0.1.3/",
"archive_prefix": "agent-runtime-v0.2.0/",
"workflow": ".github/workflows/release.yml",
"allowed_signers": ".github/release-allowed-signers",
"assets": {
"archive": "agent-runtime-v0.1.3-source.tar.gz",
"sbom": "agent-runtime-v0.1.3.spdx.json",
"notes": "release-notes-v0.1.3.md",
"manifest": "release-manifest-v0.1.3.json",
"archive": "agent-runtime-v0.2.0-source.tar.gz",
"sbom": "agent-runtime-v0.2.0.spdx.json",
"notes": "release-notes-v0.2.0.md",
"manifest": "release-manifest-v0.2.0.json",
"checksums": "SHA256SUMS"
},
"limits": {
Expand Down
2 changes: 1 addition & 1 deletion schema_parity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestSchemaAndLicenseParity(t *testing.T) {
if governance["properties"].(map[string]any)["schema_version"].(map[string]any)["const"] != "v1alpha1" {
t.Fatal("repository governance schema version drift")
}
if releaseContract["properties"].(map[string]any)["version"].(map[string]any)["const"] != "v0.1.3" || releaseManifest["properties"].(map[string]any)["schema_version"].(map[string]any)["const"] != "v1alpha1" {
if releaseManifest["properties"].(map[string]any)["schema_version"].(map[string]any)["const"] != "v1alpha1" {
t.Fatal("release schema identity drift")
}
buildResultProperties := releaseBuildResult["properties"].(map[string]any)
Expand Down
2 changes: 1 addition & 1 deletion schemas/release-build-result-v1alpha1.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"properties": {
"schema_version": {"const": "v1alpha1"},
"artifact_root": {"type": "string", "minLength": 1},
"version": {"const": "v0.1.3"},
"version": {"const": "v0.2.0"},
"source_commit": {"type": "string", "pattern": "^[0-9a-f]{40}$"},
"module_path": {"const": "github.com/NDDev-it-com/agent-runtime"},
"license": {"const": "AGPL-3.0-only"},
Expand Down
12 changes: 6 additions & 6 deletions schemas/release-contract-v1alpha1.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,24 @@
"required": ["schema_version", "version", "module_path", "go_compatibility", "license", "dependencies", "graph_only_modules", "source_commit", "archive_prefix", "workflow", "allowed_signers", "assets", "limits", "actions"],
"properties": {
"schema_version": {"const": "v1alpha1"},
"version": {"const": "v0.1.3"},
"version": {"const": "v0.2.0"},
"module_path": {"const": "github.com/NDDev-it-com/agent-runtime"},
"go_compatibility": {"const": "1.25"},
"license": {"const": "AGPL-3.0-only"},
"dependencies": {"type": "array", "minItems": 8, "maxItems": 8, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["module_path", "version", "license"], "properties": {"module_path": {"enum": ["github.com/ProtonMail/go-crypto", "github.com/cloudflare/circl", "github.com/goccy/go-yaml", "github.com/santhosh-tekuri/jsonschema/v6", "golang.org/x/crypto", "golang.org/x/mod", "golang.org/x/sys", "golang.org/x/text"]}, "version": {"type": "string", "pattern": "^v[0-9]+\\.[0-9]+\\.[0-9]+$"}, "license": {"enum": ["Apache-2.0", "BSD-3-Clause", "MIT"]}, "indirect": {"type": "boolean"}}}},"graph_only_modules": {"type": "array", "minItems": 0, "maxItems": 64, "uniqueItems": true, "items": {"type": "object", "additionalProperties": false, "required": ["module_path", "version", "license"], "properties": {"module_path": {"enum": ["github.com/dlclark/regexp2"]}, "version": {"type": "string", "pattern": "^v[0-9]+\\.[0-9]+\\.[0-9]+$"}, "license": {"enum": ["Apache-2.0", "BSD-3-Clause", "MIT"]}, "indirect": {"type": "boolean"}}}},
"source_commit": {"const": "HEAD"},
"archive_prefix": {"const": "agent-runtime-v0.1.3/"},
"archive_prefix": {"const": "agent-runtime-v0.2.0/"},
"workflow": {"const": ".github/workflows/release.yml"},
"allowed_signers": {"const": ".github/release-allowed-signers"},
"assets": {
"type": "object",
"additionalProperties": false,
"required": ["archive", "sbom", "notes", "manifest", "checksums"],
"properties": {
"archive": {"const": "agent-runtime-v0.1.3-source.tar.gz"},
"sbom": {"const": "agent-runtime-v0.1.3.spdx.json"},
"notes": {"const": "release-notes-v0.1.3.md"},
"manifest": {"const": "release-manifest-v0.1.3.json"},
"archive": {"const": "agent-runtime-v0.2.0-source.tar.gz"},
"sbom": {"const": "agent-runtime-v0.2.0.spdx.json"},
"notes": {"const": "release-notes-v0.2.0.md"},
"manifest": {"const": "release-manifest-v0.2.0.json"},
"checksums": {"const": "SHA256SUMS"}
}
},
Expand Down