@zalom/plastic 2.0.0-alpha.24 → 2.0.0-alpha.25

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.
@@ -9,7 +9,7 @@ description: |
9
9
  approaches and kill criteria for architecture, one-way doors, or deadlocks. Model is set by config
10
10
  (agents.models.claude.plastic-advisor); fable is the shipped default.
11
11
  model: fable
12
- effort: xhigh
12
+ effort: medium
13
13
  ---
14
14
 
15
15
  You are the advisor, consulted for expensive reasoning per the shipped Advisor
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zalom/plastic",
3
- "version": "2.0.0-alpha.24",
3
+ "version": "2.0.0-alpha.25",
4
4
  "description": "Intent-driven idea development system for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -102,6 +102,17 @@ module AgentModels
102
102
  models_section(global_config, harness: harness).merge(models_section(project_config, harness: harness))
103
103
  end
104
104
 
105
+ def effort_override_map(project_config: {}, global_config: {}, harness: "claude")
106
+ efforts_section(global_config, harness).merge(efforts_section(project_config, harness))
107
+ end
108
+
109
+ def efforts_section(config, harness)
110
+ agents = config.is_a?(Hash) ? config["agents"] : nil
111
+ efforts = agents.is_a?(Hash) ? agents["efforts"] : nil
112
+ section = efforts.is_a?(Hash) ? efforts[harness] : nil
113
+ section.is_a?(Hash) ? section : {}
114
+ end
115
+
105
116
  # The model_reasoning_effort for a Plastic tier alias, or nil for any value that is not
106
117
  # one of the three shipped aliases (the caller treats nil as a literal Codex model id).
107
118
  def effort_for(value)
@@ -412,7 +412,7 @@ class Doctor
412
412
  fix_hint: "Re-run the Plastic installer: npx @zalom/plastic@latest --claude (prunes " \
413
413
  "stale launchers). The plastic- prefix is reserved for Plastic's own hooks: " \
414
414
  "if one of these is yours, rename it (for example to ~/.claude/hooks/" \
415
- "writing-style) and re-register it in settings.json before re-running."
415
+ "plain-writing) and re-register it in settings.json before re-running."
416
416
  )
417
417
  end
418
418
 
@@ -1081,7 +1081,7 @@ class InstallerCore
1081
1081
  installed += install_skills_flat(skills_source, skills_root, exclude: skill_exclude) if File.directory?(skills_source)
1082
1082
 
1083
1083
  # Copy agent role files into <dir>/agents (manifest-tracked, pruned on update)
1084
- installed += install_agents(File.join(config[:dir], "agents"), models: agent_model_overrides, advisor_enabled: advisor_enabled?)
1084
+ installed += install_agents(File.join(config[:dir], "agents"), models: agent_model_overrides, efforts: agent_effort_overrides, advisor_enabled: advisor_enabled?)
1085
1085
 
1086
1086
  # Write VERSION
1087
1087
  version_file = File.join(plastic_dir, "VERSION")
@@ -1314,7 +1314,7 @@ class InstallerCore
1314
1314
  skills_source = File.join(package_root, "skills")
1315
1315
  skill_exclude = advisor_enabled? ? [] : ["agent-advisor"]
1316
1316
  installed += install_skills_flat(skills_source, File.join(config[:dir], "skills"), exclude: skill_exclude) if File.directory?(skills_source)
1317
- installed += install_agents(File.join(config[:dir], "agents"), models: agent_model_overrides, advisor_enabled: advisor_enabled?)
1317
+ installed += install_agents(File.join(config[:dir], "agents"), models: agent_model_overrides, efforts: agent_effort_overrides, advisor_enabled: advisor_enabled?)
1318
1318
 
1319
1319
  # Uniform per-agent record (intent 210, D2): write VERSION alongside the manifest,
1320
1320
  # the same shape install_claude already writes.
@@ -1365,7 +1365,7 @@ class InstallerCore
1365
1365
  # AgentModels::CONSULTATION_AGENTS file entirely (both plastic-advisor and
