@zalom/plastic 2.0.0-alpha.26 → 2.0.0-alpha.27

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.
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- # Usage: read-config <key> [--default VALUE] [--project PATH]
2
+ # Usage: read-config <key> [--default VALUE] [--project PATH] [--harness claude|codex]
3
3
  # Resolves a config value: project -> global -> built-in defaults.
4
4
  # Nested keys use dot notation: agent.type, architect.style
5
5
  # Returns scalar values as strings, hash/array values as JSON.
@@ -46,6 +46,7 @@ def parse_args(argv)
46
46
  key = nil
47
47
  default_val = nil
48
48
  project_dir = nil
49
+ harness = nil
49
50
 
50
51
  i = 0
51
52
  while i < argv.length
@@ -58,13 +59,17 @@ def parse_args(argv)
58
59
  abort "Error: --project requires a value" unless argv[i + 1]
59
60
  project_dir = argv[i + 1]
60
61
  i += 2
62
+ when "--harness"
63
+ abort "Error: --harness requires a value" unless argv[i + 1]
64
+ harness = argv[i + 1]
65
+ i += 2
61
66
  else
62
67
  key = argv[i]
63
68
  i += 1
64
69
  end
65
70
  end
66
71
 
67
- [key, default_val, project_dir]
72
+ [key, default_val, project_dir, harness]
68
73
  end
69
74
 
70
75
  def load_yaml(path)
@@ -119,10 +124,10 @@ if ARGV.include?("--migrate")
119
124
  exit 0
120
125
  end
121
126
 
122
- key, explicit_default, project_dir = parse_args(ARGV)
127
+ key, explicit_default, project_dir, harness = parse_args(ARGV)
123
128
 
124
129
  if key.nil? || key.empty?
125
- $stderr.puts "Usage: read-config <key> [--default VALUE] [--project PATH]"
130
+ $stderr.puts "Usage: read-config <key> [--default VALUE] [--project PATH] [--harness claude|codex]"
126
131
  exit 1
127
132
  end
128
133
 
@@ -135,9 +140,42 @@ if project_dir
135
140
  project_config = load_yaml(project_config_path)
136
141
  end
137
142
 
138
- value = dig_key(project_config, key)
139
- value = dig_key(global_config, key) if value.nil?
143
+ def canonical_harness(value)
144
+ return nil if value.nil?
145
+ return "claude" if %w[claude claude-code].include?(value.to_s)
146
+ return "codex" if value.to_s == "codex"
147
+
148
+ abort "Error: --harness must be claude or codex"
149
+ end
150
+
151
+ def harness_agent_value(config, key, harness)
152
+ match = key.match(/\Aagents\.(models|efforts)\.([^.]+)\z/)
153
+ return nil unless match
154
+
155
+ section, agent = match.captures
156
+ if section == "models"
157
+ AgentModels.models_section(config, harness: harness)[agent]
158
+ else
159
+ AgentModels.efforts_section(config, harness)[agent]
160
+ end
161
+ end
162
+
163
+ harness = canonical_harness(harness)
164
+ if harness
165
+ value = harness_agent_value(project_config, key, harness)
166
+ value = harness_agent_value(global_config, key, harness) if value.nil?
167
+ else
168
+ value = dig_key(project_config, key)
169
+ value = dig_key(global_config, key) if value.nil?
170
+ end
140
171
  value = explicit_default if value.nil? && explicit_default
172
+ if value.nil? && harness && (match = key.match(/\Aagents\.(models|efforts)\.([^.]+)\z/))
173
+ value = if match[1] == "models"
174
+ AgentModels.shipped_model_for(match[2], harness: harness)
175
+ else
176
+ AgentModels::DEFAULT_EFFORT
177
+ end
178
+ end
141
179
  value = dig_key(DEFAULTS, key) if value.nil?
142
180
 
143
181
  puts format_value(value)
@@ -6,7 +6,7 @@ description: >-
6
6
  failed attempts, or ranking several plausible options. Use when the user asks for
7
7
  a second opinion, a hard design decision, an architecture review, help breaking a
8
8
  deadlock, or says "ask the advisor". Also sets which advisor is the default when
9
- asked ("make Fable my advisor", "switch my advisor", "use the real advisor").
9
+ asked ("make Primary Advisor my default", "switch my advisor", "use Secondary Advisor").
10
10
  user-invocable: true
