pantheon-opencode 1.6.0-beta.5 → 1.6.0-beta.7

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.
Files changed (62) hide show
  1. package/AGENTS.md +27 -820
  2. package/CHANGELOG.md +130 -0
  3. package/README.md +205 -30
  4. package/README.pt-BR.md +47 -23
  5. package/package.json +10 -5
  6. package/plugin.json +1 -1
  7. package/pyproject.toml +3 -1
  8. package/scripts/build-agents-md.mjs +162 -28
  9. package/scripts/doctor.mjs +104 -22
  10. package/scripts/install/agents-md.mjs +2 -2
  11. package/scripts/install/config-migration.mjs +154 -7
  12. package/scripts/install/opencode.mjs +202 -40
  13. package/scripts/install/shared.mjs +115 -7
  14. package/scripts/install/strings.mjs +8 -0
  15. package/scripts/probe-pantheon-cost.mjs +16 -3
  16. package/scripts/run-node-tests.mjs +189 -0
  17. package/scripts/sync-artifacts.mjs +2 -2
  18. package/scripts/test-opencode-v2-sandbox.sh +820 -86
  19. package/skills-lock.json +6 -5
  20. package/src/agents/aphrodite.md +17 -28
  21. package/src/agents/athena.md +1 -0
  22. package/src/agents/demeter.md +8 -18
  23. package/src/agents/hephaestus.md +10 -11
  24. package/src/agents/hermes.md +15 -30
  25. package/src/agents/iris.md +1 -0
  26. package/src/agents/nyx.md +1 -0
  27. package/src/agents/prometheus.md +16 -10
  28. package/src/agents/talos.md +4 -1
  29. package/src/agents/themis.md +5 -3
  30. package/src/agents/zeus.md +17 -280
  31. package/src/instructions/agent-return-format.instructions.md +4 -50
  32. package/src/instructions/backend-standards.instructions.md +2 -0
  33. package/src/instructions/frontend-standards.instructions.md +3 -1
  34. package/src/instructions/memory-protocol.instructions.md +12 -121
  35. package/src/instructions/zeus-anti-stall.instructions.md +8 -111
  36. package/src/instructions/zeus-communication-rules.instructions.md +0 -1
  37. package/src/instructions/zeus-memory-operations.instructions.md +26 -0
  38. package/src/instructions/zeus-timeout-retry.instructions.md +9 -130
  39. package/src/pantheon/secret-scanner.ts +489 -0
  40. package/src/pantheon/v2-delegation-enforce.ts +86 -0
  41. package/src/pantheon/v2-execute-after.ts +186 -0
  42. package/src/pantheon/v2-unsupported.mjs +0 -23
  43. package/src/plugin-v2.ts +254 -102
  44. package/src/plugins/pantheon-hooks.ts +82 -35
  45. package/src/plugins/tui/README.md +14 -0
  46. package/src/plugins/tui/dist/tui.d.ts +11 -8
  47. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  48. package/src/plugins/tui/dist/tui.js +102 -62
  49. package/src/plugins/tui/package-lock.json +30 -33
  50. package/src/plugins/tui/package.json +5 -1
  51. package/src/plugins/tui/src/index.tsx +163 -107
  52. package/src/plugins/tui/tsdown.config.ts +17 -0
  53. package/src/routing.yml +12 -9
  54. package/src/skills/README.md +9 -4
  55. package/src/skills/agent-coordination/SKILL.md +13 -83
  56. package/src/skills/artifact-management/SKILL.md +12 -5
  57. package/src/skills/auto-continue/SKILL.md +38 -28
  58. package/src/skills/code-review-checklist/SKILL.md +5 -5
  59. package/src/skills/council-synthesis/SKILL.md +29 -0
  60. package/src/skills/tdd-with-agents/SKILL.md +18 -10
  61. package/scripts/hooks/scan-secrets.sh +0 -97
  62. package/src/instructions/zeus-council-synthesis.instructions.md +0 -299
@@ -53,16 +53,7 @@ import { homedir } from 'node:os'
53
53
  import { dirname, join } from 'node:path'
54
54
  import { fileURLToPath } from 'node:url'
55
55
  import type { TuiPlugin, TuiPluginApi, TuiPluginModule } from '@opencode-ai/plugin/tui'
56
- import {
57
- createEffect,
58
- createMemo,
59
- createResource,
60
- createSignal,
61
- For,
62
- onCleanup,
63
- onMount,
64
- Show,
65
- } from 'solid-js'
56
+ import { createMemo, createResource, createSignal, For, onCleanup, onMount, Show } from 'solid-js'
66
57
 
67
58
  // ─── Double-load guard (mirrors src/pantheon/plugin-once.ts) ───────────────
68
59
  // Opencode merges global + project plugin paths, so this module can load twice