1366
1366
  # plastic-faux-advisor), so a user who declined the advisor never gets either
1367
1367
  # agent installed.
1368
- def install_agents(agents_root, models: {}, advisor_enabled: true)
1368
+ def install_agents(agents_root, models: {}, efforts: {}, advisor_enabled: true)
1369
1369
  sources = Dir.glob(File.join(package_root, "agents", "*.md"))
1370
1370
  return [] if sources.empty?
1371
1371
 
@@ -1377,9 +1377,13 @@ class InstallerCore
1377
1377
  sources.map do |src|
1378
1378
  dest = File.join(agents_root, File.basename(src))
1379
1379
  basename = File.basename(src, ".md")
1380
- override = models[basename]
1381
- if override
1382
- File.write(dest, rewrite_model_line(File.read(src), override))
1380
+ model = models[basename]
1381
+ effort = efforts[basename]
1382
+ if model || effort
1383
+ content = File.read(src)
1384
+ content = rewrite_model_line(content, model) if model
1385
+ content = rewrite_effort_line(content, effort) if effort
1386
+ File.write(dest, content)
1383
1387
  else
1384
1388
  FileUtils.cp(src, dest)
1385
1389
  end
@@ -1393,6 +1397,12 @@ class InstallerCore
1393
1397
  content.sub(/^model:[^\n]*$/, "model: #{model}")
1394
1398
  end
1395
1399
 
1400
+ def rewrite_effort_line(content, effort)
1401
+ return content.sub(/^effort:[^\n]*$/, "effort: #{effort}") if content.match?(/^effort:/)
1402
+
1403
+ content.sub(/^(model:[^\n]*)$/) { "#{Regexp.last_match(1)}\neffort: #{effort}" }
1404
+ end
1405
+
1396
1406
  # Resolve per-agent model overrides for this install: project config (when a
1397
1407
  # project dir is known) overlaid on global config, scoped to `harness`
1398
1408
  # ("claude" or "codex"). Defaults are NOT included, so unconfigured agents
@@ -1416,6 +1426,12 @@ class InstallerCore
1416
1426
  AgentModels.override_map(project_config: project_config, global_config: global_config, harness: harness)
1417
1427
  end
1418
1428
 
1429
+ def agent_effort_overrides(project_dir = nil, harness: "claude")
1430
+ global_config = load_config_yaml(File.join(plastic_home, "config.yml"))
1431
+ project_config = project_dir ? load_config_yaml(File.join(project_dir, ".plastic_store", "config.yml")) : {}
1432
+ AgentModels.effort_override_map(project_config: project_config, global_config: global_config, harness: harness)
1433
+ end
1434
+
1419
1435
  # advisor.enabled: project overlays global, missing or malformed counts as
1420
1436
  # enabled (fail-open). Harness-blind: false skips both advisor agents and the
1421
1437
  # agent-advisor skill on every installed harness.
@@ -1566,7 +1582,7 @@ class InstallerCore
1566
1582
  puts " \u{2139}\u{fe0f} Kept #{kept.size} hook(s) Plastic does not own, named with the reserved plastic- prefix:"
1567
1583
  kept.each { |cmd| puts " - #{tilde(cmd.to_s)}" }
1568
1584
  puts " The plastic- prefix is reserved for Plastic's own hooks. Rename yours (for"
1569
- puts " example ~/.claude/hooks/writing-style) so a future update never mistakes it."
1585
+ puts " example ~/.claude/hooks/plain-writing) so a future update never mistakes it."
1570
1586
  end
1571
1587
 
1572
1588
  # --- settings.json merge (read-modify-write, never clobber) ---
@@ -120,7 +120,7 @@ renders. The two never merge.
120
120
 
121
121
  ## Brevity: point, don't repeat
122
122
 
123
- Surface rules are owned by the `writing-style` skill. This contract does not restate them. Its
123
+ Surface rules are owned by the `plain-writing` skill. This contract does not restate them. Its
124
124
  job is naming which screen prints when, not the wording inside it - `report-screen` derives
125
125
  every cell from the record (D14), so there is no prose left to style here.
126
126