11
11
  ---
12
12
 
@@ -15,12 +15,10 @@ user-invocable: true
15
15
  Plastic ships two consultation agents, never dispatched by the auto pipeline, summoned
16
16
  only when you decide the reasoning is worth buying:
17
17
 
18
- - **`plastic-advisor`** ("the real advisor"): the frontier model itself, expensive,
19
- billed through usage credits. Spawn it for a few rounds on the hardest problem, then
20
- close the session.
21
- - **`plastic-faux-advisor`** ("the imitation advisor"): an ordinary model carrying the
22
- same reasoning discipline inline in its own body, so it reasons the same disciplined
23
- way at a fraction of the cost. The cheaper default.
18
+ - **Primary Advisor** (`plastic-primary-advisor`): Fable at medium effort. Use it for
19
+ normal consultation.
20
+ - **Secondary Advisor** (`plastic-secondary-advisor`): Fable at high effort. Use it only
21
+ as an explicit escalation for harder or higher-risk reasoning.
24
22
 
25
23
  ## When to consult (and when not to)
26
24
 
@@ -33,25 +31,23 @@ when the ordering decides where you spend the next day.
33
31
  Never buy a consultation for: anything a tool can answer (search, reading code, running
34
32
  tests, documentation), writing code at volume, confirming a decision you already made,
35
33
  style or naming a linter would settle, or anything reversible and cheap you have not
36
- tried first. The full buy/never-buy list, the effort table, and the entry test live in
34
+ tried first. The full buy/never-buy list, answer-shape table, and entry test live in
37
35
  `references/advisor-protocol.md`; read it before writing a brief for the first time in
38
36
  a session.
39
37
 
40
38
  ## Routing: which advisor answers
41
39
 
42
40
  1. Read the harness-scoped config: `advisor.claude.default`, the only advisor routing key
