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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Versioning.

## [Unreleased]

- Observe installed Devin CLI as the eighth catalogue identity while retaining
seven verified execution adapters. Bind per-mapping runtime evidence policy
and refuse unproven Devin configuration projections or runtime-proof claims.

- Converge the ci-workflows reusable callers on the signed 0.1.26 tag
(`a7b90bd`); the `gds-ci` projection pin moves through its canonical
`ci.workflow_ref` input.
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ also runs the source-bound 2000-repository assurance scenario and requires
current source evidence before any artifact can be attested.

It does **not** prove harness runtime behaviour, and no longer claims to. The
seven harnesses are registered here with delegated runtime evidence; their
seven execution adapters are registered here with delegated runtime evidence; their
runtime suites live in the private `NDDev-it-com/setup-systems` repository,
which `harnesses/module-bridge.yaml` names as the evidence owner. Each profile
records `runtime_tests.last_result: delegated`, and
Expand All @@ -102,4 +102,8 @@ claiming `delegated` that the bridge does not map is rejected
evidence here nor delegates it (`GDS_HARNESS_RUNTIME_UNOWNED`). Promoting a
harness to `supported` still requires a local `pass`.

The eighth catalogue identity, Devin, is installed-only and provisional. GDS
observes its version but neither configures it nor claims model/runtime proof.
Its bootstrap mapping explicitly declares unproven evidence (ADR 0041).

Architecture and contracts are in `docs/architecture/` and `docs/contracts/`.
70 changes: 70 additions & 0 deletions core/harness/devin_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package harness

import (
"context"
"os"
"path/filepath"
"testing"

"github.com/NDDev-OpenNetwork/github-device-sync/core/validation"
)

func TestDevinVersionDetectionDoesNotConfigureTheHarness(t *testing.T) {
root := repoRootForTest(t)
schemas, err := validation.NewSchemaSet()
if err != nil {
t.Fatal(err)
}
bin := t.TempDir()
program := filepath.Join(bin, "devin")
if err := os.WriteFile(program, []byte("#!/bin/sh\n[ \"$1\" = --version ] || exit 42\nprintf 'devin 1.2.3\\n'\n"), 0o755); err != nil {
t.Fatal(err)
}
t.Setenv("PATH", bin)
home := t.TempDir()
t.Setenv("HOME", home)
observation, findings := Detect(context.Background(), root, "devin", schemas)
if len(findings) != 0 || observation.Result != "observed" || observation.Version != "devin 1.2.3" {
t.Fatalf("Devin observation=%+v findings=%+v", observation, findings)
}
entries, err := os.ReadDir(home)
if err != nil || len(entries) != 0 {
t.Fatalf("version observation changed the home directory: %v %v", entries, err)
}
}

func TestDevinRegistryDoesNotClaimDelegatedProofOrInstallConfiguration(t *testing.T) {
root := repoRootForTest(t)
schemas, err := validation.NewSchemaSet()
if err != nil {
t.Fatal(err)
}
report, findings := ValidateStatic(root, "devin", schemas)
if len(findings) != 0 || report.CapabilityStatus != "provisional" || report.RuntimeEvidence != "not-proven" || report.RuntimeEvidenceOwner != "" {
t.Fatalf("unproven Devin capabilities were promoted: %+v %+v", report, findings)
}
adapter, findings := NewAdapter(root, "devin", schemas)
if len(findings) != 0 {
t.Fatal(findings)
}
target := t.TempDir()
_, findings = adapter.PlanInstall(target, RenderRequest{SkillProfile: "core", Scope: "project"})
if !containsHarnessFinding(findings, "GDS_HARNESS_PROJECT_SKILLS_NOT_PROVEN") {
t.Fatalf("observation-only Devin produced a configuration plan: %+v", findings)
}
entries, err := os.ReadDir(target)
if err != nil || len(entries) != 0 {
t.Fatalf("refused adapter plan changed the target: %v %v", entries, err)
}
}

func TestExplicitDevinRuntimeProofRemainsUnproven(t *testing.T) {
schemas, err := validation.NewSchemaSet()
if err != nil {
t.Fatal(err)
}
_, findings := Validate(repoRootForTest(t), "devin", schemas)
if !containsHarnessFinding(findings, "GDS_HARNESS_RUNTIME_UNOWNED") {
t.Fatalf("an explicit runtime request accepted an installed-only CLI: %+v", findings)
}
}
15 changes: 11 additions & 4 deletions core/harness/module_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ type ModuleBridgeDocument struct {
}

