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
9 changes: 4 additions & 5 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
GENERATED FILE - DO NOT EDIT DIRECTLY
generator: gds
bundle: 0.1.0-dev
source-commit: 06dd4355b03d600bbf40eee21e86fb9e424d42c5
input-digest: sha256:229eda43354f1690ccec8d8070eb8392b3072c1ab9ff80b451ce500a5d8867cb
output-digest: sha256:8e2e6d165d8bdeca5c3f47f18ebd2a8778bf3e9f7979d468b988019506c89d6b
source-commit: 7120d79f77124632c6cf355bca27598c120c1182
input-digest: sha256:24879f858628a87b9316a2f7a91d090c53b39723491abc207f8dec44d4eaab95
output-digest: sha256:d63e25cbe4ea712b5562cc5e7c663ba33a6ca21a6f299c25d4cff88636a55c18
edit-source:
- .gds/repository.yaml
- policies/base/repository-default.yaml
Expand Down Expand Up @@ -42,8 +42,7 @@ edit-source:

## Verification commands

- No repository-owned verification command is declared; report it as
`NOT_PROVEN`.
- Test: `python3 cli-tools/validate_public_contracts.py`.

## Claude workflow routing

Expand Down
14 changes: 7 additions & 7 deletions .gds/bundle.lock.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ bundle:
version: "0.1.0-dev"
release_sequence: 0
channel: "development"
source_commit: "06dd4355b03d600bbf40eee21e86fb9e424d42c5"
digest: "sha256:82c50767f8891f2235905270a8f3f98fa10f56a2d5aac1db768f3f8b522606b7"
source_commit: "7120d79f77124632c6cf355bca27598c120c1182"
digest: "sha256:7dd8c40b344edf75b465f692dc44340b1dda8a187a5326fe703aef0aabeeb1c1"