43
- the installer writes. If unset, use `plastic-advisor`, the shipped default.
44
- 2. If the user names which advisor they want ("ask the real one", "use Fable", "ask the
45
- cheap one"), honor that directly and dispatch `plastic-advisor` (the real advisor) or
46
- `plastic-faux-advisor` (the cheaper imitation) accordingly, overriding step 1 for this
47
- consultation only.
41
+ the installer writes. If unset, use `plastic-primary-advisor`, the shipped default.
42
+ 2. If the user explicitly asks for Primary Advisor or Secondary Advisor, honor that choice for
43
+ this consultation. Otherwise, dispatch the configured agent from step 1.
48
44
  3. If `advisor.enabled` reads `false`, neither advisor agent nor this skill is
49
45
  installed; this step should not be reachable, but if it is, tell the user the
50
46
  advisor is disabled and point at "Setting the default" below.
51
47
  4. Dispatch the resolved agent with a brief built per `references/advisor-protocol.md`
52
48
  section 4 (natural prose, the block is a completeness check, not a form to fill).
53
- State EFFORT and the answer shape explicitly; classify low and prove your way up,
54
- never open high "to be safe".
49
+ State the answer shape explicitly. Primary uses medium effort and Secondary uses high;
50
+ only an explicit owner config override changes either value.
55
51
  5. Consume the answer per the protocol's section 5: run the Operating Manual's
56
52
  five-question self-test on the advisor's plan before executing it. Advice is input,
57
53
  not authority; the plan is the advisor's, the outcome is yours.
@@ -66,27 +62,23 @@ ruby ~/.plastic/scripts/read-config advisor.claude.default --project <repo>
66
62
 
67
63
  ## Setting the default advisor
68
64
 
69
- When asked to change the default ("make Fable my advisor", "switch my advisor", "use
70
- the cheaper one by default"), present the two options in plain language and write the
65
+ When asked to change the default, present the two options in plain language and write the
71
66
  choice:
72
67
 
73
- - **Faux Fable** (`plastic-faux-advisor`, recommended): an ordinary model carrying the
74
- frontier reasoning instructions. Much cheaper, available on any plan, reasons in the
75
- same disciplined way.
76
- - **Fable 5** (`plastic-advisor`): the frontier model itself. The strongest reasoning
77
- available, billed through usage credits, so summon it for a few rounds and close it.
68
+ - **Primary Advisor** (`plastic-primary-advisor`, recommended): Fable at medium effort.
69
+ - **Secondary Advisor** (`plastic-secondary-advisor`): Fable at high effort.
78
70
 
79
71
  These are the same two options the installer offers at install and update time. Write
80
72
  the choice to `advisor.claude.default` in the global `~/.plastic/config.yml` (or the
81
73
  project's `.plastic_store/config.yml` when the user scopes the change to one project):
82
- read the file as YAML, set `advisor.claude.default` to the agent name (`plastic-advisor`
83
- or `plastic-faux-advisor`, never a model name or nickname), and write it back. Confirm
74
+ read the file as YAML, set `advisor.claude.default` to the agent name (`plastic-primary-advisor`
75
+ or `plastic-secondary-advisor`, never a model name or nickname), and write it back. Confirm
84
76
  the new default back to the user in one line.
85
77
 
86
78
  ## References
87
79
 
88
80
  - `references/advisor-protocol.md`: the full shipped Advisor Protocol (what to buy,
89
- effort and answer shape, the entry test, how to write a brief that earns its cost, the
81
+ answer shape, the entry test, how to write a brief that earns its cost, the
90
82
  answer contract, session economics, anti-patterns). Read it before the first
91
83
  consultation in a session; the second consultation in the same advisor thread costs a
92
84
  fraction of the first, so keep follow-ups on one thread rather than opening a new one.
@@ -4,13 +4,13 @@
4
4
 
5
5
  *Adapted for Plastic (intent 185): this is the shipped reference copy the
6
6
  `plastic-agent-advisor` skill teaches from. Two named agents carry it,
7
- `plastic-advisor` (the real advisor) and `plastic-faux-advisor` (the cheaper
8
- imitation, the same discipline at a fraction of the cost); EFFORT and the
9
- answer shape below shape the brief and the answer on whichever one you
7
+ `plastic-primary-advisor` (Primary Advisor) and `plastic-secondary-advisor`
8
+ (Secondary Advisor, the explicit escalation); the
9
+ answer shape below shapes the brief and the answer on whichever one you
10
10
  dispatch, never which file to pick. The
11
11
  `plastic-agent-advisor` skill reads harness-scoped config
12
- (`advisor.claude.default`, falling back to `secondary`, then to
13
- `plastic-faux-advisor`) to route your consultation automatically; name a
12
+ (`advisor.claude.default`, falling back to `plastic-primary-advisor`) to route your
13
+ consultation automatically; name a
14
14
  specific advisor in your request to override it. A frontier model rewards a
15
15
  single, well-formed one-shot brief more than a back-and-forth, so front-load
16
16
  everything section 3 below asks for before you send. The rest of this
@@ -53,17 +53,18 @@ You own the work and the outcome. Fable owns the hardest thinking, on demand.
53
53
 
54
54
  ---
55
55
 
56
- ## 2. Effort and answer shape
56
+ ## 2. Answer shape
57
57
 
58
58
  Classify every consultation before sending it. Default to the smallest shape and
59
- prove your way up. Never open at a higher effort "to be safe": effort follows the cost of being
60
- wrong, not the importance the task feels like it has.
59
+ prove your way up. Primary Advisor ships at medium reasoning effort. Secondary Advisor ships
60
+ at high reasoning effort on Claude Code and Codex. An explicit harness-scoped config override
61
+ may change one agent's effort.
61
62
 
62
63
  | Shape | Coding | Business | Research | Effort | Brief size | Expected return |
63
64
  |------|--------|----------|----------|--------|------------|-----------------|
64
- | **Verdict** | Verdict on one step; choose between two named implementations | Pick between two options you already compared (vendor, pricing point) | Judge whether one source or result is trustworthy enough to build on | `low` | Under 300 words | Verdict, one paragraph of reasoning, the single biggest risk |
65
- | **Plan** | Plan a feature inside one system; review a full plan for holes; design one interface; rank root causes | Positioning or pricing decision from a compiled evidence pack; review a proposal before sending it | Design a research plan for a bounded question; rank competing explanations of the data you gathered | `medium`, or `high` if an irreversible step is inside | Up to one page | Decision, numbered plan with per-step checks, risk map |
66
- | **Architecture** | Cross-system architecture; migration with one-way doors; deadlock after two failed attempts; security-critical design | Build-vs-buy, market entry, or any commitment measured in months; strategy where reversal is expensive | Synthesis across many sources where the conclusion drives a large bet; contested questions with conflicting evidence | `xhigh`; `max` only when being wrong means data loss, a broken contract, or weeks of rework | Full evidence brief | Decision, plan, risk register, kill criteria, list of what could not be verified |
65
+ | **Verdict** | Verdict on one step; choose between two named implementations | Pick between two options you already compared (vendor, pricing point) | Judge whether one source or result is trustworthy enough to build on | `medium` | Under 300 words | Verdict, one paragraph of reasoning, the single biggest risk |
66
+ | **Plan** | Plan a feature inside one system; review a full plan for holes; design one interface; rank root causes | Positioning or pricing decision from a compiled evidence pack; review a proposal before sending it | Design a research plan for a bounded question; rank competing explanations of the data you gathered | `medium` | Up to one page | Decision, numbered plan with per-step checks, risk map |
67
+ | **Architecture** | Cross-system architecture; migration with one-way doors; deadlock after two failed attempts; security-critical design | Build-vs-buy, market entry, or any commitment measured in months; strategy where reversal is expensive | Synthesis across many sources where the conclusion drives a large bet; contested questions with conflicting evidence | `medium` | Full evidence brief | Decision, plan, risk register, kill criteria, list of what could not be verified |
67
68
 
68
69
  **Escalate one shape when any of these holds:**
69
70
 
@@ -124,11 +125,8 @@ What actually raises the quality of my answer, in order of impact:
124
125
  under the Operating Manual." Then I write steps you can run at your best:
125
126
  each step with its own check, its own trap named, and its own
126
127
  stop-and-return trigger. A plan without that is half a plan.
127
- 6. **Know what effort buys.** At `low` I stress-test your candidate and give a
128
- verdict. At `medium`/`high` I generate rival solutions and compare them. At
129
- `xhigh`/`max` I build the strongest case for every rival and then try to
130
- break my own winner before you ever see it. Buy the depth the failure cost
131
- justifies, nothing more.
128
+ 6. **Use the medium default well.** Ask for the smallest answer shape that can decide the
129
+ question, and spend the available reasoning on the load-bearing risk.
132
130
  7. **Come back on the same thread.** My context is cached inside a session.
133
131
  The second question in a thread costs a fraction of the first. A new session
134
132
  pays for your whole brief again.
@@ -142,7 +140,7 @@ briefing described above; use the block as your completeness check before
142
140
  sending. Fable must never need to explore.
143
141
 
144
142
  ```
145
- SHAPE: verdict | plan | architecture EFFORT: low | medium | high | xhigh | max
143
+ SHAPE: verdict | plan | architecture
146
144
  DOMAIN: coding | business | research
147
145
  GOAL: <target state in one sentence, and the decision this answer feeds>
148
146
  QUESTIONS:
@@ -229,8 +227,8 @@ reformat, then work with what you have.
229
227
  hear yes.
230
228
  - **Drip-feeding.** Splitting one decision across many small calls, paying
231
229
  session overhead each time.
232
- - **Prestige escalation.** Requesting `max` because the task feels important.
233
- Effort follows failure cost, nothing else.
230
+ - **Prestige escalation.** Changing the medium default because the task feels important,
231
+ without evidence that a harness-scoped override will improve the decision.
234
232
  - **Unbounded questions.** "Any thoughts on this approach?" invites an essay.
235
233
  Ask for a decision with named options.
236
234
  - **Silent adoption.** Pasting Fable's plan straight into execution without
@@ -15,8 +15,8 @@ Announce: "Taking over intent [ID] - [name] for autonomous delivery."
15
15
  **Advisory (not a rule).** At auto-mode start, recommend once that the user run this
16
16
  orchestrating session on the best available thinking model (Fable, Opus, or whatever supersedes
17
17
  them); this is advice only, and dispatched agents keep their configured model, never resolving
18
- to Fable without an explicit `agents.models.<name>` config override. `plastic-advisor` and
19
- `plastic-faux-advisor` are consultation roles the user or this session summons deliberately;
18
+ to Fable without an explicit `agents.models.<name>` config override. Primary Advisor and
19
+ Secondary Advisor are consultation roles the user or this session summons deliberately;
20
20
  the auto pipeline never dispatches them.
21
21
 
22
22
  ## Precondition
@@ -94,16 +94,14 @@ Ask the user one feature question, interactive sessions only:
94
94
 
95
95
  If yes, ask which advisor is the default, exactly two choices:
96
96
  > "Which advisor should be the default?"
97
- > - **Faux Fable** (recommended): Opus 4.8 carrying the frontier reasoning
98
- > instructions. Much cheaper, available on any plan, reasons in the same
99
- > disciplined way. -> append `--advisor faux`
100
- > - **Fable 5**: the frontier model itself. The strongest reasoning available,
101
- > billed through usage credits, so summon it for a few rounds and close it. ->
102
- > append `--advisor real`
97
+ > - **Primary Advisor** (recommended): Fable at medium effort for normal
98
+ > consultation. -> append `--advisor primary`
99
+ > - **Secondary Advisor**: Fable at high effort for explicit escalation. ->
100
+ > append `--advisor secondary`
103
101
 
104
102
  Non-interactive sessions (no tty) skip the question entirely: the install ships with the
105
103
  shipped default, advisor enabled with no `--advisor` flag (the `plastic-agent-advisor`
106
- skill's own routing falls back to `plastic-faux-advisor` at consult time).
104
+ skill's own routing falls back to `plastic-primary-advisor` at consult time).
107
105
 
108
106
  Update flow: pending config questions, including this one, are now announced
109
107
  generically by `plastic-update`'s Step 2, sourced from `config_asks.yml` - not
@@ -81,7 +81,7 @@ Once the user picks an option, run the printed `write-config` command for that
81
81
  option, for example:
82
82
 
83
83
  ```
84
- ruby ~/.plastic/scripts/write-config advisor.claude.default plastic-faux-advisor
84
+ ruby ~/.plastic/scripts/write-config advisor.claude.default plastic-primary-advisor
85
85
  ```
86
86
 
87
87
  If they say "not now" / want to keep the default, run the printed dismissal
@@ -34,18 +34,25 @@ architect:
34
34
  # plastic-enforcer: opus
35
35
  # codex:
36
36
  # plastic-executor: gpt-5.6-terra
37
+ # efforts:
38
+ # claude:
39
+ # plastic-executor: medium
40
+ # codex:
41
+ # plastic-executor: medium
42
+ # Every shipped agent defaults to medium reasoning effort on both harnesses.
43
+ # An agents.efforts.<harness>.<agent> entry is an explicit per-agent override.
37
44
 
38
- # The advisor (intent 185): two consultation agents, plastic-advisor (the real
39
- # advisor, expensive, model fable by default) and plastic-faux-advisor (the
40
- # cheaper imitation, model opus by default, carrying the same reasoning
41
- # discipline inline). advisor.enabled defaults to enabled; missing or
45
+ # The advisors: Primary Advisor and Secondary Advisor. Both use Fable on Claude
46
+ # Code and gpt-6-astra on Codex. Primary uses medium effort; Secondary uses high.
47
+ # advisor.enabled defaults to enabled; missing or
42
48
  # unreadable counts as enabled (fail-open). The claude.default value is an
43
49
  # AGENT NAME, never a model name, so it can point at
44
50
  # a locally registered agent instead. Set at install time via --no-advisor /
45
51
  # --advisor, or uncomment here directly. Each agent's actual model is a plain
46
- # agents.models.claude.<name> override, same mechanism as any other agent.
52
+ # agents.models.claude.<name> override, same mechanism as any other agent. Codex
53
+ # generates both advisors with their role-specific effort.
47
54
  # advisor:
48
55
  # enabled: false # skip installing both advisor agents and the
49
56
  # # agent-advisor skill entirely
50
57
  # claude:
51
- # default: plastic-advisor # which agent the advisor skill routes to
58
+ # default: plastic-primary-advisor # which agent the advisor skill routes to
@@ -3,9 +3,11 @@ node: r1
3
3
  kind: research
4
4
  files: []
5
5
  budget: 60000
6
+ # Optional. When present, use one relative Markdown path under resources/.
7
+ # report: resources/report--topic.md
6
8
  ---
7
9
  # r1 - <what to find out>
8
10
 
9
11
  ## Deposit
10
- <Where the finding lands: a resources/ file, an artifact URL, or a ruling
11
- recorded in the intent's ## Decisions.>
12
+ <Where the finding lands: declare report: above for a resources/ Markdown file,
13
+ or name an artifact URL or a ruling recorded in the intent's ## Decisions.>