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
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
{
"name": "agentic-engineering",
"description": "The autonomous engineering system for repository portfolios — engineer, read-only surveyor, and meta-engineer agents; portfolio, product, spend, and improvement workflows; cross-tool instruction architecture and skill discovery; configured by the consumer AGENTS.md",
"version": "6.1.0",
"version": "6.1.1",
"source": "./plugins/agentic-engineering"
},
{
Expand Down
2 changes: 1 addition & 1 deletion .github/plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
{
"name": "agentic-engineering",
"description": "The autonomous engineering system for repository portfolios — engineer, read-only surveyor, and meta-engineer agents; portfolio, product, spend, and improvement workflows; cross-tool instruction architecture and skill discovery; configured by the consumer AGENTS.md",
"version": "6.1.0",
"version": "6.1.1",
"source": "./plugins/agentic-engineering"
},
{
Expand Down
2 changes: 1 addition & 1 deletion plugins/agentic-engineering/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "agentic-engineering",
"description": "The autonomous engineering system for repository portfolios — engineer, read-only surveyor, and meta-engineer agents; portfolio, product, spend, and improvement workflows; cross-tool instruction architecture and skill discovery; configured by the consumer AGENTS.md",
"version": "6.1.0",
"version": "6.1.1",
"author": {
"name": "devantler-tech",
"url": "https://github.com/devantler-tech"
Expand Down
5 changes: 4 additions & 1 deletion plugins/agentic-engineering/AUTONOMY.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ and independently verify their hashes, scope and verdict before using this adapt
does not parse the referenced calculator output or compute its measurements. Incomplete, unknown,
future, foreign or unbound assertions yield a hold rather than replacement support.

A bound failure remains negative after expiry. Unknown observations never establish support or its loss. Loss of current evidence or runtime support can
A bound runtime failure remains negative even if its counterpart is missing or future-dated, and
a bound failure remains negative after expiry. Both runtime reports must be complete for replacement
support. Protected requests retain only the matching incumbent; foreign scope or an unsupported
current revision produces no recommendation. Unknown observations never establish support or its loss. Loss of current evidence or runtime support can
recommend contraction when the candidate is current and scoped recovery is reported tested and
already authorized. Pre-experiment and future observations cannot establish that loss. Missing
recovery readiness yields a hold with the recovery owner; no fallback command is run.
Expand Down
6 changes: 6 additions & 0 deletions plugins/agentic-engineering/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
new one before re-enabling unattended writes. Stopping early resumes writes with the retired FinOps
schedule still armed, or with a schedule pointing at an entrypoint that no longer resolves.

## 6.1.1 — 2026-10-04

**Fixed** — autonomy assessments require distinct stage records, bind protected requests before
retaining the incumbent, and preserve independently bound runtime failures when their counterpart
report is incomplete. Recommendations remain advisory and never admit execution or run recovery.

## 6.1.0 — 2026-10-04

**Added** — optional offline autonomy assessments join consumer classifications, exact capability
Expand Down
2 changes: 1 addition & 1 deletion plugins/agentic-engineering/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "agentic-engineering",
"description": "The autonomous engineering system for repository portfolios — engineer, read-only surveyor, and meta-engineer agents; portfolio, product, spend, and improvement workflows; cross-tool instruction architecture and skill discovery; configured by the consumer AGENTS.md",
"version": "6.1.0",
"version": "6.1.1",
"author": {
"name": "devantler-tech",
"url": "https://github.com/devantler-tech"
Expand Down
27 changes: 17 additions & 10 deletions plugins/agentic-engineering/scripts/autonomy-contract-go/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,10 +316,16 @@ func assess(in Input, now time.Time) Result {
if c.Owner.Kind != "human" || !exact(c.Owner.ID) || !exact(c.Owner.Record) || !exact(c.ClassificationRecord) || !scopeValid(c.Scope) || !bindingsValid(c.Bindings) || !exact(c.RecoveryOwner) || c.Fallback != c.Bindings.Baseline || !unique(c.Protected) || !covers(c.Protected, domains) || !unique(c.RequiredEvidence) || !covers(c.RequiredEvidence, kinds) || !unique(c.RequiredOutcomes) || !unique(c.ProtectedOutcomes) || !covers(c.RequiredOutcomes, c.ProtectedOutcomes) || !unique(c.RequiredPaths) || (c.Classification != "protected" && c.Classification != "replaceable-default") {
return finish("INVALID", "", "consumer classification, ownership, scope, required facts or fallback is incomplete")
}
if !scopeValid(in.Request.Scope) || !scopeEqual(c.Scope, in.Request.Scope) || in.Request.Bindings != c.Bindings || (in.Request.Current != c.Bindings.Baseline && in.Request.Current != c.Bindings.Candidate) {
return finish("HOLD", "", "request scope or immutable provenance does not match")
}
if c.Classification == "protected" {
return finish("RETAIN_DEFAULT", in.Request.Current, "protected method cannot be replaced by this assessment")
if in.Request.Current != c.Bindings.Baseline {
return finish("HOLD", "", "protected request does not name the incumbent")
}
return finish("RETAIN_DEFAULT", c.Bindings.Baseline, "protected method cannot be replaced by this assessment")
}
if !scopeValid(in.Request.Scope) || !scopeEqual(c.Scope, in.Request.Scope) || in.Request.Bindings != c.Bindings || !scopeValid(p.Scope) || !scopeEqual(c.Scope, p.Scope) || p.Bindings != c.Bindings || (in.Request.Current != c.Bindings.Baseline && in.Request.Current != c.Bindings.Candidate) {
if !scopeValid(p.Scope) || !scopeEqual(c.Scope, p.Scope) || p.Bindings != c.Bindings {
return finish("HOLD", "", "capability, scope or immutable provenance does not match")
}
// Only observations bound to the declared experiment can establish support or its loss.
Expand All @@ -335,11 +341,13 @@ func assess(in Input, now time.Time) Result {
expired := assessmentBound && a.Result != "unknown" && !ae.After(now)
complete := assessmentBound && a.Result == "pass" && ae.After(now)
ids, observedKinds := map[string]bool{}, []string{}
records := map[string]bool{}
for _, e := range p.Evidence {
if !reportValid(e) || ids[e.ID] || !contains(c.RequiredEvidence, e.Kind) || e.Result == "intercepted" || len(e.Paths) != 0 {
if !reportValid(e) || ids[e.ID] || records[e.Record] || !contains(c.RequiredEvidence, e.Kind) || e.Result == "intercepted" || len(e.Paths) != 0 {
return finish("INVALID", "", "ambiguous or invalid proof evidence")
}
ids[e.ID] = true
records[e.Record] = true
observedKinds = append(observedKinds, e.Kind)
o, _ := stamp(e.Observed)
ex, _ := stamp(e.Expires)
Expand Down Expand Up @@ -375,16 +383,15 @@ func assess(in Input, now time.Time) Result {
complete = false
}
}
runtimeBound := planBound && scopeValid(r.Scope) && scopeEqual(c.Scope, r.Scope) && r.Revision == c.Bindings.Runtime && unique(r.Paths) && covers(r.Paths, c.RequiredPaths) && reportValid(r.Positive) && reportValid(r.Negative) && r.Positive.ID != r.Negative.ID && r.Positive.Record != r.Negative.Record && r.Positive.Kind == "runtime" && r.Negative.Kind == "runtime" && unique(r.Positive.Paths) && unique(r.Negative.Paths) && covers(r.Positive.Paths, c.RequiredPaths) && covers(r.Negative.Paths, c.RequiredPaths)
for _, e := range []Report{r.Positive, r.Negative} {
runtimeScopeBound := planBound && scopeValid(r.Scope) && scopeEqual(c.Scope, r.Scope) && r.Revision == c.Bindings.Runtime && unique(r.Paths) && covers(r.Paths, c.RequiredPaths)
reportBound := func(e Report) bool {
o, ok := stamp(e.Observed)
if !ok || o.After(now) || o.Before(started) {
runtimeBound = false
}
return runtimeScopeBound && reportValid(e) && e.Kind == "runtime" && unique(e.Paths) && covers(e.Paths, c.RequiredPaths) && ok && !o.After(now) && !o.Before(started)
}
runtimeBound := reportBound(r.Positive) && reportBound(r.Negative) && r.Positive.ID != r.Negative.ID && r.Positive.Record != r.Negative.Record
runtimeReady := runtimeBound && r.Positive.Result == "pass" && r.Negative.Result == "intercepted" && fresh(r.Positive.Observed, r.Positive.Expires, now) && fresh(r.Negative.Observed, r.Negative.Expires, now)
if runtimeBound {
for _, e := range []Report{r.Positive, r.Negative} {
for _, e := range []Report{r.Positive, r.Negative} {
if reportBound(e) {
ex, _ := stamp(e.Expires)
if e.Result == "fail" {
failed = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,83 @@ func TestAssess(t *testing.T) {
}
}

func TestBoundRecommendations(t *testing.T) {
now := time.Date(2026, 10, 4, 0, 0, 0, 0, time.UTC)
baseline, candidate := strings.Repeat("4", 64), strings.Repeat("5", 64)
cases := []struct {
name, status, revision string
change func(map[string]any)
}{
{"distinct stage records", "RECOMMEND_CANDIDATE", candidate, func(m map[string]any) {}},
{"reused stage record", "INVALID", "", func(m map[string]any) {
for _, e := range nested(m, "observation", "proof")["evidence"].([]any) {
e.(map[string]any)["record"] = "artifact://one-report"
}
}},
{"protected incumbent", "RETAIN_DEFAULT", baseline, func(m map[string]any) { nested(m, "contract")["candidateClassification"] = "protected" }},
{"protected foreign scope", "HOLD", "", func(m map[string]any) {
nested(m, "contract")["candidateClassification"] = "protected"
nested(m, "request", "scope")["repository"] = "devantler-tech/foreign"
}},
{"protected unknown current", "HOLD", "", func(m map[string]any) {
nested(m, "contract")["candidateClassification"] = "protected"
nested(m, "request")["currentRevision"] = strings.Repeat("9", 64)
}},
{"protected candidate is not incumbent", "HOLD", "", func(m map[string]any) {
nested(m, "contract")["candidateClassification"] = "protected"
nested(m, "request")["currentRevision"] = candidate
}},
{"failure without counterpart", "RECOMMEND_CONTRACTION", baseline, func(m map[string]any) {
nested(m, "request")["currentRevision"] = candidate
nested(m, "observation", "runtime", "positive")["result"] = "fail"
delete(nested(m, "observation", "runtime"), "interceptedNegative")
}},
{"failure with future counterpart", "RECOMMEND_CONTRACTION", baseline, func(m map[string]any) {
nested(m, "request")["currentRevision"] = candidate
nested(m, "observation", "runtime", "positive")["result"] = "fail"
nested(m, "observation", "runtime", "interceptedNegative")["observedAt"] = "2026-10-05T00:00:00Z"
nested(m, "observation", "runtime", "interceptedNegative")["expiresAt"] = "2026-10-06T00:00:00Z"
}},
{"negative failure without positive", "RECOMMEND_CONTRACTION", baseline, func(m map[string]any) {
nested(m, "request")["currentRevision"] = candidate
nested(m, "observation", "runtime", "interceptedNegative")["result"] = "fail"
delete(nested(m, "observation", "runtime"), "positive")
}},
{"foreign failure", "HOLD", "", func(m map[string]any) {
nested(m, "request")["currentRevision"] = candidate
nested(m, "observation", "runtime", "positive")["result"] = "fail"
nested(m, "observation", "runtime", "scope")["repository"] = "devantler-tech/foreign"
delete(nested(m, "observation", "runtime"), "interceptedNegative")
}},
{"future failure", "HOLD", "", func(m map[string]any) {
nested(m, "request")["currentRevision"] = candidate
p := nested(m, "observation", "runtime", "positive")
p["result"] = "fail"
p["observedAt"] = "2026-10-05T00:00:00Z"
p["expiresAt"] = "2026-10-06T00:00:00Z"
delete(nested(m, "observation", "runtime"), "interceptedNegative")
}},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
m := inputFixture(t)
tc.change(m)
raw, _ := json.Marshal(m)
in, err := decode(strings.NewReader(string(raw)))
if err != nil {
t.Fatal(err)
}
got := assess(in, now)
if got.Status != tc.status || got.RecommendedRevision != tc.revision {
t.Fatalf("got %+v, want %s/%s", got, tc.status, tc.revision)
}
if got.ExecutionAdmitted || got.MutationPerformed || got.ReportedEvidenceAuthenticated {
t.Fatal("assessment became authority")
}
})
}
}

func TestDecode(t *testing.T) {
for _, raw := range []string{fixture + fixture, `{"schemaVersion":1,"schemaVersion":1}`, `{"schemaVersion":1,"schem\u0061Version":1}`, `{"schemaVersion":1,"executionAdmitted":true}`, `null`, `[]`, "{", strings.Repeat(" ", 1<<20) + fixture, string([]byte{'{', '"', 'x', '"', ':', '"', 0xff, '"', '}'})} {
if _, err := decode(strings.NewReader(raw)); err == nil {
Expand Down
Loading