type ModuleHarnessMapping struct {
ModuleID string `json:"module_id"`
HarnessID string `json:"harness_id"`
Lifecycle string `json:"lifecycle"`
ModuleAliases []string `json:"module_aliases,omitempty"`
ModuleID string `json:"module_id"`
HarnessID string `json:"harness_id"`
Lifecycle string `json:"lifecycle"`
ModuleAliases []string `json:"module_aliases,omitempty"`
RuntimeEvidence string `json:"runtime_evidence,omitempty"`
}

type BridgeConsumer struct {
Expand Down Expand Up @@ -123,6 +124,12 @@ func validateModuleBridgeSemantics(
}
}
for _, mapping := range document.Mappings {
if mapping.RuntimeEvidence != "" && mapping.RuntimeEvidence != "delegated" && mapping.RuntimeEvidence != "not-proven" {
findings = append(findings, bridgeFinding(
"GDS_MODULE_BRIDGE_EVIDENCE_POLICY_INVALID", "Module mapping has an unknown runtime evidence policy.",
map[string]any{"harness_id": mapping.HarnessID, "runtime_evidence": mapping.RuntimeEvidence},
))
}
findings = append(findings,
claimBridgeIdentity(seenModule, mapping.ModuleID, mapping.ModuleID, "MODULE_ID")...,
)
Expand Down
13 changes: 12 additions & 1 deletion core/harness/module_bridge_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ func TestCanonicalModuleBridgeCoversEveryHarnessAndDigestsDeterministically(t *t
if changed == first.IdentityDigest {
t.Fatal("identity digest did not bind lifecycle identity")
}
mutated.Mappings[0].RuntimeEvidence = "not-proven"
changedEvidence, err := moduleBridgeIdentityDigest(mutated)
if err != nil || changedEvidence == changed {
t.Fatalf("identity digest did not bind runtime evidence policy: %s %v", changedEvidence, err)
}
}

func TestModuleBridgeIdentityDigestIgnoresOrderingButBindsIdentityDrift(t *testing.T) {
Expand Down Expand Up @@ -262,14 +267,20 @@ func TestSelectedRuntimeValidationReportsDelegationRatherThanSilentSuccess(t *te
if err != nil {
t.Fatal(err)
}
report, findings := ValidateSelected(root, CanonicalIDs, schemas)
report, findings := ValidateSelected(root, WorkPolicyActiveIDs, schemas)
if len(findings) != 0 {
t.Fatalf("findings = %#v", findings)
}
if len(report.Harnesses) != len(CanonicalIDs) {
t.Fatalf("harness count = %d, want %d", len(report.Harnesses), len(CanonicalIDs))
}
for _, item := range report.Harnesses {
if item.Harness == "devin" {
if item.RuntimeEvidence != "not-proven" || item.RuntimeEvidenceOwner != "" || item.CapabilityStatus != "provisional" {
t.Fatalf("installed-only Devin inherited execution proof: %+v", item)
}
continue
}
if item.RuntimeEvidence != "delegated" {
t.Fatalf("%s runtime evidence = %q, want delegated", item.Harness, item.RuntimeEvidence)
}
Expand Down
15 changes: 11 additions & 4 deletions core/harness/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ var CanonicalIDs = []string{
"claude-code",
"codex",
"cursor",
"devin",
"grok-build",
"opencode",
"pi",
}

// WorkPolicyActiveIDs is the global execution/release allowlist. It equals
// CanonicalIDs: every catalogued harness is delivered by a setup system, so
// there is no longer an on-pause remainder to separate.
// WorkPolicyActiveIDs is the execution/configuration allowlist. The catalogue
// also includes installed-only harnesses whose adapter behavior is not proven.
var WorkPolicyActiveIDs = []string{
"antigravity",
"claude-code",
Expand Down Expand Up @@ -209,7 +209,11 @@ func validateAll(
for _, alias := range entry.LegacyAliases {
report.Aliases[alias] = entry.ID
}
entryRuntime := includeRuntime && (selected == nil || selected[entry.ID])
// A mapping declaring installation-only coverage is observed statically
// in all-mode. An explicit runtime request for that identity remains
// unproven, rather than inheriting another harness's delegated proof.
entryRuntime := includeRuntime && (selected == nil || selected[entry.ID]) &&
(entry.RuntimeEvidence != "not-proven" || selected != nil && selected[entry.ID])
var item Report
var profile CapabilityProfile
var itemFindings []domain.Finding
Expand Down Expand Up @@ -324,6 +328,9 @@ func delegationIndex(bridge ModuleBridgeDocument) map[string]string {
}
index := make(map[string]string, len(bridge.Mappings))
for _, mapping := range bridge.Mappings {
if mapping.RuntimeEvidence == "not-proven" {
continue
}
index[mapping.HarnessID] = bridge.EvidenceOwner.Repository
}
return index
Expand Down
25 changes: 15 additions & 10 deletions core/harness/work_policy_test.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
package harness

import "testing"
import (
"slices"
"testing"
)

// The catalogue and the work-policy allowlist were once different sizes: ten
// catalogued harnesses had no setup system and were carried on-pause. Every
// catalogued harness is now delivered by one of the seven setup systems, so the
// two sets are identical and nothing can be catalogued-but-paused. A harness
// that is not in the catalogue is rejected as unknown, not as paused.
func TestWorkPolicyCatalogueEqualsActiveSeven(t *testing.T) {
if len(CanonicalIDs) != 7 || len(WorkPolicyActiveIDs) != 7 {
t.Fatalf("catalogue=%d active=%d, want 7 and 7", len(CanonicalIDs), len(WorkPolicyActiveIDs))
// seven execution adapters retain their proof requirements. An installed-only
// CLI may be observed without being selected for configuration or execution.
func TestWorkPolicyCatalogueIncludesObservedDevinAndActiveSeven(t *testing.T) {
if len(CanonicalIDs) != 8 || len(WorkPolicyActiveIDs) != 7 {
t.Fatalf("catalogue=%d active=%d, want 8 and 7", len(CanonicalIDs), len(WorkPolicyActiveIDs))
}
for index, id := range CanonicalIDs {
if WorkPolicyActiveIDs[index] != id {
t.Fatalf("catalogue and active set diverge at %d: %q vs %q", index, id, WorkPolicyActiveIDs[index])
for _, id := range WorkPolicyActiveIDs {
if !slices.Contains(CanonicalIDs, id) {
t.Fatalf("active identity %q is not catalogued", id)
}
}
if findings := ValidateDeviceSelection([]string{"devin"}); len(findings) != 1 || findings[0].Code != "GDS_DEVICE_HARNESS_PAUSED" {
t.Fatalf("observation-only Devin must not be selected as a configured adapter: %+v", findings)
}
findings := ValidateDeviceSelection([]string{"codex", "zcode"})
if len(findings) != 1 || findings[0].Code != "GDS_HARNESS_SELECTED_UNKNOWN" ||
findings[0].Evidence["harness"] != "zcode" {
Expand Down
33 changes: 33 additions & 0 deletions docs/adr/0041-installed-harnesses-and-execution-adapters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# ADR 0041: Installed harnesses and execution adapters

Status: Accepted

Date: 2026-10-08

Supersedes: ADR 0037 (the exact catalogue membership only)

## Context

Devin CLI is distributed by the public bootstrap, but GDS rejected its identity
as unknown. Registering an installed program must not imply that its skill,
instruction, hook, model or configuration behavior has passed adapter tests.

## Decision

- The canonical catalogue includes eight identities. Devin is provisional and
supports bounded version observation; its runtime evidence is `not-proven`.
- The seven verified execution adapters remain in `WorkPolicyActiveIDs`.
Selecting Devin for adapter synchronization reports `installed-paused`.
- The Devin module bridge maps to `macos-ubuntu-bootstrap` and explicitly
declares `runtime_evidence: not-proven`. This mapping does not inherit the
setup-systems runtime evidence owner.
- Default registry-wide validation retains the observation-only entry without
promoting it. An explicit request for Devin runtime proof remains unproven.
- Adapter installation refuses unproven project skill paths. Version detection
performs no model call and creates no vendor configuration.

## Verification

Synthetic version observation, empty-target adapter refusal, explicit runtime
proof refusal and registry/work-policy separation are exercised in Go tests.
The module bridge digest binds the per-mapping evidence policy.
1 change: 1 addition & 0 deletions docs/adr/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ clause stops being normative.

| ADR | Title | Status | Supersedes | Superseded by |
|---|---|---|---|---|
| [0041](0041-installed-harnesses-and-execution-adapters.md) | Installed harnesses and execution adapters | Accepted | ADR 0037 | — |
| [0040](0040-tenancy-is-the-provider-account.md) | Tenancy is the provider account | Accepted | — | — |
| [0039](0039-repo-scoped-session-evidence.md) | Repo-scoped session evidence | Accepted | — | — |
| [0038](0038-release-identity-carries-no-channel.md) | Release identity carries no channel | Accepted | ADR 0016 | — |
Expand Down
1 change: 1 addition & 0 deletions docs/contracts/harness-adapters-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ antigravity
claude-code
codex
cursor
devin
grok-build
opencode
pi
Expand Down
12 changes: 7 additions & 5 deletions harnesses/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# Harness capability registry

`capability-registry.yaml` is the canonical index for the seven agent harnesses
this estate installs, one per setup system in `NDDev-OpenNetwork`. Each profile
records only current official documentation facts.
`capability-registry.yaml` is the canonical index for eight harness identities.
Seven have execution adapters delivered by setup systems. Devin is registered
for bounded installed-version observation through the public bootstrap.

The catalogue and the work-policy allowlist are the same set, so nothing can be
catalogued but paused. ADR 0037 records why the catalogue is seven.
The execution/configuration allowlist remains the seven proven adapters.
Devin is provisional and cannot install a GDS configuration projection.
ADR 0041 records this separation; ADR 0037 retains the historical decision.

Canonical harness identities are:

Expand All @@ -14,6 +15,7 @@ Canonical harness identities are:
- `claude-code`;
- `codex`;
- `cursor`;
- `devin`;
- `grok-build`;
- `opencode`;
- `pi`.
Expand Down
9 changes: 7 additions & 2 deletions harnesses/capability-registry.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ harnesses:



- id: "devin"
status: "provisional"
profile: "harnesses/devin/profile.yaml"
verified_at: "2026-10-08"
runtime_evidence: "not-proven"
legacy_aliases: []

- id: "grok-build"
status: "supported"
profile: "harnesses/grok-build/profile.yaml"
Expand All @@ -59,5 +66,3 @@ harnesses:
runtime_evidence: "delegated"
legacy_aliases: []



34 changes: 34 additions & 0 deletions harnesses/devin/profile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
schema_version: 1

harness_profile:
id: "devin"
product: "devin"
status: "provisional"
aliases: []
capability_version: "2026-10-08"
verified_at: "2026-10-08"
official_sources:
- "https://docs.devin.ai/cli"
- "https://docs.devin.ai/cli/extensibility"
detection:
command_candidates: ["devin"]
version_arguments: ["--version"]
instructions:
native_agents: true
nested_chain: "custom"
imports: true
skills:
standard: "none"
native_paths: []
symlinks: false
explicit_only:
mechanism: "not-proven"
projection:
instruction_strategy: "not-proven"
skill_strategy: "not-proven"
hooks:
supported: false
lifecycle: []
runtime_tests:
required: false
last_result: "not-proven"
6 changes: 5 additions & 1 deletion harnesses/module-bridge.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ evidence_owner:
runtime_tests:
required: false

# Seven harnesses, seven setup systems, one mapping each. The retired harness
# Seven execution adapters and one installed-only CLI, one mapping each. The retired harness
# application line is archived and is deliberately not named in this file --
# not as a module, not as an alias. A bridge is a statement about what exists;
# ADR 0037 holds the history.
Expand All @@ -30,6 +30,10 @@ mappings:
- module_id: "cursor-setup-system"
harness_id: "cursor"
lifecycle: "active"
- module_id: "macos-ubuntu-bootstrap"
harness_id: "devin"
lifecycle: "active"
runtime_evidence: "not-proven"
- module_id: "grok-setup-system"
harness_id: "grok-build"
lifecycle: "active"
Expand Down
Loading
Loading