@plainconceptsplatform/agent-harness 2.0.0 → 2.1.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.
Files changed (117) hide show
  1. package/README.md +426 -419
  2. package/package.json +3 -3
  3. package/src/commands/join.js +244 -244
  4. package/src/commands/shared.js +27 -27
  5. package/src/commands/single.js +79 -79
  6. package/src/commands/update.js +109 -109
  7. package/src/commands/wizard.js +134 -134
  8. package/src/content/.agents/skills/browser-automation/SKILL.md +66 -66
  9. package/src/content/.agents/skills/pc-guardrails-generic/SKILL.md +68 -68
  10. package/src/content/.agents/skills/pc-guardrails-project/SKILL.md +8 -8
  11. package/src/content/.agents/skills/pc-make-architecture/SKILL.md +51 -51
  12. package/src/content/.agents/skills/pc-make-architecture/structure-template.md +38 -38
  13. package/src/content/.agents/skills/pc-make-design/SKILL.md +68 -68
  14. package/src/content/.agents/skills/pc-make-engineer/SKILL.md +219 -219
  15. package/src/content/.agents/skills/pc-make-engineer/signal-mapping.md +68 -68
  16. package/src/content/.agents/skills/pc-make-engineer/template.md +81 -81
  17. package/src/content/.agents/skills/pc-make-evidence-scaffold/SKILL.md +18 -18
  18. package/src/content/.agents/skills/pc-make-evidence-scaffold/evidence-contract.md +29 -29
  19. package/src/content/.agents/skills/pc-make-guardrails/SKILL.md +74 -74
  20. package/src/content/.agents/skills/pc-make-guardrails/category-reference.md +68 -68
  21. package/src/content/.agents/skills/pc-make-merge-risk-assess/SKILL.md +70 -70
  22. package/src/content/.agents/skills/pc-make-merge-risk-assess/category-reference.md +98 -98
  23. package/src/content/.agents/skills/pc-make-user-model/SKILL.md +66 -66
  24. package/src/content/.agents/skills/pc-ops-evidence/SKILL.md +127 -127
  25. package/src/content/.agents/skills/pc-ops-ship/SKILL.md +18 -18
  26. package/src/content/.agents/skills/pc-plan-apply/SKILL.md +83 -83
  27. package/src/content/.agents/skills/pc-plan-apply/simple-mode.md +21 -21
  28. package/src/content/.agents/skills/pc-plan-archive/SKILL.md +63 -63
  29. package/src/content/.agents/skills/pc-plan-explore/SKILL.md +9 -9
  30. package/src/content/.agents/skills/pc-plan-goal/SKILL.md +94 -94
  31. package/src/content/.agents/skills/pc-plan-goal/branching.md +30 -30
  32. package/src/content/.agents/skills/pc-plan-goal/failure-policy.md +30 -30
  33. package/src/content/.agents/skills/pc-plan-goal/output-mode.md +9 -9
  34. package/src/content/.agents/skills/pc-plan-goal/output.md +68 -68
  35. package/src/content/.agents/skills/pc-plan-propose/SKILL.md +125 -125
  36. package/src/content/.agents/skills/pc-plan-propose/task-annotation.md +39 -39
  37. package/src/content/.agents/skills/pc-plan-quick/SKILL.md +62 -62
  38. package/src/content/.agents/skills/pc-plan-story/SKILL.md +146 -146
  39. package/src/content/.agents/skills/pc-repo-audit/SKILL.md +44 -44
  40. package/src/content/.agents/skills/pc-repo-help/SKILL.md +91 -91
  41. package/src/content/.agents/skills/pc-repo-initialize/SKILL.md +130 -130
  42. package/src/content/.agents/skills/pc-repo-onboard/SKILL.md +87 -87
  43. package/src/content/.agents/skills/pc-repo-verify/SKILL.md +34 -34
  44. package/src/content/.agents/skills/pc-userstory-az/SKILL.md +157 -157
  45. package/src/content/.agents/skills/pc-userstory-browser/SKILL.md +132 -132
  46. package/src/content/.agents/skills/pc-userstory-gh/SKILL.md +120 -120
  47. package/src/content/.agents/skills/pc-userstory-jira/SKILL.md +131 -131
  48. package/src/content/.opencode/_gitignore +9 -7
  49. package/src/content/.opencode/commands/init.md +5 -5
  50. package/src/content/.opencode/commands/make-architecture.md +5 -5
  51. package/src/content/.opencode/commands/make-design.md +5 -5
  52. package/src/content/.opencode/commands/make-engineer.md +5 -5
  53. package/src/content/.opencode/commands/make-evidence-scaffold.md +5 -5
  54. package/src/content/.opencode/commands/make-guardrails.md +5 -5
  55. package/src/content/.opencode/commands/make-user-model.md +5 -5
  56. package/src/content/.opencode/commands/ops-backlog.md +10 -10
  57. package/src/content/.opencode/commands/ops-evidence.md +9 -9
  58. package/src/content/.opencode/commands/ops-review.md +8 -8
  59. package/src/content/.opencode/commands/ops-ship.md +9 -9
  60. package/src/content/.opencode/commands/plan-apply.md +9 -9
  61. package/src/content/.opencode/commands/plan-archive.md +5 -5
  62. package/src/content/.opencode/commands/plan-explore.md +9 -9
  63. package/src/content/.opencode/commands/plan-goal.md +5 -5
  64. package/src/content/.opencode/commands/plan-propose.md +9 -9
  65. package/src/content/.opencode/commands/plan-quick.md +5 -5
  66. package/src/content/.opencode/commands/plan-story.md +9 -9
  67. package/src/content/.opencode/commands/repo-audit.md +5 -5
  68. package/src/content/.opencode/commands/repo-help.md +5 -5
  69. package/src/content/.opencode/commands/repo-initialize.md +5 -5
  70. package/src/content/.opencode/commands/repo-onboard.md +5 -5
  71. package/src/content/.opencode/commands/repo-verify.md +5 -5
  72. package/src/content/.opencode/plugins/pc-subagent-monitor.js +139 -139
  73. package/src/content/.opencode/plugins/pc-subagent-tiers.js +281 -179
  74. package/src/content/.opencode/plugins/pc-system-reminders.js +96 -96
  75. package/src/content/.opencode/tui/pc-subagents.tsx +98 -98
  76. package/src/content/.opencode/tui.json +6 -6
  77. package/src/content/AGENTS.md +71 -71
  78. package/src/content/opencode.jsonc +39 -31
  79. package/src/fragments/archive/az.md +95 -95
  80. package/src/fragments/archive/gh.md +94 -94
  81. package/src/fragments/archive/gl.md +94 -94
  82. package/src/fragments/archive/none.md +73 -73
  83. package/src/fragments/guardrails/codegraph.md +7 -7
  84. package/src/fragments/guardrails/humanizer.md +4 -4
  85. package/src/fragments/guardrails/memory.md +4 -4
  86. package/src/fragments/guardrails/rtk.md +3 -3
  87. package/src/fragments/guardrails/simple-english.md +4 -4
  88. package/src/fragments/ops-backlog/az.md +28 -28
  89. package/src/fragments/ops-backlog/gh.md +29 -29
  90. package/src/fragments/ops-backlog/jira.md +28 -28
  91. package/src/fragments/ops-evidence/az.md +41 -41
  92. package/src/fragments/ops-evidence/gh.md +53 -53
  93. package/src/fragments/ops-evidence/jira.md +38 -38
  94. package/src/fragments/ops-review/az.md +62 -62
  95. package/src/fragments/ops-review/gh.md +52 -52
  96. package/src/fragments/ops-review/gl.md +56 -56
  97. package/src/fragments/ops-ship/az.md +80 -80
  98. package/src/fragments/ops-ship/gh.md +68 -68
  99. package/src/fragments/ops-ship/gl.md +85 -85
  100. package/src/index.js +107 -107
  101. package/src/presets/agents-content.json +53 -53
  102. package/src/presets/models.json +68 -68
  103. package/src/steps/copy/agents.js +118 -118
  104. package/src/steps/copy/commands.js +91 -91
  105. package/src/steps/copy/fullstack-engineer.js +85 -83
  106. package/src/steps/copy/index.js +88 -88
  107. package/src/steps/copy/opencode-json.js +147 -129
  108. package/src/steps/copy/skills.js +196 -196
  109. package/src/steps/metadata/index.js +108 -108
  110. package/src/steps/models/write.js +34 -34
  111. package/src/steps/optimization/patch-guardrails.js +108 -108
  112. package/src/utils/copy.js +108 -108
  113. package/src/utils/legacy-check.js +30 -30
  114. package/src/utils/models-cache.js +58 -58
  115. package/src/utils/paths.js +67 -64
  116. package/src/utils/update-manifest.js +49 -49
  117. package/src/content/.opencode/plugins/pc-system-reminders.test.js +0 -35