projection:
input_digest: "sha256:229eda43354f1690ccec8d8070eb8392b3072c1ab9ff80b451ce500a5d8867cb"
output_digest: "sha256:701ff062593f8e74e75e290c12ab20bee00aed5cf63195d5df7f783b8194d000"
input_digest: "sha256:24879f858628a87b9316a2f7a91d090c53b39723491abc207f8dec44d4eaab95"
output_digest: "sha256:3456bc3372b26a41206804d6cf4dbf39cb57b84ebf16682871b08e02dda4039c"
files:
- path: ".claude/CLAUDE.md"
digest: "sha256:b62ac7223e22c7618e349f85c069993e529796af30b925182c04d25e7aaecc30"
digest: "sha256:bc7c9a870bfdb8b6cd6d32935cbe793ef4365600fdcd0a5b49d910f547c2536c"
- path: ".gds/compiled-policy.json"
digest: "sha256:226b256afbe7b17f854ee3260e5d7a858cbb67f478c94525ceb7a656fa473f08"
digest: "sha256:eeb034a7afa169596f397691f12b9f08b8a963e72f1c07d8db08dc9f746cc023"
- path: "AGENTS.md"
digest: "sha256:24a10b8af5fc20a4e5209b768c6c78dfd07c96b3a6028e2aff159abf18ed32ea"
digest: "sha256:e976a2bd9f616aa5a2ba101272b0f64f8e28012f51880717898244555843d380"
54 changes: 5 additions & 49 deletions .gds/compiled-policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"compiled_policy": {
"repository_id": "repo_01KX8PR71HN6XNJ3VN5SQCB0TF",
"bundle_version": "0.1.0-dev",
"digest": "sha256:5fca177339e8c6da97053eda3688758a6d039a08d03a93f56a1c97ee47abe6e1"
"digest": "sha256:55be68d3e3e69c161c90a16276a2617faef824083296d4300fc20d3eb1fb90c5"
},
"sources": [
{
Expand All @@ -12,7 +12,7 @@
"priority": 100,
"distribution": "public",
"path": "policies/base/repository-default.yaml",
"digest": "sha256:90d112ae49f4c44ebce3b749d543660548214061128926d3d6d11ba02827a414"
"digest": "sha256:5075e944793d13e6c506da09f136214872a40c5b91eabb06fae09d0993631649"
},
{
"id": "organization-default",
Expand Down Expand Up @@ -50,26 +50,17 @@
"github": {
"actions": {
"allowed_actions": {
"management": "managed",
"value": "selected"
"management": "observed"
},
"enabled": {
"management": "managed",
"value": true
},
"selected_actions": {
"management": "managed",
"value": {
"github_owned_allowed": true,
"patterns_allowed": [
"NDDev-it-com/nddev-ci-workflows/.github/workflows/*@*"
],
"verified_allowed": false
}
"management": "observed"
},
"sha_pinning_required": {
"management": "managed",
"value": true
"management": "observed"
}
},
"merge": {
Expand Down Expand Up @@ -198,13 +189,6 @@
"file": "policies/base/repository-default.yaml",
"operation": "set"
},
"/effective/github/actions/allowed_actions/value": {
"source": "repository-default",
"tier": "base",
"priority": 100,
"file": "policies/base/repository-default.yaml",
"operation": "set"
},
"/effective/github/actions/enabled/management": {
"source": "repository-default",
"tier": "base",
Expand All @@ -226,41 +210,13 @@
"file": "policies/base/repository-default.yaml",
"operation": "set"
},
"/effective/github/actions/selected_actions/value/github_owned_allowed": {
"source": "repository-default",
"tier": "base",
"priority": 100,
"file": "policies/base/repository-default.yaml",
"operation": "set"
},
"/effective/github/actions/selected_actions/value/patterns_allowed/0": {
"source": "repository-default",
"tier": "base",
"priority": 100,
"file": "policies/base/repository-default.yaml",
"operation": "set"
},
"/effective/github/actions/selected_actions/value/verified_allowed": {
"source": "repository-default",
"tier": "base",
"priority": 100,
"file": "policies/base/repository-default.yaml",
"operation": "set"
},
"/effective/github/actions/sha_pinning_required/management": {
"source": "repository-default",
"tier": "base",
"priority": 100,
"file": "policies/base/repository-default.yaml",
"operation": "set"
},
"/effective/github/actions/sha_pinning_required/value": {
"source": "repository-default",
"tier": "base",
"priority": 100,
"file": "policies/base/repository-default.yaml",
"operation": "set"
},
"/effective/github/merge/allow_auto_merge/management": {
"source": "repository-default",
"tier": "base",
Expand Down
7 changes: 7 additions & 0 deletions .gds/repository.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ git:
handoff_pr: "preferred"
cleanup: "merged-only"

verification:
commands:
test:
- "python3 cli-tools/validate_public_contracts.py"
required:
- "test"

agent:
context_profile: "public-module"
generated_agents: true
Expand Down
86 changes: 68 additions & 18 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,24 +147,42 @@ jobs:
import sys

EVIDENCE_PATH = "build/release-evidence.json"
REQUIRED_LANES = (
"fast",
"release",
"platform:macos",
"platform:ubuntu",
"benchmark:macos",
"benchmark:ubuntu",
)
SHA256 = re.compile(r"sha256:[0-9a-f]{64}")

def fail(message):
print(f"::error::{message}", file=sys.stderr)
raise SystemExit(1)

def parse_utc(value):
if not isinstance(value, str) or not value.endswith("Z"):
return None
try:
parsed = dt.datetime.fromisoformat(value.replace("Z", "+00:00"))
except ValueError:
return None
return parsed if parsed.utcoffset() == dt.timedelta(0) else None

try:
evidence = json.loads(pathlib.Path(EVIDENCE_PATH).read_text(encoding="utf-8"))
except (OSError, json.JSONDecodeError) as exc:
fail(f"cannot read {EVIDENCE_PATH}: {exc}")
if not isinstance(evidence, dict):
fail("release-evidence must be a JSON object")
if evidence.get("schema_version") != 1:
fail("release-evidence schema_version must be 1")
if evidence.get("schema_version") != 2:
fail("release-evidence schema_version must be 2 (execution-bound)")
module = evidence.get("module")
if not isinstance(module, dict) or module.get("repository") != "NDDev-it-com/nddev-zcode-app":
fail("release-evidence.module.repository must be this repository")
digest = module.get("setup_digest")
if not isinstance(digest, str) or re.fullmatch(r"sha256:[0-9a-f]{64}", digest) is None:
if not isinstance(digest, str) or SHA256.fullmatch(digest) is None:
fail("release-evidence.module.setup_digest must be a sha256 content digest")

# Bind the recorded digest to the exact tagged content: hash every
Expand Down Expand Up @@ -201,19 +219,53 @@ jobs:
platforms = evidence.get("platforms")
if not isinstance(platforms, list) or not platforms:
fail("release-evidence.platforms must be a non-empty array")
checks = evidence.get("checks")
if not isinstance(checks, list) or not checks or not all(isinstance(item, str) and item for item in checks):
fail("release-evidence.checks must be a non-empty array of strings")

# Freshness: the bundle must be inside its validated window at tag time.
def parse_utc(value):
if not isinstance(value, str) or not value.endswith("Z"):
return None
try:
parsed = dt.datetime.fromisoformat(value.replace("Z", "+00:00"))
except ValueError:
return None
return parsed if parsed.utcoffset() == dt.timedelta(0) else None
promotion = evidence.get("promotion")
if not isinstance(promotion, dict) or promotion.get("decision") != "approved":
fail("release-evidence.promotion.decision must be approved; pending bundles cannot release")
approved_by = promotion.get("approved_by")
if not isinstance(approved_by, dict) or not str(approved_by.get("mechanism", "")).strip() or not str(approved_by.get("identity", "")).strip():
fail("release-evidence.promotion.approved_by must record mechanism and identity")

lanes = evidence.get("lanes")
if not isinstance(lanes, list):
fail("release-evidence.lanes must be an array of execution records")
seen = {}
for index, record in enumerate(lanes):
context = f"release-evidence.lanes[{index}]"
if not isinstance(record, dict):
fail(f"{context} must be an object")
if record.get("status") != "passed":
fail(f"{context}: status must be passed")
lane = str(record.get("lane", ""))
seen[lane] = seen.get(lane, 0) + 1
for key in ("workflow", "run_id", "runner", "toolchain", "platform"):
if not str(record.get(key, "")).strip():
fail(f"{context}: {key} must be a non-empty string")
if record.get("setup_digest") != digest:
fail(f"{context}: setup_digest does not match the bundle module digest")
if not isinstance(record.get("log_digest"), str) or SHA256.fullmatch(record["log_digest"]) is None:
fail(f"{context}: log_digest must be a sha256 digest")
started = parse_utc(record.get("started_at_utc"))
completed = parse_utc(record.get("completed_at_utc"))
if started is None or completed is None or started > completed:
fail(f"{context}: execution timestamps are missing or inverted")
for lane in REQUIRED_LANES:
if seen.get(lane, 0) != 1:
fail(f"release-evidence: lane {lane} must have exactly one passed execution record")
if set(seen) - set(REQUIRED_LANES):
fail("release-evidence: unknown lane records present")

observation = evidence.get("vendor_observation")
if not isinstance(observation, dict):
fail("release-evidence.vendor_observation must record the currentness check")
for key in ("source", "observed_latest_version", "event_date"):
if not str(observation.get(key, "")).strip():
fail(f"release-evidence.vendor_observation.{key} must be a non-empty string")
if parse_utc(observation.get("observed_at_utc")) is None:
fail("release-evidence.vendor_observation.observed_at_utc must be ISO-8601 UTC")
if not isinstance(observation.get("artifact_evidence_digest"), str) or SHA256.fullmatch(observation["artifact_evidence_digest"]) is None:
fail("release-evidence.vendor_observation.artifact_evidence_digest must be a sha256 digest")

generated_at = parse_utc(evidence.get("generated_at_utc"))
expires_at = parse_utc(evidence.get("expires_at_utc"))
Expand All @@ -227,9 +279,7 @@ jobs:
if now < generated_at:
fail("release-evidence.generated_at_utc is in the future")

if evidence.get("promotion", {}).get("decision") != "approved":
fail("release-evidence.promotion.decision must be approved")
print(f"ok: release-evidence bundle recomputed and consistent for {version_file}")
print(f"ok: execution-bound release-evidence verified for {version_file}")
BUNDLE

publish:
Expand Down
8 changes: 4 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
GENERATED FILE - DO NOT EDIT DIRECTLY
generator: gds
bundle: 0.1.0-dev
source-commit: 06dd4355b03d600bbf40eee21e86fb9e424d42c5
input-digest: sha256:229eda43354f1690ccec8d8070eb8392b3072c1ab9ff80b451ce500a5d8867cb
output-digest: sha256:e88382bea884b0476e6a65f5568a98aec71c43dc0544eecd2c2d882843fc6b18
source-commit: 7120d79f77124632c6cf355bca27598c120c1182
input-digest: sha256:24879f858628a87b9316a2f7a91d090c53b39723491abc207f8dec44d4eaab95
output-digest: sha256:e105b92a1cbdf280afc3902b666ffc347b1fa864a7644b85ffe5796d1de5c7b9
edit-source:
- .gds/repository.yaml
- policies/base/repository-default.yaml
Expand Down Expand Up @@ -40,7 +40,7 @@ edit-source:

## Development

- No repository-owned verification command is declared; report it as `NOT_PROVEN`.
- Test: `python3 cli-tools/validate_public_contracts.py`.

## Agent routing

Expand Down
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,31 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [2.1.3] - 2026-07-14

### Changed

- Verified ZCode runtime advanced to the official app 3.3.5 (build 3.3.5.3027,
released 2026-07-13): all six download artifacts re-pinned by independently
derived filename, byte size, and SHA-512; macOS bundle identity, Developer ID
signature, and notarization re-verified; Debian package version 3.3.5-3027;
embedded CLI remains 0.15.2 (rebuilt bundle, byte-identical across all six
artifacts).
- `build/release-evidence.json` upgraded to execution-bound schema version 2:
promotion starts as `pending` and becomes `approved` only from real per-lane
CI result records plus a vendor-currentness observation; approval is never a
default.

### Added

- `cli-tools/validate_public_contracts.py`: repository-owned public fast
verification (version lockstep, artifact identity shape, baseline
cross-references, marketplace/plugin catalog integrity) declared in
`.gds/repository.yaml` as the required test command.
- GDS generated projections (`AGENTS.md`, `.claude/CLAUDE.md`,
`.gds/bundle.lock.yaml`, `.gds/compiled-policy.json`) refreshed from bundle
source 7120d79.

### Added

- Machine-readable per-platform support tiers in
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ changes.
- **Author:** Danil Silantyev (github:rldyourmnd), CEO NDDev
- **License:** AGPL-3.0-or-later
- **Build version:** 2.1.2
- **Verified ZCode runtime:** app 3.3.4, CLI 0.15.2, model GLM-5.2
- **Verified ZCode runtime:** app 3.3.5, CLI 0.15.2, model GLM-5.2

## What this repository contains

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.1.2
2.1.3
2 changes: 1 addition & 1 deletion build/manifest.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nddev-zcode-app",
"build_version": "2.1.2",
"build_version": "2.1.3",
"source_root": "zcode_tools/marketplaces/",
"installer": "cli-tools/scripts/install.sh install --setup <id>",
"layout": {
Expand Down
Loading
Loading