triad-plus 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/README.md +7 -0
- package/adapters/antigravity/README.md +1 -1
- package/adapters/antigravity/install.sh +1 -1
- package/adapters/claude-code/README.md +1 -1
- package/adapters/claude-code/install.sh +1 -1
- package/adapters/codex/README.md +1 -1
- package/adapters/codex/install.sh +3 -3
- package/adapters/hermes/install.sh +1 -1
- package/adapters/opencode/.opencode/agents/triad-developer.md +14 -0
- package/adapters/opencode/.opencode/agents/triad-orchestrator.md +1 -0
- package/adapters/opencode/.opencode/agents/triad-reviewer.md +15 -0
- package/adapters/opencode/README.md +15 -6
- package/adapters/opencode/install.sh +1 -1
- package/adapters/registry.mjs +22 -2
- package/bin/triad-plus.js +207 -41
- package/docs/configuration.md +26 -6
- package/docs/npx-installation.md +16 -0
- package/docs/opencode-replication.md +8 -0
- package/docs/runtimes.md +1 -1
- package/package.json +2 -2
- package/runtime/lib/assignment-packet.mjs +38 -1
- package/runtime/lib/model-config.mjs +165 -0
- package/runtime/lib/repository-context.mjs +192 -0
- package/runtime/lib/terminal.mjs +86 -0
- package/runtime/triad-runtime-context.mjs +88 -0
- package/runtime/triad-verify.mjs +26 -18
- package/skills/triad-loop-developer/SKILL.md +14 -0
- package/skills/triad-loop-orchestrator/SKILL.md +13 -0
- package/skills/triad-loop-reviewer/SKILL.md +16 -0
- package/skills/triad-model-configuration/SKILL.md +98 -0
- package/skills/triad-model-configuration/agents/openai.yaml +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.10.0 — 2026-09-16
|
|
4
|
+
|
|
5
|
+
- Improve TUI and doctor output with terminal-native summaries, sober color
|
|
6
|
+
handling, `NO_COLOR`, and non-TTY support.
|
|
7
|
+
- Add the agent-first model-configuration skill with `.triad-plus/team.json`
|
|
8
|
+
as the role/model source of truth and explicit host-native bindings,
|
|
9
|
+
including OpenCode `variant` materialization.
|
|
10
|
+
- Add shared-skill diagnostics and repair during managed upgrades, plus
|
|
11
|
+
deterministic repository/runtime context verification and nested-repository
|
|
12
|
+
hardening.
|
|
13
|
+
- Fail closed on incorrect working directories, mixed Git roots, symlink
|
|
14
|
+
escapes, missing or mutated skills, and implicit fallback to unrelated skill
|
|
15
|
+
copies.
|
|
16
|
+
|
|
3
17
|
## 1.9.0 — 2026-09-16
|
|
4
18
|
|
|
5
19
|
- Add native BMAD `epics.md` intake while preserving the boundary that BMAD
|
package/README.md
CHANGED
|
@@ -184,6 +184,13 @@ workspace with that adapter. Triad+ does not dispatch different roles across
|
|
|
184
184
|
different hosts in one run. Read [configuration](docs/configuration.md) and
|
|
185
185
|
[runtime details](docs/runtimes.md).
|
|
186
186
|
|
|
187
|
+
The installed `triad-model-configuration` Agent Skill lets the host agent
|
|
188
|
+
inspect or change requested role models while preserving `team.json` as the
|
|
189
|
+
source of truth and reporting host-specific binding limits.
|
|
190
|
+
|
|
191
|
+
On OpenCode, `team.json`'s `reasoning_effort` is materialized as the native
|
|
192
|
+
per-agent `variant`; the OpenCode session default is a separate host setting.
|
|
193
|
+
|
|
187
194
|
`triad-verify` validates assignment/candidate binding, runs declared
|
|
188
195
|
control-plane gates, detects mutation, and writes evidence. It supports the
|
|
189
196
|
loop; it never replaces the Orchestrator. See [verification](docs/verification.md).
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Triad+ for Antigravity
|
|
2
2
|
|
|
3
3
|
The Antigravity adapter uses native workspace paths: `.agents/skills/` for the
|
|
4
|
-
|
|
4
|
+
six shared Triad+ skills and `/triad` workflow, plus `.agents/agents/` for the
|
|
5
5
|
four technical agents. Start Antigravity from the project-control workspace and
|
|
6
6
|
invoke:
|
|
7
7
|
|
|
@@ -30,7 +30,7 @@ fi
|
|
|
30
30
|
adapter_root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
31
31
|
repository_root="$(cd -- "$adapter_root/../.." && pwd)"
|
|
32
32
|
agent_names=(triad-orchestrator triad-developer triad-evaluator triad-reviewer)
|
|
33
|
-
skill_names=(triad-loop-bootstrap triad-loop-orchestrator triad-loop-developer triad-loop-evaluator triad-loop-reviewer)
|
|
33
|
+
skill_names=(triad-loop-bootstrap triad-loop-orchestrator triad-loop-developer triad-loop-evaluator triad-loop-reviewer triad-model-configuration)
|
|
34
34
|
collisions=()
|
|
35
35
|
|
|
36
36
|
for agent_name in "${agent_names[@]}"; do
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Triad+ Engineering Loop for Claude Code
|
|
2
2
|
|
|
3
|
-
This adapter installs the shared
|
|
3
|
+
This adapter installs the shared six Triad skills, three isolated Claude Code
|
|
4
4
|
subagents, the `/triad` command, and—on a project installation—the Node control
|
|
5
5
|
plane. It does not modify global Claude settings or automatically activate a
|
|
6
6
|
hook.
|
|
@@ -30,7 +30,7 @@ fi
|
|
|
30
30
|
adapter_root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
31
31
|
repository_root="$(cd -- "$adapter_root/../.." && pwd)"
|
|
32
32
|
agent_names=(triad-developer triad-evaluator triad-reviewer)
|
|
33
|
-
skill_names=(triad-loop-bootstrap triad-loop-orchestrator triad-loop-developer triad-loop-evaluator triad-loop-reviewer)
|
|
33
|
+
skill_names=(triad-loop-bootstrap triad-loop-orchestrator triad-loop-developer triad-loop-evaluator triad-loop-reviewer triad-model-configuration)
|
|
34
34
|
collisions=()
|
|
35
35
|
|
|
36
36
|
for agent_name in "${agent_names[@]}"; do
|
package/adapters/codex/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Then install the global entry point and the skills once for the Codex user:
|
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
The installer refuses any overwrite. It installs the project runtime under
|
|
21
|
-
`.triad-runtime` and the
|
|
21
|
+
`.triad-runtime` and the six shared skills under `.agents/skills`; the global
|
|
22
22
|
installation also makes the skills available to Codex and writes
|
|
23
23
|
`$CODEX_HOME/prompts/triad.md` (`$HOME/.codex` by default).
|
|
24
24
|
|
|
@@ -8,10 +8,10 @@ Usage:
|
|
|
8
8
|
./adapters/codex/install.sh --global
|
|
9
9
|
|
|
10
10
|
Install the Triad Codex adapter without overwriting existing skills, prompt, or
|
|
11
|
-
project runtime. --project installs the
|
|
11
|
+
project runtime. --project installs the six skills under
|
|
12
12
|
<control-repository-path>/.agents/skills and installs .triad-runtime. It does
|
|
13
13
|
not install the user-level Codex prompt. --global installs the /prompts:triad
|
|
14
|
-
entry point and the
|
|
14
|
+
entry point and the six skills under $CODEX_HOME (default: $HOME/.codex).
|
|
15
15
|
|
|
16
16
|
For normal use run both commands once: --project for each control repository,
|
|
17
17
|
then --global for the Codex entry point. Existing paths are never overwritten.
|
|
@@ -19,7 +19,7 @@ EOF
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
codex_home="${CODEX_HOME:-$HOME/.codex}"
|
|
22
|
-
skill_names=(triad-loop-bootstrap triad-loop-orchestrator triad-loop-developer triad-loop-evaluator triad-loop-reviewer)
|
|
22
|
+
skill_names=(triad-loop-bootstrap triad-loop-orchestrator triad-loop-developer triad-loop-evaluator triad-loop-reviewer triad-model-configuration)
|
|
23
23
|
|
|
24
24
|
if [[ $# -eq 2 && "$1" == "--project" ]]; then
|
|
25
25
|
project_root="$2"
|
|
@@ -18,7 +18,7 @@ fi
|
|
|
18
18
|
|
|
19
19
|
adapter_root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
20
20
|
repository_root="$(cd -- "$adapter_root/../.." && pwd)"
|
|
21
|
-
skill_names=(triad-loop-bootstrap triad-loop-orchestrator triad-loop-developer triad-loop-evaluator triad-loop-reviewer)
|
|
21
|
+
skill_names=(triad-loop-bootstrap triad-loop-orchestrator triad-loop-developer triad-loop-evaluator triad-loop-reviewer triad-model-configuration)
|
|
22
22
|
|
|
23
23
|
if [[ "$global_install" == true ]]; then
|
|
24
24
|
hermes_root="${HERMES_HOME:-$HOME/.hermes}"
|
|
@@ -28,6 +28,20 @@ At activation, read `.triad-plus/team.json`. Your first report to the
|
|
|
28
28
|
Orchestrator identifies the configured `roles.developer.displayName` as the
|
|
29
29
|
Triad+ Developer and names the assigned card.
|
|
30
30
|
|
|
31
|
+
Before editing, run the exact runtime-context proof from this activation's
|
|
32
|
+
actual cwd:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
node /absolute/path/to/control-workspace/.triad-runtime/triad-runtime-context.mjs \
|
|
36
|
+
--project /absolute/path/to/control-workspace \
|
|
37
|
+
--assignment /absolute/path/to/control-workspace/.loop/runtime/assignments/<assignment-file>.json
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Record packet cwd, process cwd, shell `pwd`, Git top-level, and every resolved
|
|
41
|
+
repository-skill path/hash. A non-zero result or any mismatch is invalid
|
|
42
|
+
runtime context: stop and report it, and never substitute a control-workspace
|
|
43
|
+
or global skill copy.
|
|
44
|
+
|
|
31
45
|
Verify the worktree and branch. Do not expand scope, silently change project
|
|
32
46
|
policy, add dependencies without authorization, or make delivery decisions. Run
|
|
33
47
|
the required gates, measure the declared metrics, and report exact commands and
|
|
@@ -30,6 +30,21 @@ At activation, read `.triad-plus/team.json`. Your first report to the
|
|
|
30
30
|
Orchestrator identifies the configured `roles.reviewer.displayName` as the
|
|
31
31
|
Triad+ Reviewer and names the feature and attempt under review.
|
|
32
32
|
|
|
33
|
+
Before inspecting the candidate, run this exact runtime-context proof from the
|
|
34
|
+
actual Reviewer cwd:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
node /absolute/path/to/control-workspace/.triad-runtime/triad-runtime-context.mjs \
|
|
38
|
+
--project /absolute/path/to/control-workspace \
|
|
39
|
+
--assignment /absolute/path/to/control-workspace/.loop/runtime/assignments/<assignment-file>.json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Record packet cwd, process cwd, shell `pwd`, Git top-level, and each resolved
|
|
43
|
+
repository-skill path/hash. On non-zero status, `NotFound`, hash mismatch,
|
|
44
|
+
mixed repository roots, or cwd inconsistency, return `blocked` / invalid
|
|
45
|
+
runtime context. Do not use a same-named skill from the control workspace or
|
|
46
|
+
global skills as a fallback.
|
|
47
|
+
|
|
33
48
|
Return one evidence-based recommendation: `approved`, `rework`, or `blocked`.
|
|
34
49
|
List severity-ranked findings before gate and metric evidence, residual risks,
|
|
35
50
|
and the recommendation. A blocked recommendation must identify the exact owner
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Triad+ Engineering Loop for OpenCode
|
|
2
2
|
|
|
3
|
-
This adapter makes the repository's existing
|
|
3
|
+
This adapter makes the repository's existing six standard Agent Skills
|
|
4
4
|
operational in OpenCode. It installs four specialized agents and the `/triad`
|
|
5
5
|
command; it does not duplicate the method or alter `opencode.json`.
|
|
6
6
|
|
|
@@ -26,6 +26,7 @@ skills/triad-loop-orchestrator/
|
|
|
26
26
|
skills/triad-loop-developer/
|
|
27
27
|
skills/triad-loop-evaluator/
|
|
28
28
|
skills/triad-loop-reviewer/
|
|
29
|
+
skills/triad-model-configuration/
|
|
29
30
|
.triad-runtime/
|
|
30
31
|
triad-verify.mjs
|
|
31
32
|
triad-runtime-capabilities.mjs
|
|
@@ -55,12 +56,12 @@ remain in a declared project workspace.
|
|
|
55
56
|
|
|
56
57
|
`.triad-plus/team.json` is the source of truth for role-level model
|
|
57
58
|
configuration. When a team file supplies values, Triad+ materializes the
|
|
58
|
-
OpenCode-native `model` and `
|
|
59
|
-
|
|
59
|
+
OpenCode-native `model` and `variant` frontmatter fields in each project agent
|
|
60
|
+
definition during `init` and `upgrade --apply`:
|
|
60
61
|
|
|
61
62
|
```text
|
|
62
63
|
team.json model → OpenCode model
|
|
63
|
-
team.json reasoning_effort → OpenCode
|
|
64
|
+
team.json reasoning_effort → OpenCode variant
|
|
64
65
|
```
|
|
65
66
|
|
|
66
67
|
Do not treat generated `.opencode/agents/*.md` files as an independent
|
|
@@ -70,8 +71,9 @@ absent so OpenCode uses its host/session default.
|
|
|
70
71
|
|
|
71
72
|
The adapter only writes fields supported by this OpenCode materialization. Host
|
|
72
73
|
and provider capabilities may still limit which model or reasoning levels are
|
|
73
|
-
available. Inspect identifiers with `opencode models` and keep
|
|
74
|
-
routing explicit in the team file
|
|
74
|
+
available. Inspect identifiers and variants with `opencode models` and keep
|
|
75
|
+
role-specific routing explicit in the team file. OpenCode's role `variant` is
|
|
76
|
+
not the same thing as the default model/session selected by the TUI:
|
|
75
77
|
|
|
76
78
|
| Agent | Recommended profile |
|
|
77
79
|
| --- | --- |
|
|
@@ -84,6 +86,13 @@ Use `opencode models` to inspect the provider/model identifiers available in
|
|
|
84
86
|
the local installation. Keep the developer, evaluator, and reviewer separately
|
|
85
87
|
configured when independent model routing is required.
|
|
86
88
|
|
|
89
|
+
The adapter targets the installed OpenCode agent contract: `variant` is the
|
|
90
|
+
host-native per-agent option, while `team.json` remains the canonical desired
|
|
91
|
+
configuration. A null or blank model/effort removes the managed field and lets
|
|
92
|
+
OpenCode use its host or session default. `upgrade --apply` refreshes managed
|
|
93
|
+
agents and then reapplies this same binding; it does not rewrite `team.json`.
|
|
94
|
+
OpenCode 1.18.x exposes this contract through the `AgentConfig.variant` field.
|
|
95
|
+
|
|
87
96
|
## Start the loop
|
|
88
97
|
|
|
89
98
|
Launch OpenCode from the project-control repository, then enter:
|
|
@@ -31,7 +31,7 @@ adapter_root="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
31
31
|
repository_root="$(cd -- "$adapter_root/../.." && pwd)"
|
|
32
32
|
|
|
33
33
|
agent_names=(triad-orchestrator triad-developer triad-evaluator triad-reviewer)
|
|
34
|
-
skill_names=(triad-loop-bootstrap triad-loop-orchestrator triad-loop-developer triad-loop-evaluator triad-loop-reviewer)
|
|
34
|
+
skill_names=(triad-loop-bootstrap triad-loop-orchestrator triad-loop-developer triad-loop-evaluator triad-loop-reviewer triad-model-configuration)
|
|
35
35
|
command_name="triad"
|
|
36
36
|
collisions=()
|
|
37
37
|
|
package/adapters/registry.mjs
CHANGED
|
@@ -7,7 +7,8 @@ export const sharedSkillNames = [
|
|
|
7
7
|
'triad-loop-orchestrator',
|
|
8
8
|
'triad-loop-developer',
|
|
9
9
|
'triad-loop-evaluator',
|
|
10
|
-
'triad-loop-reviewer'
|
|
10
|
+
'triad-loop-reviewer',
|
|
11
|
+
'triad-model-configuration'
|
|
11
12
|
];
|
|
12
13
|
|
|
13
14
|
export const roleDefinitions = [
|
|
@@ -87,7 +88,13 @@ const definitions = [
|
|
|
87
88
|
entry: '/triad',
|
|
88
89
|
lifecycle: null,
|
|
89
90
|
modelBinding: 'project-frontmatter',
|
|
90
|
-
|
|
91
|
+
// OpenCode's agent frontmatter has a first-class `variant` field. Keep
|
|
92
|
+
// Triad's canonical `reasoning_effort` name in team.json and map it to
|
|
93
|
+
// that host-native field rather than emitting provider options such as
|
|
94
|
+
// `reasoningEffort` into the agent profile.
|
|
95
|
+
modelFields: ['model', 'variant'],
|
|
96
|
+
modelFieldSources: { model: 'model', variant: 'reasoning_effort' },
|
|
97
|
+
modelCleanupFields: ['reasoningEffort'],
|
|
91
98
|
modelRoles: roleDefinitions.map((role) => role.id),
|
|
92
99
|
projectAssets: [
|
|
93
100
|
{ source: 'adapters/opencode/.opencode/agents', destination: '.opencode/agents' },
|
|
@@ -114,6 +121,10 @@ const definitions = [
|
|
|
114
121
|
},
|
|
115
122
|
roleModelPaths(controlRoot) {
|
|
116
123
|
return roleDefinitions.map((role) => join(controlRoot, '.opencode', 'agents', `triad-${role.id}.md`));
|
|
124
|
+
},
|
|
125
|
+
globalRoleModelPaths() {
|
|
126
|
+
const root = hostHome('.config', 'opencode');
|
|
127
|
+
return rolePaths(root, roleDefinitions.map((role) => `triad-${role.id}`));
|
|
117
128
|
}
|
|
118
129
|
},
|
|
119
130
|
{
|
|
@@ -157,6 +168,10 @@ const definitions = [
|
|
|
157
168
|
},
|
|
158
169
|
roleModelPaths(controlRoot) {
|
|
159
170
|
return ['developer', 'reviewer', 'evaluator'].map((role) => join(controlRoot, '.claude', 'agents', `triad-${role}.md`));
|
|
171
|
+
},
|
|
172
|
+
globalRoleModelPaths() {
|
|
173
|
+
const root = hostHome('.claude');
|
|
174
|
+
return ['developer', 'reviewer', 'evaluator'].map((role) => join(root, 'agents', `triad-${role}.md`));
|
|
160
175
|
}
|
|
161
176
|
},
|
|
162
177
|
{
|
|
@@ -222,6 +237,7 @@ const definitions = [
|
|
|
222
237
|
lifecycle: null,
|
|
223
238
|
modelBinding: 'project-frontmatter',
|
|
224
239
|
modelFields: ['model', 'reasoningEffort'],
|
|
240
|
+
modelFieldSources: { model: 'model', reasoningEffort: 'reasoning_effort' },
|
|
225
241
|
modelRoles: roleDefinitions.map((role) => role.id),
|
|
226
242
|
projectAssets: [
|
|
227
243
|
{ source: 'adapters/copilot/.github/agents', destination: '.github/agents' },
|
|
@@ -253,6 +269,10 @@ const definitions = [
|
|
|
253
269
|
},
|
|
254
270
|
roleModelPaths(controlRoot) {
|
|
255
271
|
return roleDefinitions.map((role) => join(controlRoot, '.github', 'agents', `triad-${role.id}.agent.md`));
|
|
272
|
+
},
|
|
273
|
+
globalRoleModelPaths() {
|
|
274
|
+
const root = hostHome('.copilot');
|
|
275
|
+
return roleDefinitions.map((role) => join(root, 'agents', `triad-${role.id}.agent.md`));
|
|
256
276
|
}
|
|
257
277
|
}
|
|
258
278
|
];
|