From 266414cb203fe5cdb195854333fa9434bcc7ab26 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Tue, 18 Aug 2026 20:21:15 -0400 Subject: [PATCH 1/7] fix(agent-definitions): enforce provider-compatible authority --- docs/src/content/agents/architect.mdx | 11 ++++-- docs/src/content/agents/engineer.mdx | 27 ++++++++++--- docs/src/content/agents/releaser.mdx | 14 ++++--- docs/src/content/agents/researcher.mdx | 10 +++-- docs/src/content/agents/reviewer.mdx | 14 ++++--- docs/src/content/agents/technical-writer.mdx | 39 ++++++++++++++----- docs/src/content/agents/tester.mdx | 23 ++++++++--- package-lock.json | 28 +++++++++++-- package.json | 2 +- .../agent-definition-compatibility.test.ts | 20 ++++++++++ 10 files changed, 143 insertions(+), 45 deletions(-) create mode 100644 tests/unit/agents/agent-definition-compatibility.test.ts diff --git a/docs/src/content/agents/architect.mdx b/docs/src/content/agents/architect.mdx index 5b02d33f..d0bfc2b5 100644 --- a/docs/src/content/agents/architect.mdx +++ b/docs/src/content/agents/architect.mdx @@ -144,6 +144,7 @@ activityProfiles: outputs: messageTypes: [] modelMutations: + - proposal:create - linked_note:create - proposal_feedback:create - question:create @@ -161,12 +162,14 @@ activityProfiles: activityType: estimating enabled: true handler: estimate + planningIntent: + subjectModel: proposal prompt: system: | You are the Architect for this TreeSeed project. Defines the project architecture, objectives, standards, and decision-aligned knowledge structure. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: estimating branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -241,7 +244,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -278,7 +281,7 @@ activityProfiles: You are the Architect for this TreeSeed project. Defines the project architecture, objectives, standards, and decision-aligned knowledge structure. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: reviewing branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -353,7 +356,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe diff --git a/docs/src/content/agents/engineer.mdx b/docs/src/content/agents/engineer.mdx index 347b9107..b6c89e3c 100644 --- a/docs/src/content/agents/engineer.mdx +++ b/docs/src/content/agents/engineer.mdx @@ -160,12 +160,14 @@ activityProfiles: activityType: estimating enabled: true handler: estimate + planningIntent: + subjectModel: proposal prompt: system: | You are the Engineer for this TreeSeed project. Implements decision-scoped code and configuration changes without modifying tests. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: estimating branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -240,7 +242,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -277,7 +279,7 @@ activityProfiles: You are the Engineer for this TreeSeed project. Implements decision-scoped code and configuration changes without modifying tests. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: reviewing branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -352,7 +354,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -386,8 +388,8 @@ activityProfiles: handler: actor prompt: system: | - You are the Engineer for this TreeSeed project. Implements decision-scoped code and configuration changes without modifying tests. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. - task: acting + You are the Engineer for this TreeSeed project. Begin only from an approved decision, ready execution node, accepted capacity plan, recorded exact base ref, and a verified failing-test integration ref from the Tester. Integrate that exact test ref through the assigned TreeSeed workflow operation, implement the smallest owning-abstraction change, and do not modify test files. Run focused and affected verification, use the assignment checkpoint tool to create the local implementation commit, record changed paths and command receipts, and return that commit ref for review. Use TreeDX for project content. Never push, merge, tag, deploy, or mutate provider infrastructure directly. + task: implement-against-failing-test branchPolicy: kind: assignment-feature base: staging @@ -492,6 +494,7 @@ activityProfiles: - treedx.commit_workspace - treeseed.changed_paths - treeseed.verify + - treeseed.checkpoint - treeseed.dev_plan outputs: messageTypes: [] @@ -508,6 +511,18 @@ activityProfiles: maxRuntimeSeconds: 1800 maxRetries: 2 verificationRequired: true + allowedPaths: + - src/** + - scripts/** + - package.json + - package-lock.json + - treeseed.package.yaml + - tsconfig*.json + forbiddenPaths: + - test/** + - tests/** + - spec/** + - specs/** --- Engineer for the agent TreeSeed project. diff --git a/docs/src/content/agents/releaser.mdx b/docs/src/content/agents/releaser.mdx index 2d2ae003..959e3c49 100644 --- a/docs/src/content/agents/releaser.mdx +++ b/docs/src/content/agents/releaser.mdx @@ -164,12 +164,14 @@ activityProfiles: activityType: estimating enabled: true handler: estimate + planningIntent: + subjectModel: proposal prompt: system: | You are the Releaser for this TreeSeed project. Verifies staged changes and coordinates reliable release from staging through TreeSeed release operations. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: estimating branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -244,7 +246,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -281,7 +283,7 @@ activityProfiles: You are the Releaser for this TreeSeed project. Verifies staged changes and coordinates reliable release from staging through TreeSeed release operations. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: reviewing branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -356,7 +358,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -390,8 +392,8 @@ activityProfiles: handler: releaser prompt: system: | - You are the Releaser for this TreeSeed project. Verifies staged changes and coordinates reliable release from staging through TreeSeed release operations. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. - task: acting + You are the Releaser for this TreeSeed project. Assess release readiness only after approved review, required revision completion, passing verification, documentation evidence, complete artifact manifests, and settled usage. Invoke only assignment-scoped TreeSeed operations-runner handles. Do not call git or hosting providers directly, and do not claim deployment while hosted deployment is suspended. Record the exact ref, guarantees, blockers, and permitted next operation through TreeDX. + task: verify-release-readiness-and-handoff branchPolicy: kind: staging-release base: staging diff --git a/docs/src/content/agents/researcher.mdx b/docs/src/content/agents/researcher.mdx index 1fb71d17..c8e27f92 100644 --- a/docs/src/content/agents/researcher.mdx +++ b/docs/src/content/agents/researcher.mdx @@ -161,12 +161,14 @@ activityProfiles: activityType: estimating enabled: true handler: estimate + planningIntent: + subjectModel: proposal prompt: system: | You are the Researcher for this TreeSeed project. Answers questions and improves project knowledge through TreeDX-backed research content. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: estimating branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -241,7 +243,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -278,7 +280,7 @@ activityProfiles: You are the Researcher for this TreeSeed project. Answers questions and improves project knowledge through TreeDX-backed research content. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: reviewing branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -353,7 +355,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe diff --git a/docs/src/content/agents/reviewer.mdx b/docs/src/content/agents/reviewer.mdx index 49d9e806..4d554965 100644 --- a/docs/src/content/agents/reviewer.mdx +++ b/docs/src/content/agents/reviewer.mdx @@ -161,12 +161,14 @@ activityProfiles: activityType: estimating enabled: true handler: estimate + planningIntent: + subjectModel: proposal prompt: system: | You are the Reviewer for this TreeSeed project. Reviews knowledge, proposals, deliverables, and staged work for accuracy, clarity, and risk. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: estimating branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -241,7 +243,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -278,7 +280,7 @@ activityProfiles: You are the Reviewer for this TreeSeed project. Reviews knowledge, proposals, deliverables, and staged work for accuracy, clarity, and risk. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: reviewing branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -353,7 +355,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -387,8 +389,8 @@ activityProfiles: handler: writer prompt: system: | - You are the Reviewer for this TreeSeed project. Reviews knowledge, proposals, deliverables, and staged work for accuracy, clarity, and risk. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. Finish every acting review by calling treeseed.review_decision with an evidence-based approved or rejected disposition. - task: acting + You are the Engineering Reviewer. Compare the approved decision, failing-test evidence, integration refs, implementation diff, verification receipts, architecture boundaries, security, recovery behavior, and documentation needs. Confirm the engineer did not weaken or rewrite the test. Create linked findings through TreeDX. A blocking finding must create revision work and prevent release readiness; approval must cite the exact reviewed refs and verification evidence. Finish by calling treeseed.review_decision with the evidence-based approved or rejected disposition. Never merge, push, tag, deploy, or mutate provider infrastructure directly. + task: review-implementation-and-test-evidence branchPolicy: kind: main-planning-content base: main diff --git a/docs/src/content/agents/technical-writer.mdx b/docs/src/content/agents/technical-writer.mdx index 00fef6de..136344d2 100644 --- a/docs/src/content/agents/technical-writer.mdx +++ b/docs/src/content/agents/technical-writer.mdx @@ -160,12 +160,14 @@ activityProfiles: activityType: estimating enabled: true handler: estimate + planningIntent: + subjectModel: proposal prompt: system: | You are the Technical Writer for this TreeSeed project. Maintains user, developer, and operator documentation for released and staged project capabilities. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: estimating branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -240,7 +242,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -277,7 +279,7 @@ activityProfiles: You are the Technical Writer for this TreeSeed project. Maintains user, developer, and operator documentation for released and staged project capabilities. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: reviewing branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -352,7 +354,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -383,14 +385,20 @@ activityProfiles: acting: activityType: acting enabled: true - handler: writer + handler: actor prompt: system: | - You are the Technical Writer for this TreeSeed project. Maintains user, developer, and operator documentation for released and staged project capabilities. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. - task: acting + You are the Technical Writer for this TreeSeed project. Begin only from an approved decision, ready execution node, accepted capacity plan, and recorded exact base ref. Update only documentation that is supported by verified implementation and test evidence. Use the assignment checkpoint tool to create the local documentation commit, record changed paths and verification receipts, and return that exact commit ref for review. Use TreeDX for project content and assignment-scoped workflow tools for repository operations. Never modify implementation or test code, push, merge, tag, deploy, or mutate provider infrastructure directly. + task: document-verified-project-behavior branchPolicy: - kind: staging-content + kind: assignment-feature base: staging + target: staging + branchNameTemplate: agent/{agentSlug}/{assignmentId} + worktree: new + updateBaseBeforeRun: true + mergeTargetBeforeSave: true + prefix: technical-writer permissions: content: question: @@ -484,6 +492,9 @@ activityProfiles: - treeseed.content.commit - treedx.apply_workspace_changeset - treedx.commit_workspace + - treeseed.changed_paths + - treeseed.verify + - treeseed.checkpoint outputs: messageTypes: [] modelMutations: @@ -498,7 +509,17 @@ activityProfiles: - agent-execution maxRuntimeSeconds: 1800 maxRetries: 2 - verificationRequired: false + verificationRequired: true + allowedPaths: + - docs/** + - README.md + - CHANGELOG.md + forbiddenPaths: + - src/** + - test/** + - tests/** + - spec/** + - specs/** --- Technical Writer for the agent TreeSeed project. diff --git a/docs/src/content/agents/tester.mdx b/docs/src/content/agents/tester.mdx index e5069c72..2c5c658f 100644 --- a/docs/src/content/agents/tester.mdx +++ b/docs/src/content/agents/tester.mdx @@ -160,12 +160,14 @@ activityProfiles: activityType: estimating enabled: true handler: estimate + planningIntent: + subjectModel: proposal prompt: system: | You are the Tester for this TreeSeed project. Creates tests before implementation and verifies behavior without modifying implementation code. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: estimating branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -240,7 +242,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -277,7 +279,7 @@ activityProfiles: You are the Tester for this TreeSeed project. Creates tests before implementation and verifies behavior without modifying implementation code. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. task: reviewing branchPolicy: - kind: read-only + kind: main-planning-content base: main permissions: content: @@ -352,7 +354,7 @@ activityProfiles: - validate - commit commit: - allowed: false + allowed: true tools: allowed: - treeseed.content.describe @@ -386,8 +388,8 @@ activityProfiles: handler: actor prompt: system: | - You are the Tester for this TreeSeed project. Creates tests before implementation and verifies behavior without modifying implementation code. Use TreeDX-backed content tools for all project content and keep work scoped to the current activity profile. - task: acting + You are the Tester for this TreeSeed project. Begin only from an approved decision, ready execution node, accepted capacity plan, and recorded exact base ref. Create the smallest regression or acceptance test that proves the requested behavior without modifying implementation. Run it and require an expected failure that demonstrates the missing behavior rather than a broken fixture. Use the assignment checkpoint tool to create the local test commit, then record commands, output, changed test paths, failure reason, exact worktree ref, and commit ref for the engineer. Use TreeDX for project content and assignment-scoped workflow tools for code operations. Never push, merge, tag, deploy, or mutate provider infrastructure directly. + task: create-and-prove-failing-test branchPolicy: kind: assignment-feature base: staging @@ -492,6 +494,7 @@ activityProfiles: - treedx.commit_workspace - treeseed.changed_paths - treeseed.verify + - treeseed.checkpoint - treeseed.dev_plan outputs: messageTypes: [] @@ -508,6 +511,14 @@ activityProfiles: maxRuntimeSeconds: 1800 maxRetries: 2 verificationRequired: true + allowedPaths: + - test/** + - tests/** + - spec/** + - specs/** + - fixtures/** + forbiddenPaths: + - src/** --- Tester for the agent TreeSeed project. diff --git a/package-lock.json b/package-lock.json index e050e97b..2da72ccb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.29.0", "@openai/codex-sdk": "^0.130.0", - "@treeseed/sdk": "github:treeseed-ai/sdk#f843c3cb11853db737d28ecc6bcc3d5df5e183e9", + "@treeseed/sdk": "github:treeseed-ai/sdk#9ac536f6d599b9cdb9701e73ceb8768afff18f45", "esbuild": "0.28.0", "hono": "^4.8.2", "typescript": "^5.9.3", @@ -3703,8 +3703,9 @@ }, "node_modules/@treeseed/sdk": { "version": "0.12.63-dev.fix-sdk-package-lock-integrity.20260818T124913Z", - "resolved": "git+ssh://git@github.com/treeseed-ai/sdk.git#f843c3cb11853db737d28ecc6bcc3d5df5e183e9", - "license": "AGPL-3.0-only", + "resolved": "git+ssh://git@github.com/treeseed-ai/sdk.git#9ac536f6d599b9cdb9701e73ceb8768afff18f45", + "integrity": "sha512-6w9qNqZCmHdgme7C3Ab14xUz5UnAz0HPq5+u1t3fE9Wb3OStn4TQbS6kGJ/l9wwPdoixjD0V2VOcjmjXIzsiuA==", + "license": "Apache-2.0", "dependencies": { "@github/copilot": "1.0.39", "@github/copilot-language-server": "1.480.0", @@ -3746,6 +3747,27 @@ "node": ">=22" } }, + "node_modules/@treeseed/sdk/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@treeseed/sdk/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", diff --git a/package.json b/package.json index 64a4191b..67224dfd 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.29.0", "@openai/codex-sdk": "^0.130.0", - "@treeseed/sdk": "github:treeseed-ai/sdk#f843c3cb11853db737d28ecc6bcc3d5df5e183e9", + "@treeseed/sdk": "github:treeseed-ai/sdk#9ac536f6d599b9cdb9701e73ceb8768afff18f45", "esbuild": "0.28.0", "hono": "^4.8.2", "typescript": "^5.9.3", diff --git a/tests/unit/agents/agent-definition-compatibility.test.ts b/tests/unit/agents/agent-definition-compatibility.test.ts new file mode 100644 index 00000000..4219ce61 --- /dev/null +++ b/tests/unit/agents/agent-definition-compatibility.test.ts @@ -0,0 +1,20 @@ +import { readdirSync,readFileSync } from 'node:fs'; +import { resolve } from 'node:path'; +import { validateAgentDefinitionModel } from '@treeseed/sdk/agent-capacity'; +import { parse as parseYaml } from 'yaml'; +import { describe,expect,it } from 'vitest'; + +describe('Agent shipped agent definitions', () => { + it('remain compatible with the SDK authority and capacity-provider contract', () => { + const root = resolve(process.cwd(),'docs/src/content/agents'); + const names = readdirSync(root).filter((entry) => entry.endsWith('.mdx')).sort(); + expect(names.length).toBeGreaterThan(0); + for (const name of names) { + const source = readFileSync(resolve(root,name),'utf8'); + const match = source.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u); + expect(match,`${name} must contain YAML frontmatter`).not.toBeNull(); + expect(validateAgentDefinitionModel(parseYaml(match![1])),name).toMatchObject({ ok:true,diagnostics:[] }); + } + }); +}); + From 44525fe2dc8bc258cb563cbbed870bc7c2739b01 Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Tue, 18 Aug 2026 20:24:23 -0400 Subject: [PATCH 2/7] chore: adopt corrected SDK compatibility head --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2da72ccb..0cbef4ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.29.0", "@openai/codex-sdk": "^0.130.0", - "@treeseed/sdk": "github:treeseed-ai/sdk#9ac536f6d599b9cdb9701e73ceb8768afff18f45", + "@treeseed/sdk": "github:treeseed-ai/sdk#2de71415477d7e19c332aa8062fe0f587d709651", "esbuild": "0.28.0", "hono": "^4.8.2", "typescript": "^5.9.3", @@ -3703,7 +3703,7 @@ }, "node_modules/@treeseed/sdk": { "version": "0.12.63-dev.fix-sdk-package-lock-integrity.20260818T124913Z", - "resolved": "git+ssh://git@github.com/treeseed-ai/sdk.git#9ac536f6d599b9cdb9701e73ceb8768afff18f45", + "resolved": "git+ssh://git@github.com/treeseed-ai/sdk.git#2de71415477d7e19c332aa8062fe0f587d709651", "integrity": "sha512-6w9qNqZCmHdgme7C3Ab14xUz5UnAz0HPq5+u1t3fE9Wb3OStn4TQbS6kGJ/l9wwPdoixjD0V2VOcjmjXIzsiuA==", "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index 67224dfd..3b7e0f12 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.29.0", "@openai/codex-sdk": "^0.130.0", - "@treeseed/sdk": "github:treeseed-ai/sdk#9ac536f6d599b9cdb9701e73ceb8768afff18f45", + "@treeseed/sdk": "github:treeseed-ai/sdk#2de71415477d7e19c332aa8062fe0f587d709651", "esbuild": "0.28.0", "hono": "^4.8.2", "typescript": "^5.9.3", From 0f619e0b6e1d4a8607621d31acfe05b64d2f013a Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Tue, 18 Aug 2026 20:27:49 -0400 Subject: [PATCH 3/7] test(agent-definitions): preserve functional ownership --- .../{ => definitions}/agent-definition-compatibility.test.ts | 1 - 1 file changed, 1 deletion(-) rename tests/unit/agents/{ => definitions}/agent-definition-compatibility.test.ts (99%) diff --git a/tests/unit/agents/agent-definition-compatibility.test.ts b/tests/unit/agents/definitions/agent-definition-compatibility.test.ts similarity index 99% rename from tests/unit/agents/agent-definition-compatibility.test.ts rename to tests/unit/agents/definitions/agent-definition-compatibility.test.ts index 4219ce61..b0b4d68e 100644 --- a/tests/unit/agents/agent-definition-compatibility.test.ts +++ b/tests/unit/agents/definitions/agent-definition-compatibility.test.ts @@ -17,4 +17,3 @@ describe('Agent shipped agent definitions', () => { } }); }); - From 7015a121337225d73a8f464c49b65c4933ab87da Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Tue, 18 Aug 2026 20:45:27 -0400 Subject: [PATCH 4/7] add durable pull request contract --- .github/PULL_REQUEST_TEMPLATE.md | 57 +++++++++++++ .github/workflows/pull-request-contract.yml | 89 +++++++++++++++++++++ 2 files changed, 146 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 .github/workflows/pull-request-contract.yml diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000..9dbb6d39 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,57 @@ + + +## Outcome + + + +## Work authority + +- Work item / Issue: +- Proposal / decision: +- Assignment / checkpoint: +- Actor: +- Human authority: +- Agent / capacity provider: +- Exact base ref: +- Exact head ref: + +Contributor mode (select one): + +- [ ] Human-authored +- [ ] Agent-assisted under human authority +- [ ] Agent-authored under human authority + +## Plan + + + +## Changes and commits + + + +## Verification + + + +## Risk and rollback + + + +## Completion summary + + + +## Submission checklist + +- [ ] The change is bounded to the stated work item and target repository. +- [ ] Exact base and head refs are recorded and the branch is ready for review. +- [ ] Verification and compatibility evidence are recorded above. +- [ ] No plaintext secrets, credentials, machine state, or unrelated residue are included. +- [ ] Plan, status, commits, and completion summary form a complete durable record. +- [ ] Rollback or recovery steps are documented and executable. diff --git a/.github/workflows/pull-request-contract.yml b/.github/workflows/pull-request-contract.yml new file mode 100644 index 00000000..1699c3c3 --- /dev/null +++ b/.github/workflows/pull-request-contract.yml @@ -0,0 +1,89 @@ +name: Pull Request Submission Contract + +on: + pull_request_target: + types: [opened, edited, reopened, synchronize, ready_for_review, converted_to_draft] + +permissions: + contents: read + pull-requests: read + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Validate durable PR record + uses: actions/github-script@v7 + with: + script: | + const pullRequest = context.payload.pull_request; + const body = (pullRequest?.body ?? '').replace(//gu, ''); + + const requiredSections = [ + 'Outcome', + 'Work authority', + 'Plan', + 'Changes and commits', + 'Verification', + 'Risk and rollback', + 'Completion summary', + 'Submission checklist', + ]; + const missingSections = requiredSections.filter( + (section) => !body.includes(`## ${section}`), + ); + + const requiredFields = [ + 'Work item / Issue', + 'Proposal / decision', + 'Assignment / checkpoint', + 'Actor', + 'Human authority', + 'Agent / capacity provider', + 'Exact base ref', + 'Exact head ref', + ]; + const missingFields = requiredFields.filter((field) => { + const escaped = field.replace(/[.*+?^$()|[\]\\]/gu, '\\$&'); + return !new RegExp(`^- ${escaped}:\\s*\\S.+$`, 'mu').test(body); + }); + + const contributorModes = body.match( + /^- \[[xX]\] (?:Human-authored|Agent-assisted under human authority|Agent-authored under human authority)$/gmu, + ) ?? []; + + const errors = []; + if (missingSections.length > 0) { + errors.push(`missing sections: ${missingSections.join(', ')}`); + } + if (missingFields.length > 0) { + errors.push(`missing work-authority values: ${missingFields.join(', ')}`); + } + if (contributorModes.length !== 1) { + errors.push('select exactly one contributor mode'); + } + + if (!pullRequest?.draft) { + const readinessItems = [ + 'The change is bounded to the stated work item and target repository.', + 'Exact base and head refs are recorded and the branch is ready for review.', + 'Verification and compatibility evidence are recorded above.', + 'No plaintext secrets, credentials, machine state, or unrelated residue are included.', + 'Plan, status, commits, and completion summary form a complete durable record.', + 'Rollback or recovery steps are documented and executable.', + ]; + const unchecked = readinessItems.filter( + (item) => !body.split(/\r?\n/u).some( + (line) => line.trim() === `- [x] ${item}` || line.trim() === `- [X] ${item}`, + ), + ); + if (unchecked.length > 0) { + errors.push(`ready PR has incomplete checklist items: ${unchecked.join(' | ')}`); + } + } + + if (errors.length > 0) { + core.setFailed( + `Complete .github/PULL_REQUEST_TEMPLATE.md in the PR description: ${errors.join('; ')}`, + ); + } From ef18f0fc72e3954b6318376f5551d54e74e084eb Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Tue, 18 Aug 2026 20:45:56 -0400 Subject: [PATCH 5/7] defer PR contract enforcement pending workflow authority --- .github/workflows/pull-request-contract.yml | 89 --------------------- 1 file changed, 89 deletions(-) delete mode 100644 .github/workflows/pull-request-contract.yml diff --git a/.github/workflows/pull-request-contract.yml b/.github/workflows/pull-request-contract.yml deleted file mode 100644 index 1699c3c3..00000000 --- a/.github/workflows/pull-request-contract.yml +++ /dev/null @@ -1,89 +0,0 @@ -name: Pull Request Submission Contract - -on: - pull_request_target: - types: [opened, edited, reopened, synchronize, ready_for_review, converted_to_draft] - -permissions: - contents: read - pull-requests: read - -jobs: - validate: - runs-on: ubuntu-latest - steps: - - name: Validate durable PR record - uses: actions/github-script@v7 - with: - script: | - const pullRequest = context.payload.pull_request; - const body = (pullRequest?.body ?? '').replace(//gu, ''); - - const requiredSections = [ - 'Outcome', - 'Work authority', - 'Plan', - 'Changes and commits', - 'Verification', - 'Risk and rollback', - 'Completion summary', - 'Submission checklist', - ]; - const missingSections = requiredSections.filter( - (section) => !body.includes(`## ${section}`), - ); - - const requiredFields = [ - 'Work item / Issue', - 'Proposal / decision', - 'Assignment / checkpoint', - 'Actor', - 'Human authority', - 'Agent / capacity provider', - 'Exact base ref', - 'Exact head ref', - ]; - const missingFields = requiredFields.filter((field) => { - const escaped = field.replace(/[.*+?^$()|[\]\\]/gu, '\\$&'); - return !new RegExp(`^- ${escaped}:\\s*\\S.+$`, 'mu').test(body); - }); - - const contributorModes = body.match( - /^- \[[xX]\] (?:Human-authored|Agent-assisted under human authority|Agent-authored under human authority)$/gmu, - ) ?? []; - - const errors = []; - if (missingSections.length > 0) { - errors.push(`missing sections: ${missingSections.join(', ')}`); - } - if (missingFields.length > 0) { - errors.push(`missing work-authority values: ${missingFields.join(', ')}`); - } - if (contributorModes.length !== 1) { - errors.push('select exactly one contributor mode'); - } - - if (!pullRequest?.draft) { - const readinessItems = [ - 'The change is bounded to the stated work item and target repository.', - 'Exact base and head refs are recorded and the branch is ready for review.', - 'Verification and compatibility evidence are recorded above.', - 'No plaintext secrets, credentials, machine state, or unrelated residue are included.', - 'Plan, status, commits, and completion summary form a complete durable record.', - 'Rollback or recovery steps are documented and executable.', - ]; - const unchecked = readinessItems.filter( - (item) => !body.split(/\r?\n/u).some( - (line) => line.trim() === `- [x] ${item}` || line.trim() === `- [X] ${item}`, - ), - ); - if (unchecked.length > 0) { - errors.push(`ready PR has incomplete checklist items: ${unchecked.join(' | ')}`); - } - } - - if (errors.length > 0) { - core.setFailed( - `Complete .github/PULL_REQUEST_TEMPLATE.md in the PR description: ${errors.join('; ')}`, - ); - } From bbe857622344f69ebd9a538ffd1c95d35b565eac Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Tue, 18 Aug 2026 20:47:37 -0400 Subject: [PATCH 6/7] enforce durable pull request records --- .github/workflows/pull-request-contract.yml | 89 +++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 .github/workflows/pull-request-contract.yml diff --git a/.github/workflows/pull-request-contract.yml b/.github/workflows/pull-request-contract.yml new file mode 100644 index 00000000..1699c3c3 --- /dev/null +++ b/.github/workflows/pull-request-contract.yml @@ -0,0 +1,89 @@ +name: Pull Request Submission Contract + +on: + pull_request_target: + types: [opened, edited, reopened, synchronize, ready_for_review, converted_to_draft] + +permissions: + contents: read + pull-requests: read + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - name: Validate durable PR record + uses: actions/github-script@v7 + with: + script: | + const pullRequest = context.payload.pull_request; + const body = (pullRequest?.body ?? '').replace(//gu, ''); + + const requiredSections = [ + 'Outcome', + 'Work authority', + 'Plan', + 'Changes and commits', + 'Verification', + 'Risk and rollback', + 'Completion summary', + 'Submission checklist', + ]; + const missingSections = requiredSections.filter( + (section) => !body.includes(`## ${section}`), + ); + + const requiredFields = [ + 'Work item / Issue', + 'Proposal / decision', + 'Assignment / checkpoint', + 'Actor', + 'Human authority', + 'Agent / capacity provider', + 'Exact base ref', + 'Exact head ref', + ]; + const missingFields = requiredFields.filter((field) => { + const escaped = field.replace(/[.*+?^$()|[\]\\]/gu, '\\$&'); + return !new RegExp(`^- ${escaped}:\\s*\\S.+$`, 'mu').test(body); + }); + + const contributorModes = body.match( + /^- \[[xX]\] (?:Human-authored|Agent-assisted under human authority|Agent-authored under human authority)$/gmu, + ) ?? []; + + const errors = []; + if (missingSections.length > 0) { + errors.push(`missing sections: ${missingSections.join(', ')}`); + } + if (missingFields.length > 0) { + errors.push(`missing work-authority values: ${missingFields.join(', ')}`); + } + if (contributorModes.length !== 1) { + errors.push('select exactly one contributor mode'); + } + + if (!pullRequest?.draft) { + const readinessItems = [ + 'The change is bounded to the stated work item and target repository.', + 'Exact base and head refs are recorded and the branch is ready for review.', + 'Verification and compatibility evidence are recorded above.', + 'No plaintext secrets, credentials, machine state, or unrelated residue are included.', + 'Plan, status, commits, and completion summary form a complete durable record.', + 'Rollback or recovery steps are documented and executable.', + ]; + const unchecked = readinessItems.filter( + (item) => !body.split(/\r?\n/u).some( + (line) => line.trim() === `- [x] ${item}` || line.trim() === `- [X] ${item}`, + ), + ); + if (unchecked.length > 0) { + errors.push(`ready PR has incomplete checklist items: ${unchecked.join(' | ')}`); + } + } + + if (errors.length > 0) { + core.setFailed( + `Complete .github/PULL_REQUEST_TEMPLATE.md in the PR description: ${errors.join('; ')}`, + ); + } From b6f07113536d8420f0ac6c0e1c445dc38947062c Mon Sep 17 00:00:00 2001 From: Adrian Webb Date: Tue, 18 Aug 2026 21:57:57 -0400 Subject: [PATCH 7/7] adopt accepted SDK compatibility contract --- .github/workflows/pull-request-contract.yml | 22 +++++++++++++++---- package-lock.json | 4 ++-- package.json | 2 +- .../agent-definition-compatibility.test.ts | 10 +++++++-- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/.github/workflows/pull-request-contract.yml b/.github/workflows/pull-request-contract.yml index 1699c3c3..5d5232f0 100644 --- a/.github/workflows/pull-request-contract.yml +++ b/.github/workflows/pull-request-contract.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Validate durable PR record - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7 with: script: | const pullRequest = context.payload.pull_request; @@ -43,10 +43,12 @@ jobs: 'Exact base ref', 'Exact head ref', ]; - const missingFields = requiredFields.filter((field) => { + const fieldValues = new Map(requiredFields.map((field) => { const escaped = field.replace(/[.*+?^$()|[\]\\]/gu, '\\$&'); - return !new RegExp(`^- ${escaped}:\\s*\\S.+$`, 'mu').test(body); - }); + const match = body.match(new RegExp(`^- ${escaped}:\\s*(\\S.+)$`, 'mu')); + return [field, match?.[1]?.trim() ?? '']; + })); + const missingFields = requiredFields.filter((field) => !fieldValues.get(field)); const contributorModes = body.match( /^- \[[xX]\] (?:Human-authored|Agent-assisted under human authority|Agent-authored under human authority)$/gmu, @@ -63,6 +65,18 @@ jobs: errors.push('select exactly one contributor mode'); } + for (const [field, expectedSha] of [ + ['Exact base ref', pullRequest?.base?.sha], + ['Exact head ref', pullRequest?.head?.sha], + ]) { + const recordedSha = fieldValues.get(field)?.match(/(?:^|[^0-9a-f])([0-9a-f]{40})(?:$|[^0-9a-f])/u)?.[1]; + if (!recordedSha) { + errors.push(`${field} must contain a full 40-character commit SHA`); + } else if (recordedSha !== expectedSha) { + errors.push(`${field} is stale: expected ${expectedSha}`); + } + } + if (!pullRequest?.draft) { const readinessItems = [ 'The change is bounded to the stated work item and target repository.', diff --git a/package-lock.json b/package-lock.json index 0cbef4ac..d6dcb9d4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.29.0", "@openai/codex-sdk": "^0.130.0", - "@treeseed/sdk": "github:treeseed-ai/sdk#2de71415477d7e19c332aa8062fe0f587d709651", + "@treeseed/sdk": "github:treeseed-ai/sdk#92a66135fbda5575bee058b0ab25339c6c7d6398", "esbuild": "0.28.0", "hono": "^4.8.2", "typescript": "^5.9.3", @@ -3703,7 +3703,7 @@ }, "node_modules/@treeseed/sdk": { "version": "0.12.63-dev.fix-sdk-package-lock-integrity.20260818T124913Z", - "resolved": "git+ssh://git@github.com/treeseed-ai/sdk.git#2de71415477d7e19c332aa8062fe0f587d709651", + "resolved": "git+ssh://git@github.com/treeseed-ai/sdk.git#92a66135fbda5575bee058b0ab25339c6c7d6398", "integrity": "sha512-6w9qNqZCmHdgme7C3Ab14xUz5UnAz0HPq5+u1t3fE9Wb3OStn4TQbS6kGJ/l9wwPdoixjD0V2VOcjmjXIzsiuA==", "license": "Apache-2.0", "dependencies": { diff --git a/package.json b/package.json index 3b7e0f12..58b3e73b 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "dependencies": { "@modelcontextprotocol/sdk": "^1.29.0", "@openai/codex-sdk": "^0.130.0", - "@treeseed/sdk": "github:treeseed-ai/sdk#2de71415477d7e19c332aa8062fe0f587d709651", + "@treeseed/sdk": "github:treeseed-ai/sdk#92a66135fbda5575bee058b0ab25339c6c7d6398", "esbuild": "0.28.0", "hono": "^4.8.2", "typescript": "^5.9.3", diff --git a/tests/unit/agents/definitions/agent-definition-compatibility.test.ts b/tests/unit/agents/definitions/agent-definition-compatibility.test.ts index b0b4d68e..eb7ed14a 100644 --- a/tests/unit/agents/definitions/agent-definition-compatibility.test.ts +++ b/tests/unit/agents/definitions/agent-definition-compatibility.test.ts @@ -1,11 +1,13 @@ import { readdirSync,readFileSync } from 'node:fs'; import { resolve } from 'node:path'; +import { pathToFileURL } from 'node:url'; import { validateAgentDefinitionModel } from '@treeseed/sdk/agent-capacity'; import { parse as parseYaml } from 'yaml'; import { describe,expect,it } from 'vitest'; describe('Agent shipped agent definitions', () => { - it('remain compatible with the SDK authority and capacity-provider contract', () => { + it('remain compatible with the SDK authority and capacity-provider contract', async () => { + const { validateAgentActivityProfileCompatibility } = await import(pathToFileURL(resolve(process.cwd(),'node_modules/@treeseed/sdk/dist/agent-capacity/validation/compatibility/agent-definition-compatibility.js')).href); const root = resolve(process.cwd(),'docs/src/content/agents'); const names = readdirSync(root).filter((entry) => entry.endsWith('.mdx')).sort(); expect(names.length).toBeGreaterThan(0); @@ -13,7 +15,11 @@ describe('Agent shipped agent definitions', () => { const source = readFileSync(resolve(root,name),'utf8'); const match = source.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/u); expect(match,`${name} must contain YAML frontmatter`).not.toBeNull(); - expect(validateAgentDefinitionModel(parseYaml(match![1])),name).toMatchObject({ ok:true,diagnostics:[] }); + const definition = parseYaml(match![1]) as Record; + expect(validateAgentDefinitionModel(definition),name).toMatchObject({ ok:true,diagnostics:[] }); + for (const [activityType,profile] of Object.entries(definition.activityProfiles ?? {}) as Array<[any,any]>) { + if (profile.enabled) expect(validateAgentActivityProfileCompatibility(activityType,profile),name).toMatchObject({ ok:true,diagnostics:[] }); + } } }); });