@@ -749,12 +740,27 @@ async function loadConfig(configPath: string | undefined): Promise<UsageBarConfi
749
740
  }
750
741
  }
751
742
 
752
- /** Vendored usage-bar plugin init: reads config, seeds the kv cache, starts
753
- * the poll loop and registers the `app_bottom` slot. Skips everything (and
743
+ /** Vendored usage-bar plugin init: reads config, seeds the kv cache, registers
744
+ * the `app_bottom` slot, then starts the poll loop. Skips everything (and
754
745
  * registers nothing) when no provider is enabled — mirrors the standalone
755
746
  * plugin's early return. */
756
747
  async function setupUsageBar(api: TuiPluginApi) {
748
+ let disposed = false
749
+ let clockInterval: ReturnType<typeof setInterval> | undefined
750
+ const pollTimeouts = new Set<ReturnType<typeof setTimeout>>()
751
+
752
+ // This optional feature owns timers independently from the sidebar. A slow
753
+ // config read may finish after shutdown, so register cleanup before awaiting
754
+ // anything and check the disposed flag at every async boundary.
755
+ api.lifecycle.onDispose(() => {
756
+ disposed = true
757
+ if (clockInterval !== undefined) clearInterval(clockInterval)
758
+ for (const timeout of pollTimeouts) clearTimeout(timeout)
759
+ pollTimeouts.clear()
760
+ })
761
+
757
762
  const config = await loadConfig(api.state.path?.config)
763
+ if (disposed) return
758
764
  if (api.state.path?.state) opencodeAuthFile = join(api.state.path.state, 'auth.json')
759
765
 
760
766
  const enabled = providers.filter((p) => config.providers[p.id].enabled)
@@ -771,28 +777,6 @@ async function setupUsageBar(api: TuiPluginApi) {
771
777
  const [byStatus, setByStatus] = createSignal<Record<string, StatusIndicator>>({})
772
778
  const [now, setNow] = createSignal(Date.now())
773
779
 
774
- setInterval(() => setNow(Date.now()), 1_000)
775
-
776
- for (const p of enabled) {
777
- const cfg = config.providers[p.id]
778
- const poll = async () => {
779
- // Fetch usage and status concurrently; status pages are CDN-backed and
780
- // never throttle, so we poll them on the same cadence as usage.
781
- const statusP = config.showStatus && p.statusUrl ? fetchStatus(p.statusUrl) : null
782
- const [all, status] = await Promise.all([p.fetchUsage(cfg), statusP])
783
- if (all) {
784
- const windows = all.filter((w) => cfg.show[w.category] && w.resetsAt > Date.now())
785
- setByProvider((prev) => ({ ...prev, [p.id]: windows }))
786
- api.kv.set(`usage-bar.${p.id}.windows`, windows)
787
- }
788
- // `null` means the status fetch failed — keep the last known indicator.
789
- if (status !== null) setByStatus((prev) => ({ ...prev, [p.id]: status }))
790
- // Back off when the usage fetch failed (e.g. 429 — these endpoints throttle).
791
- setTimeout(poll, all ? POLL_MS : POLL_MS * 3)
792
- }
793
- void poll()
794
- }
795
-
796
780
  api.slots.register({
797
781
  order: 60,
798
782
  slots: {
@@ -880,6 +864,46 @@ async function setupUsageBar(api: TuiPluginApi) {
880
864
  },
881
865
  },
882
866
  })
867
+
868
+ // Start background work only once the optional UI slot was accepted. If
869
+ // registration fails, the outer fail-open handler can suppress it without
870
+ // leaving a timer or provider request running in the background.
871
+ clockInterval = setInterval(() => setNow(Date.now()), 1_000)
872
+
873
+ const schedulePoll = (run: () => void, delay: number) => {
874
+ if (disposed) return
875
+ const timeout = setTimeout(() => {
876
+ pollTimeouts.delete(timeout)
877
+ if (!disposed) run()
878
+ }, delay)
879
+ pollTimeouts.add(timeout)
880
+ }
881
+
882
+ for (const p of enabled) {
883
+ const cfg = config.providers[p.id]
884
+ const poll = async () => {
885
+ if (disposed) return
886
+ // Fetch usage and status concurrently; status pages are CDN-backed and
887
+ // never throttle, so we poll them on the same cadence as usage.
888
+ const statusP = config.showStatus && p.statusUrl ? fetchStatus(p.statusUrl) : null
889
+ const [all, status] = await Promise.all([p.fetchUsage(cfg), statusP])
890
+ if (disposed) return
891
+ if (all) {
892
+ const windows = all.filter((w) => cfg.show[w.category] && w.resetsAt > Date.now())
893
+ setByProvider((prev) => ({ ...prev, [p.id]: windows }))
894
+ api.kv.set(`usage-bar.${p.id}.windows`, windows)
895
+ }
896
+ // `null` means the status fetch failed — keep the last known indicator.
897
+ if (status !== null) setByStatus((prev) => ({ ...prev, [p.id]: status }))
898
+ // Back off when the usage fetch failed (e.g. 429 — these endpoints throttle).
899
+ schedulePoll(runPoll, all ? POLL_MS : POLL_MS * 3)
900
+ }
901
+ const runPoll = () => {
902
+ if (disposed) return
903
+ void poll().catch(() => schedulePoll(runPoll, POLL_MS * 3))
904
+ }
905
+ runPoll()
906
+ }
883
907
  }
884
908
 
885
909
  /* ─── Delegations (real-time panel) ────────────────────────
@@ -919,9 +943,9 @@ async function setupUsageBar(api: TuiPluginApi) {
919
943
  * (filterDelegationsToSession) drops every non-focused report — the panel
920
944
  * lists only the focused session.
921
945
  *
922
- * 3. REFRESH — session.created/updated/deleted/status events and
923
- * message.part.updated/removed (via liveStore.version bumps) re-fetch
924
- * children; a 1s safety poll (oh-my-opencode-slim pattern) re-fetches
946
+ * 3. REFRESH — session.created/updated/deleted/status events and live-store
947
+ * subscription notifications re-fetch children; a 1s safety poll
948
+ * (oh-my-opencode-slim pattern) re-fetches
925
949
  * children + re-reads the md so the panel updates EVEN without events.
926
950
  *
927
951
  * 4. DIAGNOSTICS — every re-fetch logs
@@ -947,8 +971,8 @@ async function setupUsageBar(api: TuiPluginApi) {
947
971
  * panel renders EMPTY — zero rows, zero errors.
948
972
  *
949
973
  * The live tool-part lifecycle helpers below remain (tested, exported) but
950
- * are no longer the source of truth: they feed a version signal that merely
951
- * re-triggers the children fetch. Everything is fail-open: a missing
974
+ * are no longer the source of truth: they update the shared live store, whose
975
+ * subscribers re-trigger the children fetch. Everything is fail-open: a missing
952
976
  * children API or directory yields [], and any unreadable input is skipped —
953
977
  * never crash. */
954
978
 
@@ -2631,18 +2655,88 @@ function DelegationRow(props: {
2631
2655
 
2632
2656
  /* ─── Main Sidebar View ──────────────────────────────────── */
2633
2657
 
2634
- /** Plugin-level live delegation store shared with the event subscriptions
2635
- * in `tui()`: the map of live entries + a version signal bumped on every
2636
- * mutation. The View subscribes to the version (in an effect) to refresh the
2637
- * durable child list and also reads the map as an optimistic live source. */
2658
+ /** Plugin-level live delegation store shared by event subscriptions and View.
2659
+ * Mutations notify subscribers so the View can refresh its durable child
2660
+ * list while also reading the map as an optimistic live source. */
2638
2661
  export type LiveDelegationStore = {
2639
2662
  map: Map<string, LiveDelegationEntry>
2640
- /** Reactive version getter — View reads it inside an effect to re-fetch. */
2641
- version: () => number
2642
- /** Bump the version after a live mutation. */
2663
+ /** Subscribe to invalidations consumed by the sidebar's refresh path. */
2664
+ subscribe: (listener: () => void) => () => void
2665
+ /** Notify sidebar subscribers after a live mutation. */
2643
2666
  bump: () => void
2644
2667
  }
2645
2668
 
2669
+ /** Create the observable live store shared by task events and the sidebar. */
2670
+ export function createLiveDelegationStore(): LiveDelegationStore {
2671
+ const listeners = new Set<() => void>()
2672
+ return {
2673
+ map: new Map<string, LiveDelegationEntry>(),
2674
+ subscribe(listener) {
2675
+ listeners.add(listener)
2676
+ return () => listeners.delete(listener)
2677
+ },
2678
+ bump() {
2679
+ for (const listener of listeners) listener()
2680
+ },
2681
+ }
2682
+ }
2683
+
2684
+ /** Register the live task-part events that invalidate the sidebar store. */
2685
+ export function registerLiveDelegationEvents(
2686
+ api: TuiPluginApi,
2687
+ liveStore: LiveDelegationStore,
2688
+ ): () => void {
2689
+ const unsubLive: (() => void)[] = []
2690
+
2691
+ try {
2692
+ unsubLive.push(
2693
+ api.event.on('message.part.updated', (event: unknown) => {
2694
+ // SDK v2 shape: properties.part (v1 drift: properties.info.part).
2695
+ const props = ((event as { properties?: unknown } | null)?.properties ?? {}) as {
2696
+ part?: unknown
2697
+ info?: { part?: unknown }
2698
+ }
2699
+ const part = (props.part ?? props.info?.part) as DelegationToolPart | undefined
2700
+ if (part === undefined) return
2701
+ // beta.6: track the live tool call per child session (panel's
2702
+ // activity line). Fire-and-forget — display-only state.
2703
+ const sample = extractToolActivity(part as Parameters<typeof extractToolActivity>[0])
2704
+ if (sample !== null)
2705
+ trackToolActivity(latestToolActivity, sample.sessionID, sample.activity)
2706
+ if (reduceDelegationToolPart(liveStore.map, part)) liveStore.bump()
2707
+ }),
2708
+ )
2709
+ } catch {
2710
+ /* events API unavailable — children API + 1s poll cover the panel */
2711
+ }
2712
+
2713
+ try {
2714
+ unsubLive.push(
2715
+ api.event.on('message.part.removed', (event: unknown) => {
2716
+ // SDK v2 shape: properties.partID (v1 drift: properties.part.id).
2717
+ const props = ((event as { properties?: unknown } | null)?.properties ?? {}) as {
2718
+ partID?: string
2719
+ part?: { id?: string }
2720
+ }
2721
+ const partID = props.partID ?? props.part?.id
2722
+ if (partID !== undefined && removeDelegationEntry(liveStore.map, partID)) liveStore.bump()
2723
+ }),
2724
+ )
2725
+ } catch {
2726
+ /* events API unavailable — children API + 1s poll cover the panel */
2727
+ }
2728
+
2729
+ return () => {
2730
+ for (const unsub of unsubLive) {
2731
+ try {
2732
+ unsub()
2733
+ } catch {
2734
+ /* ignore */
2735
+ }
2736
+ }
2737
+ }
2738
+ }
2739
+
2646
2740
  function View(props: {
2647
2741
  api: TuiPluginApi
2648
2742
  sessionID: string | undefined
@@ -2758,7 +2852,7 @@ function View(props: {
2758
2852
  // means the event bus isn't delivering, and the 1s poll is what keeps
2759
2853
  // the panel honest.
2760
2854
  let eventRefreshCount = 0
2761
- // In-flight guard: overlap between the poll, events and the version effect
2855
+ // In-flight guard: overlap between the poll, events and store subscribers
2762
2856
  // collapses into one fetch — no duplicate work, no duplicate entries.
2763
2857
  let delegationsInflight: Promise<void> | null = null
2764
2858
  const refreshDelegations = () => {
@@ -2910,14 +3004,17 @@ function View(props: {
2910
3004
  /* events API not available — the 1s poll still covers it */
2911
3005
  }
2912
3006
 
2913
- // message.part.updated/removed → liveStore.version() bumps (tui()):
2914
- // subscribe here so the panel ALSO re-fetches children when tool-part
2915
- // events DO arrive and the updated live row is rendered immediately.
2916
- createEffect(() => {
2917
- props.liveStore.version() // subscribe to live mutations
2918
- eventRefreshCount += 1
2919
- void refreshDelegations()
2920
- })
3007
+ // Task-part events invalidate the same store the panel reads, refreshing
3008
+ // children when those events arrive and making optimistic live rows visible.
3009
+ cleanup.push(
3010
+ props.liveStore.subscribe(() => {
3011
+ eventRefreshCount += 1
3012
+ void refreshDelegations()
3013
+ }),
3014
+ )
3015
+ // Fetch the initial state; future updates use the store subscription above.
3016
+ eventRefreshCount += 1
3017
+ void refreshDelegations()
2921
3018
 
2922
3019
  // Safety poll (OMO-slim pattern): 1s re-fetch children + md + tick the
2923
3020
  // elapsed counter. Guarantees the panel updates even with zero events.
@@ -2935,8 +3032,8 @@ function View(props: {
2935
3032
  // compacting, so after a compaction/attach the live map would start
2936
3033
  // empty even though the session still holds the delegation tool parts.
2937
3034
  // Re-seed the live map from the session's existing parts (in message
2938
- // order) right after the subscriptions are registered — the version
2939
- // bump re-triggers the children fetch. Fail-open: if the SDK access is
3035
+ // order) right after the subscriptions are registered — the store
3036
+ // notification re-triggers the children fetch. Fail-open: if the SDK access is
2940
3037
  // unavailable we skip — the children API + the 1s poll keep the panel
2941
3038
  // working.
2942
3039
  try {
@@ -3070,63 +3167,22 @@ const tui: TuiPlugin = (api, _options, _meta) => {
3070
3167
  .catch(() => setVersion(null))
3071
3168
 
3072
3169
  // Vendored feature (MIT): AI subscription usage gauges.
3073
- void setupUsageBar(api) // async init — never blocks sidebar registration
3170
+ // Usage indicators are optional: a config, storage, or slot failure must
3171
+ // never turn an otherwise healthy TUI startup into an unhandled rejection.
3172
+ void setupUsageBar(api).catch(() => undefined)
3074
3173
 
3075
- // ── Live delegation store (tool-part tracker, kept as a REFRESH
3076
- // TRIGGER) ──
3174
+ // ── Live delegation store (tool-part tracker + sidebar invalidation) ──
3077
3175
  // The Delegations panel's PRIMARY source is `api.client.session.children`
3078
3176
  // (delegations-sidebar pattern) — `message.part.updated` may not fire for
3079
3177
  // the native task tool on runtime 1.18.13 (the "(0)" symptom). The
3080
- // tool-part lifecycle below still tracks `task` parts and bumps a version
3081
- // signal the View subscribes to: when part events DO arrive, the panel
3178
+ // tool-part lifecycle below still tracks `task` parts and invalidates the
3179
+ // store subscription consumed by the View: when part events DO arrive, the panel
3082
3180
  // re-fetches children. Fail-open: if the events API is unavailable nothing
3083
3181
  // subscribes and the 1s safety poll keeps the panel working (never crash).
3084
- const [liveVersion, setLiveVersion] = createSignal(0)
3085
- const liveStore: LiveDelegationStore = {
3086
- map: new Map<string, LiveDelegationEntry>(),
3087
- version: liveVersion,
3088
- bump: () => setLiveVersion((v) => v + 1),
3089
- }
3090
- const unsubLive: (() => void)[] = []
3091
-
3092
- try {
3093
- unsubLive.push(
3094
- api.event.on('message.part.updated', (event: any) => {
3095
- // SDK v2 shape: properties.part (v1 drift: properties.info.part).
3096
- const props = (event?.properties ?? {}) as { part?: unknown; info?: { part?: unknown } }
3097
- const part = (props.part ?? props.info?.part) as DelegationToolPart | undefined
3098
- if (part === undefined) return
3099
- // beta.6: track the live tool call per child session (panel's
3100
- // activity line). Fire-and-forget — display-only state.
3101
- const sample = extractToolActivity(part as any)
3102
- if (sample !== null)
3103
- trackToolActivity(latestToolActivity, sample.sessionID, sample.activity)
3104
- if (reduceDelegationToolPart(liveStore.map, part)) liveStore.bump()
3105
- }),
3106
- )
3107
- } catch {
3108
- /* events API unavailable — children API + 1s poll cover the panel */
3109
- }
3110
- try {
3111
- unsubLive.push(
3112
- api.event.on('message.part.removed', (event: any) => {
3113
- // SDK v2 shape: properties.partID (v1 drift: properties.part.id).
3114
- const props = (event?.properties ?? {}) as { partID?: string; part?: { id?: string } }
3115
- const partID = props.partID ?? props.part?.id
3116
- if (partID !== undefined && removeDelegationEntry(liveStore.map, partID)) liveStore.bump()
3117
- }),
3118
- )
3119
- } catch {
3120
- /* events API unavailable — children API + 1s poll cover the panel */
3121
- }
3182
+ const liveStore = createLiveDelegationStore()
3183
+ const unsubscribeLive = registerLiveDelegationEvents(api, liveStore)
3122
3184
  api.lifecycle.onDispose(() => {
3123
- for (const unsub of unsubLive) {
3124
- try {
3125
- unsub()
3126
- } catch {
3127
- /* ignore */
3128
- }
3129
- }
3185
+ unsubscribeLive()
3130
3186
  liveStore.map.clear()
3131
3187
  })
3132
3188
 
@@ -1,4 +1,5 @@
1
1
  import { readFileSync } from 'node:fs'
2
+ import { appendFile, readdir, readFile } from 'node:fs/promises'
2
3
  import { join } from 'node:path'
3
4
  import { fileURLToPath } from 'node:url'
4
5
  import solid from 'rolldown-plugin-solid'
@@ -9,6 +10,21 @@ const pkg = JSON.parse(readFileSync(join(__dirname, 'package.json'), 'utf8')) as
9
10
  version: string
10
11
  }
11
12
 
13
+ async function ensureDistArtifactsEndWithNewline(): Promise<void> {
14
+ const dist = join(__dirname, 'dist')
15
+ const entries = await readdir(dist, { withFileTypes: true })
16
+
17
+ await Promise.all(
18
+ entries
19
+ .filter((entry) => entry.isFile())
20
+ .map(async ({ name }) => {
21
+ const path = join(dist, name)
22
+ const contents = await readFile(path, 'utf8')
23
+ if (!contents.endsWith('\n')) await appendFile(path, '\n')
24
+ }),
25
+ )
26
+ }
27
+
12
28
  export default defineConfig({
13
29
  entry: { tui: 'src/index.tsx', server: 'src/server.ts' },
14
30
  format: ['esm'],
@@ -33,4 +49,5 @@ export default defineConfig({
33
49
  deps: {
34
50
  neverBundle: [/^@opencode-ai\//, /^@opentui\//, /^solid-js/],
35
51
  },
52
+ onSuccess: ensureDistArtifactsEndWithNewline,
36
53
  })
package/src/routing.yml CHANGED
@@ -133,7 +133,7 @@ agents:
133
133
  - artifact-management
134
134
  - context-compression
135
135
  - auto-continue
136
- - incremental-implementation
136
+ - council-synthesis
137
137
  athena:
138
138
  role: Strategic planner
139
139
  reasoning_effort: high
@@ -188,8 +188,6 @@ agents:
188
188
  - pantheon_code_mode
189
189
  skills:
190
190
  - tdd-with-agents
191
- - file-prompts
192
- - streaming-patterns
193
191
  - git-workflow-and-versioning
194
192
  - incremental-implementation
195
193
  aphrodite:
@@ -211,7 +209,7 @@ agents:
211
209
  skills:
212
210
  - tdd-with-agents
213
211
  - visual-review-pipeline
214
- - file-prompts
212
+ - incremental-implementation
215
213
  demeter:
216
214
  role: Database specialist
217
215
  reasoning_effort: medium
@@ -459,6 +457,8 @@ handoffs:
459
457
  (priority-aware, budget-allocated), archive IMPL/REVIEW to 02-progress-log.md,
460
458
  update _xref/index.md cross-references.'
461
459
 
460
+ # Canonical explicit fallback map for Zeus timeout/retry policy. Evaluate
461
+ # left-to-right; an absent agent entry means escalate (never guess a fallback).
462
462
  fallback_chains:
463
463
  apollo:
464
464
  - athena
@@ -518,7 +518,7 @@ background_delegation:
518
518
  prune_ttl_ms: 86400000 # 24h
519
519
  read_only_agents: [apollo, gaia]
520
520
  session_max: 3
521
- retry_count: 1
521
+ retry_count: 1 # one retry after an initial transient failure; no retry loops
522
522
  # ── O5: permission.task — glob rules for which subagents an agent may
523
523
  # invoke (last matching rule wins; deny removes the agent from the delegate
524
524
  # tool description entirely — prevents circular delegation at the
@@ -551,7 +551,10 @@ hashline:
551
551
  full_auto:
552
552
  enabled: false # opt-in: goal continuations are OFF by default
553
553
  max_continuations: 25 # hard cap on goal continuations per session
554
- # Wave 3 (PR #46): full-auto goal loop. One active goal per session
555
- # (pending → in_progress → done); while active, idle sessions are
556
- # continued automatically toward the objective. Documentation mirror —
557
- # the plugin resolves behavior in code (GOAL_LOOP_DEFAULTS).
554
+ # Full-auto only continues a task/scope explicitly authorized by the user.
555
+ # It never authorizes auth/security gates, risky data/schema or destructive
556
+ # operations, global config, broad permissions, production deploy, push, or merge.
557
+ # Low-risk execution is proportional: no forced plan/discovery/council/artifact
558
+ # for a bounded fix; use focused verification. Documentation mirror — runtime
559
+ # behavior is implemented in the plugin (GOAL_LOOP_DEFAULTS).
560
+ # Wave 3 (PR #46): one active goal per session (pending → in_progress → done).
@@ -4,14 +4,14 @@
4
4
 
5
5
  Skills are reference modules loaded on demand by agents. Each skill provides domain-specific knowledge — architecture patterns, security checklists, optimization strategies, and implementation guides. Agents load skills when their task matches the skill's description, keeping context focused and token-efficient.
6
6
 
7
- There are **20 skills** divided into **5 domains**.
7
+ There are **21 skills** divided into **5 domains**.
8
8
 
9
9
  ## Skills by Domain
10
10
 
11
11
  ### Domain 1: Orchestration & Workflow
12
12
 
13
13
  1. **agent-coordination** — `agent-coordination/SKILL.md`
14
- - Multi-agent orchestration with model routing, category delegation, and sprint management.
14
+ - Lightweight coordination for substantial tasks with multiple independent specialists.
15
15
  - Used by: Zeus
16
16
 
17
17
  2. **artifact-management** — `artifact-management/SKILL.md`
@@ -34,6 +34,10 @@ There are **20 skills** divided into **5 domains**.
34
34
  - Pin session objectives to prevent scope creep across long multi-agent sessions.
35
35
  - Used by: Zeus, Mnemosyne
36
36
 
37
+ - **council-synthesis** — `council-synthesis/SKILL.md`
38
+ - Full structured council workflow, loaded only for `/pantheon` or a material multi-perspective decision.
39
+ - Used by: Zeus
40
+
37
41
  ### Domain 2: Development Tools
38
42
 
39
43
  7. **clonedeps** — `clonedeps/SKILL.md`
@@ -46,7 +50,7 @@ There are **20 skills** divided into **5 domains**.
46
50
 
47
51
  9. **incremental-implementation** — `incremental-implementation/SKILL.md`
48
52
  - Implement in thin vertical slices — one commit per task, testable, rollback-safe.
49
- - Used by: Zeus, Hermes, Aphrodite, Demeter, Prometheus, Talos
53
+ - Used by: Hermes, Aphrodite, Demeter, Prometheus, Talos
50
54
 
51
55
  10. **loop-engineering** — `loop-engineering/SKILL.md`
52
56
  - Iterative refinement pattern for complex problems — solve, review, improve, repeat in controlled cycles.
@@ -129,7 +133,7 @@ The `SKILL.md` file contains YAML frontmatter with `name`, `description`, and pl
129
133
  | 6 | session-goal | Orchestration & Workflow | Zeus, Mnemosyne |
130
134
  | 7 | clonedeps | Development Tools | Hermes, Hephaestus |
131
135
  | 8 | git-workflow-and-versioning | Development Tools | Hermes, Prometheus, Iris |
132
- | 9 | incremental-implementation | Development Tools | Zeus, Hermes, Aphrodite, Demeter, Prometheus, Talos |
136
+ | 9 | incremental-implementation | Development Tools | Hermes, Aphrodite, Demeter, Prometheus, Talos |
133
137
  | 10 | loop-engineering | Development Tools | All agents |
134
138
  | 11 | reflect | Development Tools | All agents |
135
139
  | 12 | simplify | Development Tools | All agents |
@@ -141,6 +145,7 @@ The `SKILL.md` file contains YAML frontmatter with `name`, `description`, and pl
141
145
  | 18 | spec-driven-development | Planning | Athena |
142
146
  | 19 | verification-planning | Planning | Athena, Zeus |
143
147
  | 20 | visual-review-pipeline | Frontend Development | Aphrodite |
148
+ | 21 | council-synthesis | Orchestration & Workflow | Zeus |
144
149
 
145
150
  ---
146
151
 
@@ -1,95 +1,25 @@
1
1
  ---
2
2
  name: agent-coordination
3
- description: "Multi-agent orchestration with model routing, category delegation, and sprint management. Use for coordinating Pantheon agents."
3
+ description: "Coordinate two or more specialists for substantial multi-phase work. Skip for questions, bounded fixes, and one-agent tasks."
4
4
  context: fork
5
5
  globs: []
6
6
  alwaysApply: false
7
7
  ---
8
8
 
9
- # Agent Coordination
9
+ # Agent coordination
10
10
 
11
- Master guide to orchestrating the multi-agent system. Includes category routing, model selection, and sprint management for rapid, TDD-driven feature development.
11
+ Load only when the work genuinely needs multiple specialists or dependent phases. For the default routing, retry, and safety rules, follow Zeus and `pantheon://routing`.
12
12
 
13
- ---
14
-
15
- ## Agent Hierarchy
16
-
17
- See `AGENTS.md` for the full agent table.
18
-
19
- ---
20
-
21
- ## Category Routing
22
-
23
- Route tasks to optimized agents based on category instead of specifying agents manually:
24
-
25
- | Category | Agent | Use For |
26
- |----------|-------|---------|
27
- | **Deep** | Athena, Hephaestus | Complex planning, AI pipelines |
28
- | **Quick** | Talos, Apollo | Fast fixes, codebase search |
29
- | **Ultrabrain** | Zeus | Multi-agent orchestration, model routing |
30
-
31
- ---
32
-
33
- ## Sprint Workflow
34
-
35
- ```
36
- 1. User describes feature
37
- 2. @athena creates PLAN with phases and agents
38
- 3. User approves PLAN (GATE 1)
39
- 4. Zeus dispatches agents to phases (parallel when possible)
40
- 5. Each agent: TDD cycle → writes IMPL artifact
41
- 6. @themis reviews all phases (GATE 2)
42
- 7. User reviews Themis findings
43
- 8. If approved → user commits (GATE 3)
44
- 9. @mnemosyne updates memory bank
45
- ```
46
-
47
- ---
48
-
49
- ## Parallel Execution Declaration
13
+ ## Lean coordination
50
14
 
51
- ```
52
- 🔀 PARALLEL EXECUTION — Phase 2
53
- Running simultaneously:
54
- - @hermes → backend tests → .tmp/IMPL-phase2-hermes.md
55
- - @aphrodite → frontend → .tmp/IMPL-phase2-aphrodite.md
56
- - @demeter → migrations → .tmp/IMPL-phase2-demeter.md
57
- Themis reviews all three after completion.
58
- ```
59
-
60
- ---
61
-
62
- ## Artifact Protocol
63
-
64
- All phase outputs go to `.pantheon/memory-bank/.tmp/`. See `skill: artifact-management` for the complete protocol (who generates what, templates, lifecycle).
65
-
66
- ---
67
-
68
- ## Safety Gates
69
-
70
- | Gate | When | Why |
71
- |------|------|-----|
72
- | **GATE 1** | After PLAN | User confirms scope |
73
- | **GATE 2** | After Themis review | User sees changes |
74
- | **GATE 3** | Before git commit | User controls history |
75
-
76
- ---
77
-
78
- ## Model Selection
79
-
80
- Model routing is handled by Prometheus and the platform configuration. Zeus delegates model selection to the tier system (`fast` / `default` / `coding` / `premium`).
81
-
82
- - **Deep tasks** → High-quality models (Claude, GPT-4)
83
- - **Quick tasks** → Fast/cheap models (Haiku, 4o-mini)
84
- - **Visual tasks** → Multimodal models (GPT-4V, Claude Vision)
85
- - **Cost optimization** → Route to cheapest model that meets quality bar
86
-
87
- ---
15
+ 1. State the desired outcome and split only work with distinct ownership or dependencies. Ask @athena to plan only when scope, architecture, or acceptance criteria are materially unclear.
16
+ 2. Assign each bounded task to the most specific configured specialist. Include relevant context, expected result, and focused verification; do not make @apollo rediscover context the implementer can inspect directly.
17
+ 3. Dispatch independent tasks together only when native background delegation is enabled. Otherwise use normal `task()` calls. Do not create waves for a single task or poll without a returned task ID.
18
+ 4. Collect summaries once, resolve dependencies, and report evidence, remaining risk, and blockers. Add @themis, artifacts, or user approval only where the task's risk or requested workflow requires them.
88
19
 
89
- ## Anti-Patterns
20
+ ## Boundaries
90
21
 
91
- - ❌ Zeus doing implementation work (orchestrates, doesn't code)
92
- - ❌ Skipping TDD cycle (RED → GREEN → REFACTOR)
93
- - ❌ Auto-committing without user approval
94
- - ❌ Parallel phases with dependencies (order matters)
95
- - ❌ Ignoring Themis CRITICAL findings
22
+ - Zeus coordinates; implementation agents inspect, edit, and verify their assigned scope.
23
+ - Preserve auth/security, data/schema, destructive-action, production, and permission gates.
24
+ - Do not commit, push, merge, deploy, or broaden scope without explicit authorization.
25
+ - Model selection comes from the active configured preset; do not invent a model tier or price.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: artifact-management
3
- description: "Structured artifact trail for feature implementations — plans, implementations, reviews, and decisions."
3
+ description: "Structured artifacts for planned, multi-phase, or materially risky implementation work."
4
4
  context: fork
5
5
  globs: []
6
6
  alwaysApply: false
@@ -8,7 +8,7 @@ alwaysApply: false
8
8
 
9
9
  # Artifact Management
10
10
 
11
- Structured artifact trail system for documenting feature implementations. Defines what, where, and how agents produce phase outputs.
11
+ Structured artifact trail for planned, multi-phase, or materially risky implementation work. Artifacts are not a prerequisite for simple fixes or read-only investigation.
12
12
 
13
13
  ---
14
14
 
@@ -55,6 +55,13 @@ All ephemeral artifacts live in `.pantheon/memory-bank/.tmp/` — gitignored and
55
55
 
56
56
  > **Zeus does NOT generate artifacts.** He orchestrates agents that generate them.
57
57
 
58
+ ## Proportional Use
59
+
60
+ - Create PLAN/IMPL/REVIEW artifacts for planned multi-phase work or when risk, auditability, or an explicit request needs a durable phase trail.
61
+ - A bounded, reversible fix should be investigated only as far as needed, implemented, verified with focused checks, and returned as a concise summary. Do not create PLAN, IMPL, or REVIEW artifacts for it.
62
+ - Read-only lookup or trivial discovery needs no DISC artifact; use one only when findings are broad enough to be reused or drive a material decision.
63
+ - The absence of an artifact never waives Themis review or human approval for auth/security, data/schema/migrations, production-impacting work, or sensitive actions.
64
+
58
65
  ---
59
66
 
60
67
  ## Templates
@@ -103,9 +110,9 @@ All ephemeral artifacts live in `.pantheon/memory-bank/.tmp/` — gitignored and
103
110
 
104
111
  ## Human Pause Points
105
112
 
106
- 1. **After PLAN** → user reads `.tmp/PLAN-<feature>.md` and approves
107
- 2. **After REVIEW** → user reads `.tmp/REVIEW-<feature>.md` and validates focus items
108
- 3. **Before git commit** → user executes manually
113
+ 1. **After a required PLAN** → pause only when a material scope/risk decision needs approval.
114
+ 2. **After required REVIEW** → preserve auth/security/data/schema and other sensitive approval gates.
115
+ 3. **Before commit/push/merge/deploy or destructive/global action** → require explicit human approval.
109
116
 
110
117
  ---
111
118