@@ -1,9 +1,9 @@
1
- ---
2
- description: Create a pull request for the current feature branch with screenshots if UI changed.
3
- ---
4
-
5
- Load the `pc-ops-ship` skill and execute it.
6
-
7
- Input:
8
-
9
- $ARGUMENTS
1
+ ---
2
+ description: Create a pull request for the current feature branch with screenshots if UI changed.
3
+ ---
4
+
5
+ Load the `pc-ops-ship` skill and execute it.
6
+
7
+ Input:
8
+
9
+ $ARGUMENTS
@@ -1,9 +1,9 @@
1
- ---
2
- description: Implement tasks from a plan: works with OpenSpec proposals and in-conversation plans.
3
- ---
4
-
5
- Load the `pc-plan-apply` skill and execute it in **interactive mode** with `start_from: branch` (the full protocol, including branch creation).
6
-
7
- Input:
8
-
9
- $ARGUMENTS
1
+ ---
2
+ description: Implement tasks from a plan: works with OpenSpec proposals and in-conversation plans.
3
+ ---
4
+
5
+ Load the `pc-plan-apply` skill and execute it in **interactive mode** with `start_from: branch` (the full protocol, including branch creation).
6
+
7
+ Input:
8
+
9
+ $ARGUMENTS
@@ -1,5 +1,5 @@
1
- ---
2
- description: Archive the oldest merged unarchived OpenSpec change and update documentation.
3
- ---
4
-
5
- Load the `pc-plan-archive` skill and execute it in **interactive mode**. No input required.
1
+ ---
2
+ description: Archive the oldest merged unarchived OpenSpec change and update documentation.
3
+ ---
4
+
5
+ Load the `pc-plan-archive` skill and execute it in **interactive mode**. No input required.
@@ -1,9 +1,9 @@
1
- ---
2
- description: Think through an idea, investigate a problem, or clarify requirements before creating a change.
3
- ---
4
-
5
- Load the `pc-plan-explore` skill and execute it in **interactive mode**.
6
-
7
- Input:
8
-
9
- $ARGUMENTS
1
+ ---
2
+ description: Think through an idea, investigate a problem, or clarify requirements before creating a change.
3
+ ---
4
+
5
+ Load the `pc-plan-explore` skill and execute it in **interactive mode**.
6
+
7
+ Input:
8
+
9
+ $ARGUMENTS
@@ -1,5 +1,5 @@
1
- ---
2
- description: Autonomous pipeline: explore, propose, apply, archive, then merge/PR/push. For loop-engineering.
3
- ---
4
-
5
- Load the `pc-plan-goal` skill and follow every step defined in it.
1
+ ---
2
+ description: Autonomous pipeline: explore, propose, apply, archive, then merge/PR/push. For loop-engineering.
3
+ ---
4
+
5
+ Load the `pc-plan-goal` skill and follow every step defined in it.
@@ -1,9 +1,9 @@
1
- ---
2
- description: Parse a work item or idea and propose a change plan with enriched task assignments.
3
- ---
4
-
5
- Load the `pc-plan-propose` skill and execute it in **interactive mode**.
6
-
7
- Input:
8
-
9
- $ARGUMENTS
1
+ ---
2
+ description: Parse a work item or idea and propose a change plan with enriched task assignments.
3
+ ---
4
+
5
+ Load the `pc-plan-propose` skill and execute it in **interactive mode**.
6
+
7
+ Input:
8
+
9
+ $ARGUMENTS
@@ -1,5 +1,5 @@
1
- ---
2
- description: Quick plan: analyze the codebase and create a task checklist using the Todo pane. No files, no OpenSpec.
3
- ---
4
-
5
- Load the `pc-plan-quick` skill and follow every step defined in it.
1
+ ---
2
+ description: Quick plan: analyze the codebase and create a task checklist using the Todo pane. No files, no OpenSpec.
3
+ ---
4
+
5
+ Load the `pc-plan-quick` skill and follow every step defined in it.
@@ -1,9 +1,9 @@
1
- ---
2
- description: Write a detailed, repo-aware user story from a feature idea or need.
3
- ---
4
-
5
- Load the `pc-plan-story` skill and follow every step defined in it.
6
-
7
- Input:
8
-
9
- $ARGUMENTS
1
+ ---
2
+ description: Write a detailed, repo-aware user story from a feature idea or need.
3
+ ---
4
+
5
+ Load the `pc-plan-story` skill and follow every step defined in it.
6
+
7
+ Input:
8
+
9
+ $ARGUMENTS
@@ -1,5 +1,5 @@
1
- ---
2
- description: Audit every configured source root against the fullstack engineer's guardrails and abilities. Read-only.
3
- ---
4
-
5
- Load the `pc-repo-audit` skill and follow every step defined in it.
1
+ ---
2
+ description: Audit every configured source root against the fullstack engineer's guardrails and abilities. Read-only.
3
+ ---
4
+
5
+ Load the `pc-repo-audit` skill and follow every step defined in it.
@@ -1,5 +1,5 @@
1
- ---
2
- description: Show all available commands and when to use each one.
3
- ---
4
-
5
- Load the `pc-repo-help` skill and display its reference to the user exactly as written. Do not summarize.
1
+ ---
2
+ description: Show all available commands and when to use each one.
3
+ ---
4
+
5
+ Load the `pc-repo-help` skill and display its reference to the user exactly as written. Do not summarize.
@@ -1,5 +1,5 @@
1
- ---
2
- description: Initialize the project. Presents a single form with all setup questions, then executes selected steps.
3
- ---
4
-
5
- Load the `pc-repo-initialize` skill and follow every step defined in it.
1
+ ---
2
+ description: Initialize the project. Presents a single form with all setup questions, then executes selected steps.
3
+ ---
4
+
5
+ Load the `pc-repo-initialize` skill and follow every step defined in it.
@@ -1,5 +1,5 @@
1
- ---
2
- description: Walk the user through the project and its agentic infrastructure. Explains what exists, how agents work, and how to use the system.
3
- ---
4
-
5
- Load the `pc-repo-onboard` skill and follow every step defined in it.
1
+ ---
2
+ description: Walk the user through the project and its agentic infrastructure. Explains what exists, how agents work, and how to use the system.
3
+ ---
4
+
5
+ Load the `pc-repo-onboard` skill and follow every step defined in it.
@@ -1,5 +1,5 @@
1
- ---
2
- description: Verify current-branch changes, plus immutable dependency installs, builds, and tests for every discovered project.
3
- ---
4
-
5
- Load the `pc-repo-verify` skill and follow every step defined in it.
1
+ ---
2
+ description: Verify current-branch changes, plus immutable dependency installs, builds, and tests for every discovered project.
3
+ ---
4
+
5
+ Load the `pc-repo-verify` skill and follow every step defined in it.
@@ -1,139 +1,139 @@
1
- // pc-subagent-monitor: tracks spawned subagents in .opencode/harness-run.json for
2
- // live TUI display and crash recovery. Never throws: monitor failures must
3
- // not break a session.
4
-
5
- import fs from "node:fs/promises"
6
- import path from "node:path"
7
-
8
- export const PcSubagentMonitor = async ({ directory, client }) => {
9
- const root = directory || process.cwd()
10
- const statePath = path.join(root, ".opencode", "harness-run.json")
11
- const state = { updatedAt: null, agents: {} }
12
-
13
- try {
14
- const prev = JSON.parse(await fs.readFile(statePath, "utf-8"))
15
- if (prev?.agents && typeof prev.agents === "object") {
16
- for (const [id, entry] of Object.entries(prev.agents)) {
17
- if (entry?.status === "running") entry.stale = true
18
- state.agents[id] = entry
19
- }
20
- }
21
- } catch {
22
- // fresh start
23
- }
24
-
25
- let _modelsCache = null
26
- async function loadModels() {
27
- if (_modelsCache) return _modelsCache
28
- const result = { build: null, fast: null, plan: null }
29
- for (const file of ["harness.user.json", "harness.json"]) {
30
- try {
31
- const raw = await fs.readFile(path.join(root, ".opencode", file), "utf-8")
32
- const { models = {} } = JSON.parse(raw)
33
- for (const tier of ["build", "fast", "plan"]) {
34
- if (!result[tier] && models[tier]) result[tier] = models[tier]
35
- }
36
- } catch {
37
- continue
38
- }
39
- }
40
- _modelsCache = result
41
- return result
42
- }
43
-
44
- async function modelForAgent(agent) {
45
- if (!agent) return null
46
- const dotIdx = agent.lastIndexOf(".")
47
- const tier = dotIdx !== -1 ? agent.slice(dotIdx + 1) : null
48
- if (tier && ["build", "fast", "plan"].includes(tier)) {
49
- const models = await loadModels()
50
- return models[tier] ?? null
51
- }
52
- return null
53
- }
54
-
55
- function parseTasks(title) {
56
- if (!title) return []
57
- const m = /^\s*([\d]+(?:\.[\d]+)*(?:\s*,\s*[\d]+(?:\.[\d]+)*)*)/.exec(title)
58
- return m ? m[1].split(",").map(s => s.trim()) : []
59
- }
60
-
61
- // Debounced persist: coalesce rapid writes when multiple subagents spawn
62
- // in the same microtask batch (e.g. a wave of 5 task() calls).
63
- let _persistScheduled = false
64
- async function persist() {
65
- if (_persistScheduled) return
66
- _persistScheduled = true
67
- queueMicrotask(async () => {
68
- _persistScheduled = false
69
- state.updatedAt = new Date().toISOString()
70
- try {
71
- await fs.mkdir(path.dirname(statePath), { recursive: true })
72
- const tmpPath = `${statePath}.tmp`
73
- await fs.writeFile(tmpPath, JSON.stringify(state, null, 2), "utf-8")
74
- await fs.rename(tmpPath, statePath)
75
- } catch {
76
- // best-effort
77
- }
78
- })
79
- }
80
-
81
- function sessionInfo(props) {
82
- const info = props?.info ?? props ?? {}
83
- return {
84
- id: info.id ?? info.sessionID ?? props?.sessionID,
85
- parentID: info.parentID ?? info.parentId,
86
- agent: info.agent,
87
- title: info.title,
88
- }
89
- }
90
-
91
- function pruneStale() {
92
- for (const [id, entry] of Object.entries(state.agents)) {
93
- if (entry?.stale) delete state.agents[id]
94
- }
95
- }
96
-
97
- return {
98
- event: async ({ event }) => {
99
- try {
100
- if (!event?.type?.startsWith("session.")) return
101
- const info = sessionInfo(event.properties)
102
- if (!info.id) return
103
-
104
- if (event.type === "session.created" && info.parentID) {
105
- pruneStale()
106
-
107
- state.agents[info.id] = {
108
- agent: info.agent ?? null,
109
- model: await modelForAgent(info.agent),
110
- tasks: parseTasks(info.title),
111
- title: info.title ?? null,
112
- status: "running",
113
- startedAt: new Date().toISOString(),
114
- endedAt: null,
115
- }
116
- await persist()
117
- return
118
- }
119
-
120
- const entry = state.agents[info.id]
121
- if (!entry) return
122
-
123
- if (event.type === "session.idle" && entry.status === "running") {
124
- entry.status = "done"
125
- entry.endedAt = new Date().toISOString()
126
- await persist()
127
- client?.tui?.showToast?.({
128
- body: {
129
- message: `subagent done: ${entry.title ?? info.id}`,
130
- variant: "success",
131
- },
132
- })
133
- }
134
- } catch {
135
- // monitoring must never disrupt the run
136
- }
137
- },
138
- }
139
- }
1
+ // pc-subagent-monitor: tracks spawned subagents in .opencode/harness-run.json for
2
+ // live TUI display and crash recovery. Never throws: monitor failures must
3
+ // not break a session.
4
+
5
+ import fs from "node:fs/promises"
6
+ import path from "node:path"
7
+
8
+ export const PcSubagentMonitor = async ({ directory, client }) => {
9
+ const root = directory || process.cwd()
10
+ const statePath = path.join(root, ".opencode", "harness-run.json")
11
+ const state = { updatedAt: null, agents: {} }
12
+
13
+ try {
14
+ const prev = JSON.parse(await fs.readFile(statePath, "utf-8"))
15
+ if (prev?.agents && typeof prev.agents === "object") {
16
+ for (const [id, entry] of Object.entries(prev.agents)) {
17
+ if (entry?.status === "running") entry.stale = true
18
+ state.agents[id] = entry
19
+ }
20
+ }
21
+ } catch {
22
+ // fresh start
23
+ }
24
+
25
+ let _modelsCache = null
26
+ async function loadModels() {
27
+ if (_modelsCache) return _modelsCache
28
+ const result = { build: null, fast: null, plan: null }
29
+ for (const file of ["harness.user.json", "harness.json"]) {
30
+ try {
31
+ const raw = await fs.readFile(path.join(root, ".opencode", file), "utf-8")
32
+ const { models = {} } = JSON.parse(raw)
33
+ for (const tier of ["build", "fast", "plan"]) {
34
+ if (!result[tier] && models[tier]) result[tier] = models[tier]
35
+ }
36
+ } catch {
37
+ continue
38
+ }
39
+ }
40
+ _modelsCache = result
41
+ return result
42
+ }
43
+
44
+ async function modelForAgent(agent) {
45
+ if (!agent) return null
46
+ const dotIdx = agent.lastIndexOf(".")
47
+ const tier = dotIdx !== -1 ? agent.slice(dotIdx + 1) : null
48
+ if (tier && ["build", "fast", "plan"].includes(tier)) {
49
+ const models = await loadModels()
50
+ return models[tier] ?? null
51
+ }
52
+ return null
53
+ }
54
+
55
+ function parseTasks(title) {
56
+ if (!title) return []
57
+ const m = /^\s*([\d]+(?:\.[\d]+)*(?:\s*,\s*[\d]+(?:\.[\d]+)*)*)/.exec(title)
58
+ return m ? m[1].split(",").map(s => s.trim()) : []
59
+ }
60
+
61
+ // Debounced persist: coalesce rapid writes when multiple subagents spawn
62
+ // in the same microtask batch (e.g. a wave of 5 task() calls).
63
+ let _persistScheduled = false
64
+ async function persist() {
65
+ if (_persistScheduled) return
66
+ _persistScheduled = true
67
+ queueMicrotask(async () => {
68
+ _persistScheduled = false
69
+ state.updatedAt = new Date().toISOString()
70
+ try {
71
+ await fs.mkdir(path.dirname(statePath), { recursive: true })
72
+ const tmpPath = `${statePath}.tmp`
73
+ await fs.writeFile(tmpPath, JSON.stringify(state, null, 2), "utf-8")
74
+ await fs.rename(tmpPath, statePath)
75
+ } catch {
76
+ // best-effort
77
+ }
78
+ })
79
+ }
80
+
81
+ function sessionInfo(props) {
82
+ const info = props?.info ?? props ?? {}
83
+ return {
84
+ id: info.id ?? info.sessionID ?? props?.sessionID,
85
+ parentID: info.parentID ?? info.parentId,
86
+ agent: info.agent,
87
+ title: info.title,
88
+ }
89
+ }
90
+
91
+ function pruneStale() {
92
+ for (const [id, entry] of Object.entries(state.agents)) {
93
+ if (entry?.stale) delete state.agents[id]
94
+ }
95
+ }
96
+
97
+ return {
98
+ event: async ({ event }) => {
99
+ try {
100
+ if (!event?.type?.startsWith("session.")) return
101
+ const info = sessionInfo(event.properties)
102
+ if (!info.id) return
103
+
104
+ if (event.type === "session.created" && info.parentID) {
105
+ pruneStale()
106
+
107
+ state.agents[info.id] = {
108
+ agent: info.agent ?? null,
109
+ model: await modelForAgent(info.agent),
110
+ tasks: parseTasks(info.title),
111
+ title: info.title ?? null,
112
+ status: "running",
113
+ startedAt: new Date().toISOString(),
114
+ endedAt: null,
115
+ }
116
+ await persist()
117
+ return
118
+ }
119
+
120
+ const entry = state.agents[info.id]
121
+ if (!entry) return
122
+
123
+ if (event.type === "session.idle" && entry.status === "running") {
124
+ entry.status = "done"
125
+ entry.endedAt = new Date().toISOString()
126
+ await persist()
127
+ client?.tui?.showToast?.({
128
+ body: {
129
+ message: `subagent done: ${entry.title ?? info.id}`,
130
+ variant: "success",
131
+ },
132
+ })
133
+ }
134
+ } catch {
135
+ // monitoring must never disrupt the run
136
+ }
137
+ },
138
+ }
139
+ }