agentera 0.0.0 → 3.0.0-dev.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 (252) hide show
  1. package/README.md +6 -45
  2. package/bundle/.agentera-npx-bundle.json +4 -0
  3. package/bundle/references/adapters/cursor.md +213 -0
  4. package/bundle/references/adapters/opencode.md +530 -0
  5. package/bundle/references/adapters/package-manifest-interface-model.yaml +337 -0
  6. package/bundle/references/adapters/package-registry.yaml +247 -0
  7. package/bundle/references/adapters/package-surface-characterization.md +48 -0
  8. package/bundle/references/adapters/runtime-adapter-characterization.md +79 -0
  9. package/bundle/references/adapters/runtime-adapter-interface-model.yaml +200 -0
  10. package/bundle/references/adapters/runtime-adapter-registry.yaml +548 -0
  11. package/bundle/references/adapters/runtime-feature-parity.md +189 -0
  12. package/bundle/references/analysis/benchmark.md +267 -0
  13. package/bundle/references/analysis/startup-measurement-contract.yaml +424 -0
  14. package/bundle/references/artifacts/artifact-registry-interface-model.yaml +288 -0
  15. package/bundle/references/cli/agent-ready-state-contract.yaml +950 -0
  16. package/bundle/references/cli/app-lifecycle-vocabulary.yaml +233 -0
  17. package/bundle/references/cli/audience-namespace-cli-migration.yaml +355 -0
  18. package/bundle/references/cli/bundle-skill-vocabulary.yaml +278 -0
  19. package/bundle/references/cli/capability-instruction-contract.yaml +123 -0
  20. package/bundle/references/cli/capability-tool-classification.yaml +53 -0
  21. package/bundle/references/cli/routing-execution-vocabulary.yaml +281 -0
  22. package/bundle/references/cli/update-channels.yaml +120 -0
  23. package/bundle/references/cli/vocabulary-index.yaml +160 -0
  24. package/bundle/references/cli/vocabulary.md +562 -0
  25. package/bundle/references/meta/documentation-inventory.md +43 -0
  26. package/bundle/references/v1-section-mapping.md +47 -0
  27. package/bundle/registry.json +39 -0
  28. package/bundle/skills/agentera/.claude-plugin/plugin.json +27 -0
  29. package/bundle/skills/agentera/SKILL.md +470 -0
  30. package/bundle/skills/agentera/agents/dokumentera.toml +6 -0
  31. package/bundle/skills/agentera/agents/hej.toml +6 -0
  32. package/bundle/skills/agentera/agents/inspektera.toml +6 -0
  33. package/bundle/skills/agentera/agents/inspirera.toml +6 -0
  34. package/bundle/skills/agentera/agents/optimera.toml +6 -0
  35. package/bundle/skills/agentera/agents/orkestrera.toml +6 -0
  36. package/bundle/skills/agentera/agents/planera.toml +6 -0
  37. package/bundle/skills/agentera/agents/profilera.toml +6 -0
  38. package/bundle/skills/agentera/agents/realisera.toml +6 -0
  39. package/bundle/skills/agentera/agents/resonera.toml +6 -0
  40. package/bundle/skills/agentera/agents/visionera.toml +6 -0
  41. package/bundle/skills/agentera/agents/visualisera.toml +6 -0
  42. package/bundle/skills/agentera/capabilities/dokumentera/instructions.md +428 -0
  43. package/bundle/skills/agentera/capabilities/dokumentera/schemas/artifacts.yaml +73 -0
  44. package/bundle/skills/agentera/capabilities/dokumentera/schemas/exit.yaml +35 -0
  45. package/bundle/skills/agentera/capabilities/dokumentera/schemas/triggers.yaml +35 -0
  46. package/bundle/skills/agentera/capabilities/dokumentera/schemas/validation.yaml +139 -0
  47. package/bundle/skills/agentera/capabilities/hej/instructions.md +331 -0
  48. package/bundle/skills/agentera/capabilities/hej/schemas/artifacts.yaml +69 -0
  49. package/bundle/skills/agentera/capabilities/hej/schemas/exit.yaml +32 -0
  50. package/bundle/skills/agentera/capabilities/hej/schemas/triggers.yaml +58 -0
  51. package/bundle/skills/agentera/capabilities/hej/schemas/validation.yaml +55 -0
  52. package/bundle/skills/agentera/capabilities/inspektera/instructions.md +514 -0
  53. package/bundle/skills/agentera/capabilities/inspektera/schemas/artifacts.yaml +76 -0
  54. package/bundle/skills/agentera/capabilities/inspektera/schemas/exit.yaml +36 -0
  55. package/bundle/skills/agentera/capabilities/inspektera/schemas/triggers.yaml +38 -0
  56. package/bundle/skills/agentera/capabilities/inspektera/schemas/validation.yaml +113 -0
  57. package/bundle/skills/agentera/capabilities/inspirera/instructions.md +280 -0
  58. package/bundle/skills/agentera/capabilities/inspirera/schemas/artifacts.yaml +24 -0
  59. package/bundle/skills/agentera/capabilities/inspirera/schemas/exit.yaml +33 -0
  60. package/bundle/skills/agentera/capabilities/inspirera/schemas/triggers.yaml +34 -0
  61. package/bundle/skills/agentera/capabilities/inspirera/schemas/validation.yaml +58 -0
  62. package/bundle/skills/agentera/capabilities/optimera/instructions.md +437 -0
  63. package/bundle/skills/agentera/capabilities/optimera/schemas/artifacts.yaml +69 -0
  64. package/bundle/skills/agentera/capabilities/optimera/schemas/exit.yaml +35 -0
  65. package/bundle/skills/agentera/capabilities/optimera/schemas/triggers.yaml +39 -0
  66. package/bundle/skills/agentera/capabilities/optimera/schemas/validation.yaml +91 -0
  67. package/bundle/skills/agentera/capabilities/orkestrera/instructions.md +433 -0
  68. package/bundle/skills/agentera/capabilities/orkestrera/schemas/artifacts.yaml +64 -0
  69. package/bundle/skills/agentera/capabilities/orkestrera/schemas/exit.yaml +34 -0
  70. package/bundle/skills/agentera/capabilities/orkestrera/schemas/triggers.yaml +42 -0
  71. package/bundle/skills/agentera/capabilities/orkestrera/schemas/validation.yaml +107 -0
  72. package/bundle/skills/agentera/capabilities/planera/instructions.md +368 -0
  73. package/bundle/skills/agentera/capabilities/planera/schemas/artifacts.yaml +62 -0
  74. package/bundle/skills/agentera/capabilities/planera/schemas/exit.yaml +33 -0
  75. package/bundle/skills/agentera/capabilities/planera/schemas/triggers.yaml +34 -0
  76. package/bundle/skills/agentera/capabilities/planera/schemas/validation.yaml +61 -0
  77. package/bundle/skills/agentera/capabilities/profilera/instructions.md +419 -0
  78. package/bundle/skills/agentera/capabilities/profilera/schemas/artifacts.yaml +18 -0
  79. package/bundle/skills/agentera/capabilities/profilera/schemas/exit.yaml +34 -0
  80. package/bundle/skills/agentera/capabilities/profilera/schemas/triggers.yaml +45 -0
  81. package/bundle/skills/agentera/capabilities/profilera/schemas/validation.yaml +57 -0
  82. package/bundle/skills/agentera/capabilities/realisera/instructions.md +403 -0
  83. package/bundle/skills/agentera/capabilities/realisera/schemas/artifacts.yaml +80 -0
  84. package/bundle/skills/agentera/capabilities/realisera/schemas/exit.yaml +35 -0
  85. package/bundle/skills/agentera/capabilities/realisera/schemas/triggers.yaml +39 -0
  86. package/bundle/skills/agentera/capabilities/realisera/schemas/validation.yaml +110 -0
  87. package/bundle/skills/agentera/capabilities/resonera/instructions.md +329 -0
  88. package/bundle/skills/agentera/capabilities/resonera/schemas/artifacts.yaml +47 -0
  89. package/bundle/skills/agentera/capabilities/resonera/schemas/exit.yaml +35 -0
  90. package/bundle/skills/agentera/capabilities/resonera/schemas/triggers.yaml +46 -0
  91. package/bundle/skills/agentera/capabilities/resonera/schemas/validation.yaml +77 -0
  92. package/bundle/skills/agentera/capabilities/visionera/instructions.md +309 -0
  93. package/bundle/skills/agentera/capabilities/visionera/schemas/artifacts.yaml +57 -0
  94. package/bundle/skills/agentera/capabilities/visionera/schemas/exit.yaml +35 -0
  95. package/bundle/skills/agentera/capabilities/visionera/schemas/triggers.yaml +41 -0
  96. package/bundle/skills/agentera/capabilities/visionera/schemas/validation.yaml +74 -0
  97. package/bundle/skills/agentera/capabilities/visualisera/instructions.md +400 -0
  98. package/bundle/skills/agentera/capabilities/visualisera/schemas/artifacts.yaml +44 -0
  99. package/bundle/skills/agentera/capabilities/visualisera/schemas/exit.yaml +34 -0
  100. package/bundle/skills/agentera/capabilities/visualisera/schemas/triggers.yaml +33 -0
  101. package/bundle/skills/agentera/capabilities/visualisera/schemas/validation.yaml +80 -0
  102. package/bundle/skills/agentera/capability_schema_contract.yaml +385 -0
  103. package/bundle/skills/agentera/protocol.yaml +463 -0
  104. package/bundle/skills/agentera/references/contract.md +1039 -0
  105. package/bundle/skills/agentera/schemas/artifacts/changelog.yaml +60 -0
  106. package/bundle/skills/agentera/schemas/artifacts/decisions.yaml +461 -0
  107. package/bundle/skills/agentera/schemas/artifacts/design.yaml +55 -0
  108. package/bundle/skills/agentera/schemas/artifacts/docs.yaml +402 -0
  109. package/bundle/skills/agentera/schemas/artifacts/experiments.yaml +373 -0
  110. package/bundle/skills/agentera/schemas/artifacts/health.yaml +484 -0
  111. package/bundle/skills/agentera/schemas/artifacts/objective.yaml +399 -0
  112. package/bundle/skills/agentera/schemas/artifacts/plan.yaml +342 -0
  113. package/bundle/skills/agentera/schemas/artifacts/progress.yaml +325 -0
  114. package/bundle/skills/agentera/schemas/artifacts/todo.yaml +110 -0
  115. package/bundle/skills/agentera/schemas/artifacts/vision.yaml +262 -0
  116. package/bundle/skills/hej/.claude-plugin/plugin.json +6 -0
  117. package/bundle/skills/hej/SKILL.md +69 -0
  118. package/bundle/skills/hej/agents/hej.toml +11 -0
  119. package/bundle/skills/hej/agents/openai.yaml +8 -0
  120. package/dist/analytics/extractCorpus.js +1791 -0
  121. package/dist/analytics/extractCorpus.js.map +1 -0
  122. package/dist/analytics/usageStats.js +487 -0
  123. package/dist/analytics/usageStats.js.map +1 -0
  124. package/dist/bin/agentera.js +4 -0
  125. package/dist/bin/agentera.js.map +1 -0
  126. package/dist/cli/appContext.js +226 -0
  127. package/dist/cli/appContext.js.map +1 -0
  128. package/dist/cli/argvalidate.js +41 -0
  129. package/dist/cli/argvalidate.js.map +1 -0
  130. package/dist/cli/capabilityContext.js +2421 -0
  131. package/dist/cli/capabilityContext.js.map +1 -0
  132. package/dist/cli/commands/backfill.js +84 -0
  133. package/dist/cli/commands/backfill.js.map +1 -0
  134. package/dist/cli/commands/capability.js +44 -0
  135. package/dist/cli/commands/capability.js.map +1 -0
  136. package/dist/cli/commands/compact.js +148 -0
  137. package/dist/cli/commands/compact.js.map +1 -0
  138. package/dist/cli/commands/doctor.js +180 -0
  139. package/dist/cli/commands/doctor.js.map +1 -0
  140. package/dist/cli/commands/lint.js +179 -0
  141. package/dist/cli/commands/lint.js.map +1 -0
  142. package/dist/cli/commands/prime.js +545 -0
  143. package/dist/cli/commands/prime.js.map +1 -0
  144. package/dist/cli/commands/query.js +346 -0
  145. package/dist/cli/commands/query.js.map +1 -0
  146. package/dist/cli/commands/report.js +210 -0
  147. package/dist/cli/commands/report.js.map +1 -0
  148. package/dist/cli/commands/schema.js +306 -0
  149. package/dist/cli/commands/schema.js.map +1 -0
  150. package/dist/cli/commands/state.js +1012 -0
  151. package/dist/cli/commands/state.js.map +1 -0
  152. package/dist/cli/commands/upgrade.js +49 -0
  153. package/dist/cli/commands/upgrade.js.map +1 -0
  154. package/dist/cli/commands/validate.js +519 -0
  155. package/dist/cli/commands/validate.js.map +1 -0
  156. package/dist/cli/commands/verify.js +204 -0
  157. package/dist/cli/commands/verify.js.map +1 -0
  158. package/dist/cli/dispatch.js +962 -0
  159. package/dist/cli/dispatch.js.map +1 -0
  160. package/dist/cli/orientation.js +595 -0
  161. package/dist/cli/orientation.js.map +1 -0
  162. package/dist/cli/prime-blob.js +3 -0
  163. package/dist/cli/prime-blob.js.map +1 -0
  164. package/dist/cli/stateQuery.js +292 -0
  165. package/dist/cli/stateQuery.js.map +1 -0
  166. package/dist/cli/structured.js +18 -0
  167. package/dist/cli/structured.js.map +1 -0
  168. package/dist/core/difflib.js +274 -0
  169. package/dist/core/difflib.js.map +1 -0
  170. package/dist/core/git.js +43 -0
  171. package/dist/core/git.js.map +1 -0
  172. package/dist/core/paths.js +50 -0
  173. package/dist/core/paths.js.map +1 -0
  174. package/dist/core/pyjson.js +101 -0
  175. package/dist/core/pyjson.js.map +1 -0
  176. package/dist/core/sourceRoot.js +72 -0
  177. package/dist/core/sourceRoot.js.map +1 -0
  178. package/dist/core/toml.js +11 -0
  179. package/dist/core/toml.js.map +1 -0
  180. package/dist/core/yaml.js +25 -0
  181. package/dist/core/yaml.js.map +1 -0
  182. package/dist/eval/evalSkills.js +258 -0
  183. package/dist/eval/evalSkills.js.map +1 -0
  184. package/dist/eval/semanticEval.js +148 -0
  185. package/dist/eval/semanticEval.js.map +1 -0
  186. package/dist/eval/semanticFixtures.js +227 -0
  187. package/dist/eval/semanticFixtures.js.map +1 -0
  188. package/dist/hooks/common.js +160 -0
  189. package/dist/hooks/common.js.map +1 -0
  190. package/dist/hooks/compaction.js +935 -0
  191. package/dist/hooks/compaction.js.map +1 -0
  192. package/dist/hooks/cursorPreToolUse.js +19 -0
  193. package/dist/hooks/cursorPreToolUse.js.map +1 -0
  194. package/dist/hooks/cursorSessionStart.js +71 -0
  195. package/dist/hooks/cursorSessionStart.js.map +1 -0
  196. package/dist/hooks/sessionStart.js +209 -0
  197. package/dist/hooks/sessionStart.js.map +1 -0
  198. package/dist/hooks/sessionStop.js +212 -0
  199. package/dist/hooks/sessionStop.js.map +1 -0
  200. package/dist/hooks/validateArtifact.js +933 -0
  201. package/dist/hooks/validateArtifact.js.map +1 -0
  202. package/dist/registries/artifactRegistry.js +206 -0
  203. package/dist/registries/artifactRegistry.js.map +1 -0
  204. package/dist/registries/capabilityContract.js +310 -0
  205. package/dist/registries/capabilityContract.js.map +1 -0
  206. package/dist/registries/packageRegistry.js +641 -0
  207. package/dist/registries/packageRegistry.js.map +1 -0
  208. package/dist/registries/runtimeAdapterRegistry.js +315 -0
  209. package/dist/registries/runtimeAdapterRegistry.js.map +1 -0
  210. package/dist/setup/codex.js +1052 -0
  211. package/dist/setup/codex.js.map +1 -0
  212. package/dist/setup/copilot.js +227 -0
  213. package/dist/setup/copilot.js.map +1 -0
  214. package/dist/setup/cursor.js +127 -0
  215. package/dist/setup/cursor.js.map +1 -0
  216. package/dist/setup/doctor.js +1269 -0
  217. package/dist/setup/doctor.js.map +1 -0
  218. package/dist/state/installRoot.js +279 -0
  219. package/dist/state/installRoot.js.map +1 -0
  220. package/dist/state/progressCommit.js +289 -0
  221. package/dist/state/progressCommit.js.map +1 -0
  222. package/dist/state/startupAnalysis.js +1953 -0
  223. package/dist/state/startupAnalysis.js.map +1 -0
  224. package/dist/upgrade/appModel.js +189 -0
  225. package/dist/upgrade/appModel.js.map +1 -0
  226. package/dist/upgrade/channels.js +197 -0
  227. package/dist/upgrade/channels.js.map +1 -0
  228. package/dist/upgrade/compatibility.js +197 -0
  229. package/dist/upgrade/compatibility.js.map +1 -0
  230. package/dist/upgrade/doctor.js +368 -0
  231. package/dist/upgrade/doctor.js.map +1 -0
  232. package/dist/upgrade/migrateArtifactsV2ToV3.js +412 -0
  233. package/dist/upgrade/migrateArtifactsV2ToV3.js.map +1 -0
  234. package/dist/upgrade/upgradeCommands.js +40 -0
  235. package/dist/upgrade/upgradeCommands.js.map +1 -0
  236. package/dist/upgrade/upgradeOrchestrator.js +280 -0
  237. package/dist/upgrade/upgradeOrchestrator.js.map +1 -0
  238. package/dist/validate/appHomeContract.js +150 -0
  239. package/dist/validate/appHomeContract.js.map +1 -0
  240. package/dist/validate/capability.js +412 -0
  241. package/dist/validate/capability.js.map +1 -0
  242. package/dist/validate/crossCapability.js +145 -0
  243. package/dist/validate/crossCapability.js.map +1 -0
  244. package/dist/validate/lifecycleAdapters.js +772 -0
  245. package/dist/validate/lifecycleAdapters.js.map +1 -0
  246. package/dist/validate/selfAudit.js +107 -0
  247. package/dist/validate/selfAudit.js.map +1 -0
  248. package/package.json +28 -8
  249. package/LICENSE +0 -201
  250. package/bin/agentera.mjs +0 -50
  251. package/lib/exec.mjs +0 -116
  252. package/lib/resolve.mjs +0 -129
@@ -0,0 +1,1012 @@
1
+ import fs from "node:fs";
2
+ import { artifactPath, discoverSchemasDir, loadSchemas } from "../appContext.js";
3
+ import { asList, COMMAND_FILTERS, emitStateStructured, extractEntries, filterByFieldValue, filterByTopic, firstPresent, formatEntry, loadArtifact, missingSchemaError, printStatusCounts, recentCycles, sourceMetadata, statusCounts, stringFieldNames, structuredState, truncate, validateFilterValues, } from "../stateQuery.js";
4
+ function out(io) {
5
+ return io.out ?? ((t) => process.stdout.write(t));
6
+ }
7
+ function err(io) {
8
+ return io.err ?? ((t) => process.stderr.write(t));
9
+ }
10
+ export function queryProgress(args, schemas, io) {
11
+ const o = out(io);
12
+ const e = err(io);
13
+ const info = schemas.progress;
14
+ if (!info) {
15
+ e(missingSchemaError("progress") + "\n");
16
+ return 1;
17
+ }
18
+ const p = artifactPath(info, "progress");
19
+ const data = loadArtifact(p);
20
+ let entries = extractEntries(data);
21
+ const topic = args.topic ?? null;
22
+ if (topic)
23
+ entries = filterByTopic(entries, topic, info.fields);
24
+ const statusFilter = args.status ?? null;
25
+ if (statusFilter)
26
+ entries = filterByFieldValue(entries, "type", statusFilter);
27
+ const effectiveLimit = (args.limit ?? 5) || 5;
28
+ entries = recentCycles(entries, effectiveLimit);
29
+ if ((args.format ?? "text") !== "text") {
30
+ return emitStateStructured("progress", structuredState("progress", entries, sourceMetadata("progress", p), {
31
+ filters: { topic, status: statusFilter, limit: effectiveLimit },
32
+ }), args.format ?? "text", args.fields, o, e);
33
+ }
34
+ if (entries.length === 0)
35
+ return 0;
36
+ for (const entry of entries) {
37
+ o(formatEntry(entry, ["number", "timestamp", "type", "phase", "commit"]) + "\n");
38
+ for (const key of ["what", "verified", "next"]) {
39
+ const value = entry[key];
40
+ if (value)
41
+ o(` ${key}: ${truncate(value)}\n`);
42
+ }
43
+ }
44
+ return 0;
45
+ }
46
+ function planArtifactSummary(data, header) {
47
+ const summary = {
48
+ header,
49
+ title: firstPresent(header, ["title"], data.title ?? ""),
50
+ status: firstPresent(header, ["status"], data.status ?? ""),
51
+ created: firstPresent(header, ["created"], data.created ?? ""),
52
+ what: data.what,
53
+ why: data.why,
54
+ constraints: data.constraints,
55
+ scope: data.scope,
56
+ design: data.design,
57
+ overall_acceptance: data.overall_acceptance,
58
+ surprises: data.surprises,
59
+ previous_plan_archived: data.previous_plan_archived,
60
+ };
61
+ const out = {};
62
+ for (const [k, v] of Object.entries(summary)) {
63
+ if (v !== null && v !== undefined && v !== "")
64
+ out[k] = v;
65
+ }
66
+ return out;
67
+ }
68
+ function planSourceContract(source, summary) {
69
+ const legacyEntries = Boolean(summary.legacy_entries);
70
+ const complete = Boolean(source.exists) && !legacyEntries;
71
+ const missingState = [];
72
+ if (!source.exists)
73
+ missingState.push("PLAN.md artifact");
74
+ if (legacyEntries)
75
+ missingState.push("current PLAN.md task artifact shape");
76
+ const summaryFields = Object.keys(summary).sort();
77
+ const entryFields = ["number", "name", "depends_on", "status", "acceptance", "evidence", "blocked_reason"];
78
+ return {
79
+ artifact: "PLAN.md",
80
+ canonical_artifact_label: "PLAN.md",
81
+ persisted_artifact_path: source.path,
82
+ complete_for_plan_artifact: complete,
83
+ complete_for_normal_startup_evaluation: complete,
84
+ raw_artifact_reads_required: false,
85
+ raw_artifact_read_policy: "Use `agentera plan --format json` entries, summary, source, and source_contract before raw PLAN.md access. " +
86
+ "When complete_for_plan_artifact is true, skip defensive `.agentera/plan.yaml` reads during normal read-only " +
87
+ "plan startup/evaluation; raw plan artifact access is reserved for writes, archival, validation, corruption " +
88
+ "diagnostics, or unavailable/incomplete CLI state.",
89
+ included_state: [
90
+ "header",
91
+ "what",
92
+ "why",
93
+ "constraints",
94
+ "scope",
95
+ "design",
96
+ "tasks",
97
+ "task dependencies",
98
+ "task acceptance criteria",
99
+ "task evidence",
100
+ "overall_acceptance",
101
+ "surprises",
102
+ "previous_plan_archived",
103
+ ],
104
+ complete_state: {
105
+ summary: summaryFields,
106
+ entries: entryFields,
107
+ normal_startup_evaluation: complete,
108
+ },
109
+ raw_artifact_access_boundary: {
110
+ normal_read_only_startup_evaluation: "skip raw plan artifact reads when complete_for_plan_artifact is true",
111
+ allowed_raw_artifact_uses: [
112
+ "artifact writes",
113
+ "plan archival",
114
+ "artifact validation",
115
+ "corruption diagnostics",
116
+ "unavailable or incomplete CLI state after CLI fallbacks",
117
+ ],
118
+ },
119
+ missing_state: missingState,
120
+ fallback: complete ? [] : ["agentera docs --format json"],
121
+ fallback_policy: "When plan CLI output is missing or incomplete, use supported CLI state such as `agentera docs --format json` " +
122
+ "for artifact mapping before any last-resort raw plan artifact read.",
123
+ summary_fields: summaryFields,
124
+ entry_fields: entryFields,
125
+ };
126
+ }
127
+ export function queryPlan(args, schemas, io) {
128
+ const o = out(io);
129
+ const e = err(io);
130
+ const info = schemas.plan;
131
+ if (!info) {
132
+ e(missingSchemaError("plan") + "\n");
133
+ return 1;
134
+ }
135
+ const p = artifactPath(info, "plan");
136
+ const data = loadArtifact(p);
137
+ const isDict = data !== null && typeof data === "object" && !Array.isArray(data);
138
+ const format = args.format ?? "text";
139
+ if (!isDict) {
140
+ if (format !== "text") {
141
+ const source = sourceMetadata("plan", p);
142
+ const summary = { absence_reason: "No plan artifact is available from agentera plan." };
143
+ return emitStateStructured("plan", structuredState("plan", [], source, {
144
+ filters: { status: args.status ?? null },
145
+ summary,
146
+ sourceContract: planSourceContract(source, summary),
147
+ }), format, args.fields, o, e);
148
+ }
149
+ return 0;
150
+ }
151
+ const dataDict = data;
152
+ const legacyEntries = asList(dataDict.entries);
153
+ if (legacyEntries.length > 0) {
154
+ let entries = legacyEntries;
155
+ const statusFilter = args.status ?? null;
156
+ if (statusFilter)
157
+ entries = filterByFieldValue(entries, "status", statusFilter);
158
+ const source = sourceMetadata("plan", p);
159
+ const summary = { legacy_entries: true };
160
+ if (format !== "text") {
161
+ return emitStateStructured("plan", structuredState("plan", entries, source, {
162
+ filters: { status: statusFilter },
163
+ summary,
164
+ sourceContract: planSourceContract(source, summary),
165
+ }), format, args.fields, o, e);
166
+ }
167
+ for (const entry of entries) {
168
+ const line = formatEntry(entry, ["status", "title", "name"]);
169
+ if (line)
170
+ o(line + "\n");
171
+ }
172
+ return 0;
173
+ }
174
+ const header = dataDict.header && typeof dataDict.header === "object" && !Array.isArray(dataDict.header) ? dataDict.header : {};
175
+ const summary = planArtifactSummary(dataDict, header);
176
+ const title = summary.title ?? "";
177
+ const status = summary.status ?? "";
178
+ const created = summary.created ?? "";
179
+ let tasks = asList(dataDict.tasks);
180
+ const statusFilter = args.status ?? null;
181
+ if (statusFilter)
182
+ tasks = filterByFieldValue(tasks, "status", statusFilter);
183
+ const source = sourceMetadata("plan", p);
184
+ if (format !== "text") {
185
+ return emitStateStructured("plan", structuredState("plan", tasks, source, {
186
+ filters: { status: statusFilter },
187
+ summary,
188
+ sourceContract: planSourceContract(source, summary),
189
+ }), format, args.fields, o, e);
190
+ }
191
+ o(`Plan: status=${status || "unknown"} | title=${truncate(title)} | created=${created || "-"}\n`);
192
+ for (const key of ["what", "why"]) {
193
+ const value = dataDict[key];
194
+ if (value)
195
+ o(`${key}: ${truncate(value)}\n`);
196
+ }
197
+ printStatusCounts("Task status", statusCounts(tasks), o);
198
+ for (const task of tasks.slice(0, 10)) {
199
+ const line = formatEntry(task, ["number", "status", "name", "title"]);
200
+ if (line)
201
+ o(`Task: ${line}\n`);
202
+ }
203
+ return 0;
204
+ }
205
+ export function healthAuditNumber(entry) {
206
+ const number = entry.number;
207
+ if (typeof number === "number" && Number.isInteger(number))
208
+ return number;
209
+ if (typeof number === "string" && /^\d+$/.test(number))
210
+ return parseInt(number, 10);
211
+ return null;
212
+ }
213
+ export function latestHealthAudit(entries) {
214
+ if (entries.length === 0)
215
+ return null;
216
+ let best = null;
217
+ let bestNumber = -1;
218
+ for (const entry of entries) {
219
+ const number = healthAuditNumber(entry);
220
+ if (number === null)
221
+ continue;
222
+ if (number > bestNumber) {
223
+ bestNumber = number;
224
+ best = entry;
225
+ }
226
+ }
227
+ return best !== null ? best : entries[entries.length - 1];
228
+ }
229
+ export function queryHealth(args, schemas, io) {
230
+ const o = out(io);
231
+ const e = err(io);
232
+ const info = schemas.health;
233
+ if (!info) {
234
+ e(missingSchemaError("health") + "\n");
235
+ return 1;
236
+ }
237
+ const p = artifactPath(info, "health");
238
+ const data = loadArtifact(p);
239
+ const entries = extractEntries(data);
240
+ const dimension = args.dimension ?? null;
241
+ let latest = latestHealthAudit(entries);
242
+ let latestEntries = latest ? [latest] : [];
243
+ if (dimension && latestEntries.length > 0) {
244
+ latest = latestEntries[0];
245
+ const dimLower = dimension.toLowerCase();
246
+ let matched = false;
247
+ const grades = latest.grades;
248
+ if (grades && typeof grades === "object" && !Array.isArray(grades)) {
249
+ matched = Object.keys(grades).some((gk) => String(gk).toLowerCase().includes(dimLower));
250
+ }
251
+ const details = latest.dimensions_detail;
252
+ if (Array.isArray(details)) {
253
+ matched =
254
+ matched ||
255
+ details.some((d) => d && typeof d === "object" && String(d.name ?? "").toLowerCase().includes(dimLower));
256
+ }
257
+ if (!matched)
258
+ latestEntries = [];
259
+ }
260
+ const format = args.format ?? "text";
261
+ if (format !== "text") {
262
+ return emitStateStructured("health", structuredState("health", latestEntries, sourceMetadata("health", p), {
263
+ filters: { dimension },
264
+ summary: { latest_only: true },
265
+ }), format, args.fields, o, e);
266
+ }
267
+ if (entries.length === 0)
268
+ return 0;
269
+ latest = latestHealthAudit(entries);
270
+ if (!latest)
271
+ return 0;
272
+ if (dimension) {
273
+ const dimLower = dimension.toLowerCase();
274
+ const grades = (latest.grades ?? {});
275
+ let matched = false;
276
+ for (const [gk, gv] of Object.entries(grades)) {
277
+ if (String(gk).toLowerCase().includes(dimLower)) {
278
+ o(`${gk}: ${gv}\n`);
279
+ matched = true;
280
+ }
281
+ }
282
+ const details = asList(latest.dimensions_detail);
283
+ for (const d of details) {
284
+ const dn = String(d.name ?? "");
285
+ if (dn.toLowerCase().includes(dimLower)) {
286
+ const summary = d.summary ?? "";
287
+ if (summary)
288
+ o(` ${summary}\n`);
289
+ for (const f of asList(d.findings)) {
290
+ o(` [${f.severity ?? ""}] ${f.heading ?? ""}\n`);
291
+ }
292
+ matched = true;
293
+ }
294
+ }
295
+ if (!matched)
296
+ return 0;
297
+ }
298
+ else {
299
+ const num = latest.number ?? "?";
300
+ const traj = latest.trajectory ?? "";
301
+ o(`Audit ${num}: ${traj}\n`);
302
+ const grades = (latest.grades ?? {});
303
+ for (const [gk, gv] of Object.entries(grades)) {
304
+ o(` ${gk}: ${gv}\n`);
305
+ }
306
+ }
307
+ return 0;
308
+ }
309
+ const STARTUP_COMPLETENESS_MISSING_STATE = [];
310
+ export function queryDocs(args, schemas, io) {
311
+ const o = out(io);
312
+ const e = err(io);
313
+ const info = schemas.docs;
314
+ if (!info) {
315
+ e(missingSchemaError("docs") + "\n");
316
+ return 1;
317
+ }
318
+ const p = artifactPath(info, "docs");
319
+ const data = loadArtifact(p);
320
+ const format = args.format ?? "text";
321
+ const isDict = data !== null && typeof data === "object" && !Array.isArray(data);
322
+ if (!isDict) {
323
+ if (format !== "text") {
324
+ return emitStateStructured("docs", structuredState("docs", [], sourceMetadata("docs", p), {
325
+ filters: { topic: args.topic ?? null, status: args.status ?? null },
326
+ }), format, args.fields, o, e);
327
+ }
328
+ return 0;
329
+ }
330
+ const d = data;
331
+ const legacyEntries = asList(d.entries);
332
+ if (legacyEntries.length > 0) {
333
+ let entries = legacyEntries;
334
+ const statusFilter = args.status ?? null;
335
+ if (statusFilter)
336
+ entries = filterByFieldValue(entries, "status", statusFilter);
337
+ if (format !== "text") {
338
+ return emitStateStructured("docs", structuredState("docs", entries, sourceMetadata("docs", p), { filters: { status: statusFilter } }), format, args.fields, o, e);
339
+ }
340
+ for (const entry of entries) {
341
+ const line = formatEntry(entry, ["last_audit", "document", "path", "status"]);
342
+ if (line)
343
+ o(line + "\n");
344
+ }
345
+ return 0;
346
+ }
347
+ const mapping = asList(d.mapping);
348
+ let index = asList(d.index);
349
+ const coverage = d.coverage && typeof d.coverage === "object" && !Array.isArray(d.coverage) ? d.coverage : {};
350
+ const conventions = d.conventions && typeof d.conventions === "object" && !Array.isArray(d.conventions) ? d.conventions : {};
351
+ const topic = args.topic ?? null;
352
+ if (topic) {
353
+ const t = topic.toLowerCase();
354
+ index = index.filter((entry) => String(entry.document ?? "").toLowerCase().includes(t) ||
355
+ String(entry.path ?? "").toLowerCase().includes(t) ||
356
+ String(entry.status ?? "").toLowerCase().includes(t));
357
+ }
358
+ const statusFilter = args.status ?? null;
359
+ if (statusFilter)
360
+ index = filterByFieldValue(index, "status", statusFilter);
361
+ if (format !== "text") {
362
+ return emitStateStructured("docs", structuredState("docs", index, sourceMetadata("docs", p), {
363
+ filters: { topic, status: statusFilter },
364
+ summary: {
365
+ last_audit: d.last_audit,
366
+ conventions,
367
+ mapping,
368
+ mapping_entries: mapping.length,
369
+ coverage,
370
+ source_contract: {
371
+ capability_startup_complete: STARTUP_COMPLETENESS_MISSING_STATE.length === 0,
372
+ raw_artifact_reads_required: false,
373
+ },
374
+ },
375
+ }), format, args.fields, o, e);
376
+ }
377
+ o(`Docs: last_audit=${d.last_audit ?? "-"}\n`);
378
+ o(`Mapping: entries=${mapping.length}\n`);
379
+ if (Object.keys(coverage).length > 0) {
380
+ o("Coverage: " + Object.entries(coverage).map(([k, v]) => `${k}=${truncate(v)}`).join(" | ") + "\n");
381
+ }
382
+ printStatusCounts("Docs status", statusCounts(index), o);
383
+ for (const entry of index.slice(0, 10)) {
384
+ const line = formatEntry(entry, ["document", "path", "last_updated", "status"]);
385
+ if (line)
386
+ o(line + "\n");
387
+ }
388
+ return 0;
389
+ }
390
+ export function queryObjective(args, schemas, io) {
391
+ const o = out(io);
392
+ const e = err(io);
393
+ const info = schemas.objective;
394
+ if (!info) {
395
+ e(missingSchemaError("objective") + "\n");
396
+ return 1;
397
+ }
398
+ const p = artifactPath(info, "objective");
399
+ const data = loadArtifact(p);
400
+ const format = args.format ?? "text";
401
+ const isDict = data !== null && typeof data === "object" && !Array.isArray(data);
402
+ if (!isDict) {
403
+ if (format !== "text") {
404
+ return emitStateStructured("objective", structuredState("objective", [], sourceMetadata("objective", p), { filters: { status: args.status ?? null } }), format, args.fields, o, e);
405
+ }
406
+ return 0;
407
+ }
408
+ const d = data;
409
+ const legacyEntries = asList(d.entries);
410
+ if (legacyEntries.length > 0) {
411
+ let entries = legacyEntries;
412
+ const statusFilter = args.status ?? null;
413
+ if (statusFilter)
414
+ entries = filterByFieldValue(entries, "status", statusFilter);
415
+ if (format !== "text") {
416
+ return emitStateStructured("objective", structuredState("objective", entries, sourceMetadata("objective", p), { filters: { status: statusFilter } }), format, args.fields, o, e);
417
+ }
418
+ for (const entry of entries) {
419
+ const line = formatEntry(entry, ["title", "status", "target", "reason"]);
420
+ if (line)
421
+ o(line + "\n");
422
+ }
423
+ return 0;
424
+ }
425
+ const header = d.header && typeof d.header === "object" && !Array.isArray(d.header) ? d.header : {};
426
+ const objective = d.objective && typeof d.objective === "object" && !Array.isArray(d.objective) ? d.objective : d;
427
+ const title = firstPresent(header, ["title"], objective.title ?? "");
428
+ const status = firstPresent(header, ["status"], objective.status ?? "");
429
+ const closure = d.closure && typeof d.closure === "object" && !Array.isArray(d.closure) ? d.closure : {};
430
+ if (format !== "text") {
431
+ return emitStateStructured("objective", structuredState("objective", objective ? [objective] : [], sourceMetadata("objective", p), {
432
+ filters: { status: args.status ?? null },
433
+ summary: { title, status, header, closure },
434
+ }), format, args.fields, o, e);
435
+ }
436
+ o(`Objective: title=${truncate(title)} | status=${status || "unknown"}\n`);
437
+ for (const key of ["description", "target", "measurement", "direction", "unit"]) {
438
+ const value = objective[key] ?? d[key];
439
+ if (value)
440
+ o(`${key}: ${truncate(value)}\n`);
441
+ }
442
+ if (Object.keys(closure).length > 0) {
443
+ o(formatEntry(closure, ["final_value", "target", "reason"]) + "\n");
444
+ }
445
+ return 0;
446
+ }
447
+ export function queryExperiments(args, schemas, io) {
448
+ const o = out(io);
449
+ const e = err(io);
450
+ const info = schemas.experiments;
451
+ if (!info) {
452
+ e(missingSchemaError("experiments") + "\n");
453
+ return 1;
454
+ }
455
+ const p = artifactPath(info, "experiments");
456
+ const data = loadArtifact(p);
457
+ const format = args.format ?? "text";
458
+ const isDict = data !== null && typeof data === "object" && !Array.isArray(data);
459
+ if (!isDict) {
460
+ if (format !== "text") {
461
+ return emitStateStructured("experiments", structuredState("experiments", [], sourceMetadata("experiments", p), {
462
+ filters: { topic: args.topic ?? null, status: args.status ?? null, limit: args.limit ?? 5 },
463
+ }), format, args.fields, o, e);
464
+ }
465
+ return 0;
466
+ }
467
+ const d = data;
468
+ let entries = asList(d.experiments);
469
+ const statusFilter = args.status ?? null;
470
+ if (statusFilter)
471
+ entries = filterByFieldValue(entries, "status", statusFilter);
472
+ const topic = args.topic ?? null;
473
+ if (topic)
474
+ entries = filterByTopic(entries, topic, info.fields);
475
+ const limit = (args.limit ?? 5) || 5;
476
+ entries = entries.slice(-limit);
477
+ const closure = d.closure && typeof d.closure === "object" && !Array.isArray(d.closure) ? d.closure : {};
478
+ if (format !== "text") {
479
+ return emitStateStructured("experiments", structuredState("experiments", entries, sourceMetadata("experiments", p), {
480
+ filters: { topic, status: statusFilter, limit },
481
+ summary: { closure },
482
+ }), format, args.fields, o, e);
483
+ }
484
+ printStatusCounts("Experiment status", statusCounts(entries), o);
485
+ for (const entry of entries) {
486
+ o(formatEntry(entry, ["number", "date", "label", "status"]) + "\n");
487
+ const metric = entry.metric;
488
+ if (metric && typeof metric === "object" && !Array.isArray(metric)) {
489
+ const metricLine = formatEntry(metric, ["primary_value", "delta_vs_baseline"]);
490
+ if (metricLine)
491
+ o(` metric: ${metricLine}\n`);
492
+ }
493
+ for (const key of ["conclusion", "next"]) {
494
+ const value = entry[key];
495
+ if (value)
496
+ o(` ${key}: ${truncate(value)}\n`);
497
+ }
498
+ }
499
+ if (Object.keys(closure).length > 0) {
500
+ o("Closure: " + formatEntry(closure, ["final_value", "target", "reason"]) + "\n");
501
+ }
502
+ return 0;
503
+ }
504
+ const TODO_SEVERITY_ORDER_KEYS = ["critical", "degraded", "warning", "normal", "info", "annoying"];
505
+ const TODO_ITEM_RE = /^- \[([^\]]+)\]\s+(.*)/;
506
+ const TODO_SEV_GLYPHS = {
507
+ critical: "\u21f6",
508
+ degraded: "\u21c9",
509
+ warning: "\u21c9",
510
+ normal: "\u2192",
511
+ info: "\u21e2",
512
+ annoying: "\u21e2",
513
+ };
514
+ export function normalizeSeverity(value, deflt = "normal") {
515
+ const text = String(value || deflt).toLowerCase();
516
+ for (const key of TODO_SEVERITY_ORDER_KEYS) {
517
+ if (text.includes(key))
518
+ return key;
519
+ }
520
+ return deflt;
521
+ }
522
+ export function queryTodo(args, schemas, io, openOnly = false) {
523
+ const o = out(io);
524
+ const info = schemas.todo ?? { path: "TODO.md", record: undefined, schema: {}, fields: {} };
525
+ const todoPath = artifactPath(info, "todo");
526
+ const severity = args.severity ?? null;
527
+ const status = args.status ?? null;
528
+ const format = args.format ?? "text";
529
+ if (!fs.existsSync(todoPath)) {
530
+ if (format !== "text") {
531
+ return emitStateStructured("todo", structuredState("todo", [], sourceMetadata("todo", todoPath), {
532
+ filters: { severity, status },
533
+ }), format, args.fields, o, err(io));
534
+ }
535
+ return 0;
536
+ }
537
+ const data = loadArtifact(todoPath);
538
+ let entries = extractEntries(data);
539
+ if (entries.length > 0) {
540
+ if (severity)
541
+ entries = filterByFieldValue(entries, "severity", severity);
542
+ if (status)
543
+ entries = filterByFieldValue(entries, "status", status);
544
+ if (openOnly) {
545
+ entries = entries.filter((entry) => !["done", "closed", "resolved"].includes(String(entry.status ?? "open").toLowerCase()));
546
+ }
547
+ if (format !== "text") {
548
+ return emitStateStructured("todo", structuredState("todo", entries, sourceMetadata("todo", todoPath), {
549
+ filters: { severity, status, open_only: openOnly || null },
550
+ }), format, args.fields, o, err(io));
551
+ }
552
+ printStatusCounts("TODO status", statusCounts(entries), o);
553
+ for (const entry of entries) {
554
+ const line = formatEntry(entry, ["severity", "status", "description", "title"]);
555
+ if (line)
556
+ o(line + "\n");
557
+ }
558
+ return 0;
559
+ }
560
+ const text = fs.readFileSync(todoPath, "utf8");
561
+ const marker = severity ? TODO_SEV_GLYPHS[severity.toLowerCase()] ?? severity : null;
562
+ let currentSection = null;
563
+ const markdownEntries = [];
564
+ for (const rawLine of text.split(/\r\n|\r|\n/)) {
565
+ const sline = rawLine.trim();
566
+ if (sline.startsWith("## ")) {
567
+ const section = sline.slice(3).trim();
568
+ if (section.toLowerCase().includes("resolved")) {
569
+ currentSection = null;
570
+ continue;
571
+ }
572
+ currentSection = section;
573
+ continue;
574
+ }
575
+ if (currentSection === null)
576
+ continue;
577
+ const m = TODO_ITEM_RE.exec(sline);
578
+ if (!m)
579
+ continue;
580
+ if (marker && !currentSection.includes(marker))
581
+ continue;
582
+ const item = m[2].trim();
583
+ if (status && !["open", "todo"].includes(status.toLowerCase()))
584
+ continue;
585
+ markdownEntries.push({
586
+ severity: normalizeSeverity(currentSection),
587
+ status: "open",
588
+ description: item,
589
+ section: currentSection,
590
+ });
591
+ if (format === "text")
592
+ o(`[${currentSection}] ${item}\n`);
593
+ }
594
+ if (format !== "text") {
595
+ return emitStateStructured("todo", structuredState("todo", markdownEntries, sourceMetadata("todo", todoPath), {
596
+ filters: { severity, status, open_only: openOnly || null },
597
+ }), format, args.fields, o, err(io));
598
+ }
599
+ return 0;
600
+ }
601
+ const DECISION_CONTEXT_FIELDS = [
602
+ "number",
603
+ "date",
604
+ "question",
605
+ "context",
606
+ "alternatives",
607
+ "choice",
608
+ "reasoning",
609
+ "confidence",
610
+ "feeds_into",
611
+ "satisfaction",
612
+ ];
613
+ const PRIORITY_FIELDS = [
614
+ "number", "name", "title", "date", "timestamp", "status",
615
+ "phase", "choice", "grade", "type", "label", "trajectory", "confidence",
616
+ ];
617
+ const DECISION_ARCHIVE_RE = /Decision\s+(?<number>\d+)(?:\s+\((?<date>\d{4}-\d{2}-\d{2})\))?:\s*(?<summary>.*)/;
618
+ export function displayFields(fields, limit = 6) {
619
+ const ordered = PRIORITY_FIELDS.filter((p) => p in fields);
620
+ for (const fn of Object.keys(fields)) {
621
+ if (!ordered.includes(fn))
622
+ ordered.push(fn);
623
+ }
624
+ return ordered.slice(0, limit);
625
+ }
626
+ function isEmptyValue(v) {
627
+ return (v === null ||
628
+ v === undefined ||
629
+ v === "" ||
630
+ (Array.isArray(v) && v.length === 0) ||
631
+ (typeof v === "object" && !Array.isArray(v) && Object.keys(v).length === 0));
632
+ }
633
+ function decisionArchiveEntry(entry) {
634
+ const archiveEntry = entry && typeof entry === "object" && !Array.isArray(entry) ? { ...entry } : { summary: String(entry) };
635
+ archiveEntry.compacted = true;
636
+ const summary = String(archiveEntry.summary ?? "");
637
+ const match = DECISION_ARCHIVE_RE.exec(summary);
638
+ if (match && match.groups) {
639
+ if (!("number" in archiveEntry))
640
+ archiveEntry.number = parseInt(match.groups.number, 10);
641
+ if (match.groups.date && !("date" in archiveEntry))
642
+ archiveEntry.date = match.groups.date;
643
+ }
644
+ return archiveEntry;
645
+ }
646
+ export function extractDecisionEntries(data) {
647
+ if (!data || typeof data !== "object" || Array.isArray(data))
648
+ return extractEntries(data);
649
+ const d = data;
650
+ const decisions = d.decisions ?? [];
651
+ const archive = d.archive ?? [];
652
+ const entries = Array.isArray(decisions)
653
+ ? decisions.filter((e) => e && typeof e === "object" && !Array.isArray(e))
654
+ : [];
655
+ if (Array.isArray(archive)) {
656
+ for (const entry of archive)
657
+ entries.push(decisionArchiveEntry(entry));
658
+ }
659
+ return entries;
660
+ }
661
+ function filterDecisionsByTopic(entries, topic, fields) {
662
+ const t = topic.toLowerCase();
663
+ const fnames = [...stringFieldNames(fields), "summary", "outcome"];
664
+ return entries.filter((entry) => fnames.some((f) => String(entry[f] ?? "").toLowerCase().includes(t)));
665
+ }
666
+ function decisionFieldMissing(entry, field) {
667
+ return isEmptyValue(entry[field]);
668
+ }
669
+ function decisionDownstreamReferences(entry) {
670
+ const value = entry.feeds_into;
671
+ if (value === null || value === undefined || value === "")
672
+ return null;
673
+ let refs;
674
+ if (Array.isArray(value)) {
675
+ refs = value.map((item) => String(item).trim()).filter((s) => s);
676
+ }
677
+ else {
678
+ refs = String(value)
679
+ .split(",")
680
+ .map((part) => part.trim())
681
+ .filter((s) => s);
682
+ }
683
+ if (refs.length === 0)
684
+ return null;
685
+ return refs.map((ref) => ({ source_field: "feeds_into", reference: ref }));
686
+ }
687
+ export function decisionSatisfactionContext(entry) {
688
+ const satisfaction = entry.satisfaction;
689
+ if (!satisfaction || typeof satisfaction !== "object" || Array.isArray(satisfaction)) {
690
+ return {
691
+ state: null,
692
+ evidence: null,
693
+ user_confirmation: null,
694
+ review_needed: true,
695
+ source: "missing_legacy_state",
696
+ caveats: ["Missing legacy satisfaction state is not treated as satisfied."],
697
+ };
698
+ }
699
+ const sat = satisfaction;
700
+ const state = sat.state;
701
+ const evidence = sat.evidence ?? null;
702
+ const userConfirmation = sat.user_confirmation ?? null;
703
+ const explicitReviewNeeded = sat.review_needed === true;
704
+ let caveats = [];
705
+ let reviewNeeded = true;
706
+ if (state === "user_confirmed_satisfied") {
707
+ reviewNeeded =
708
+ !(userConfirmation && typeof userConfirmation === "object" && !Array.isArray(userConfirmation)) ||
709
+ Object.keys(userConfirmation).length === 0;
710
+ if (reviewNeeded)
711
+ caveats.push("User-confirmed satisfaction is missing explicit user confirmation metadata.");
712
+ }
713
+ else if (state === "provisionally_satisfied") {
714
+ if (isEmptyValue(evidence))
715
+ caveats.push("Provisional satisfaction is missing concrete evidence.");
716
+ caveats.push("Provisional satisfaction still requires user confirmation.");
717
+ }
718
+ else if (state === "open") {
719
+ caveats.push("Satisfaction state is open and requires review.");
720
+ }
721
+ else {
722
+ caveats.push("Satisfaction state is missing or unrecognized and requires review.");
723
+ }
724
+ if (explicitReviewNeeded) {
725
+ reviewNeeded = true;
726
+ caveats.push("Decision satisfaction is explicitly marked review_needed.");
727
+ }
728
+ const originalCaveats = sat.caveats;
729
+ if (Array.isArray(originalCaveats))
730
+ caveats = [...originalCaveats.map((c) => String(c)), ...caveats];
731
+ else if (typeof originalCaveats === "string")
732
+ caveats = [originalCaveats, ...caveats];
733
+ const enriched = { ...sat };
734
+ if (!("evidence" in enriched))
735
+ enriched.evidence = evidence;
736
+ if (!("user_confirmation" in enriched))
737
+ enriched.user_confirmation = userConfirmation;
738
+ enriched.review_needed = reviewNeeded;
739
+ enriched.source = "decision.satisfaction";
740
+ enriched.caveats = caveats;
741
+ return enriched;
742
+ }
743
+ export function decisionContextEntry(entry) {
744
+ const enriched = { ...entry };
745
+ if ((enriched.outcome === null || enriched.outcome === undefined || enriched.outcome === "") &&
746
+ enriched.choice !== null && enriched.choice !== undefined && enriched.choice !== "") {
747
+ enriched.outcome = enriched.choice;
748
+ }
749
+ const compacted = Boolean(enriched.compacted) ||
750
+ ("summary" in enriched &&
751
+ ["question", "reasoning", "confidence"].some((field) => decisionFieldMissing(enriched, field)));
752
+ const missingFields = DECISION_CONTEXT_FIELDS.filter((field) => decisionFieldMissing(enriched, field));
753
+ if (decisionFieldMissing(enriched, "choice") && decisionFieldMissing(enriched, "outcome")) {
754
+ missingFields.push("outcome");
755
+ }
756
+ const downstreamReferences = decisionDownstreamReferences(enriched);
757
+ const caveats = [];
758
+ if (compacted)
759
+ caveats.push("Decision entry is compacted; full decision context is not available in this CLI result.");
760
+ if (missingFields.length > 0)
761
+ caveats.push("Decision entry is missing one or more full-detail context fields.");
762
+ if (downstreamReferences === null) {
763
+ caveats.push("No explicit downstream consequence references were present; none were inferred.");
764
+ }
765
+ const satisfaction = decisionSatisfactionContext(enriched);
766
+ if (satisfaction.review_needed) {
767
+ caveats.push("Decision satisfaction requires user review; missing legacy state is not treated as satisfied.");
768
+ }
769
+ enriched.satisfaction = satisfaction;
770
+ enriched.downstream_consequence_references = downstreamReferences;
771
+ enriched.context_complete =
772
+ !compacted && missingFields.length === 0 && downstreamReferences !== null && !satisfaction.review_needed;
773
+ enriched.missing_fields = missingFields;
774
+ enriched.compacted = compacted;
775
+ enriched.caveats = caveats;
776
+ return enriched;
777
+ }
778
+ export function decisionSourceContract(source, entries, filters) {
779
+ const sourceExists = Boolean(source.exists);
780
+ const activeFilters = Object.fromEntries(Object.entries(filters).filter(([, v]) => v !== null && v !== undefined));
781
+ const filteredNoMatch = sourceExists && Object.keys(activeFilters).length > 0 && entries.length === 0;
782
+ const compactedEntries = entries.filter((e) => e.compacted).length;
783
+ const entriesWithMissingFields = entries.filter((e) => e.missing_fields && e.missing_fields.length > 0).length;
784
+ const entriesWithoutDownstream = entries.filter((e) => e.downstream_consequence_references === null).length;
785
+ const entriesRequiringSatisfactionReview = entries.filter((e) => e.satisfaction && typeof e.satisfaction === "object" && e.satisfaction.review_needed).length;
786
+ const userConfirmedSatisfied = entries.filter((e) => e.satisfaction &&
787
+ typeof e.satisfaction === "object" &&
788
+ e.satisfaction.state === "user_confirmed_satisfied" &&
789
+ !e.satisfaction.review_needed).length;
790
+ const completeForReturned = sourceExists && entries.every((e) => e.context_complete === true);
791
+ const completeForNormalDeliberation = sourceExists;
792
+ const caveats = [
793
+ "Downstream consequence references are derived only from explicit structured feeds_into values; no references are inferred.",
794
+ "Compacted archive decisions are not expanded by this command and are not complete full-detail decision context.",
795
+ ];
796
+ if (!sourceExists)
797
+ caveats.push("Decision artifact is missing or unavailable; no decision context is available from this command result.");
798
+ if (filteredNoMatch)
799
+ caveats.push("Filtered result is empty; no returned decisions match the filter, but the decision artifact was available.");
800
+ if (entriesWithMissingFields)
801
+ caveats.push("One or more returned decisions are missing full-detail context fields.");
802
+ if (entriesWithoutDownstream)
803
+ caveats.push("One or more returned decisions lack explicit downstream consequence references.");
804
+ if (entriesRequiringSatisfactionReview)
805
+ caveats.push("One or more returned decisions require satisfaction review; satisfaction is never inferred from downstream references.");
806
+ return {
807
+ artifact: "DECISIONS.md",
808
+ canonical_artifact_label: "DECISIONS.md",
809
+ path: source.path,
810
+ complete_for_returned_decisions: completeForReturned,
811
+ complete_for_decision_context: completeForReturned,
812
+ complete_for_returned_full_detail: completeForReturned,
813
+ complete_for_normal_deliberation_context: completeForNormalDeliberation,
814
+ completeness: {
815
+ returned_decisions: entries.length,
816
+ context_complete: completeForReturned,
817
+ returned_full_detail_complete: completeForReturned,
818
+ normal_deliberation_context: completeForNormalDeliberation,
819
+ filtered_no_match: filteredNoMatch,
820
+ source_exists: sourceExists,
821
+ compacted_entries: compactedEntries,
822
+ entries_with_missing_fields: entriesWithMissingFields,
823
+ entries_without_downstream_references: entriesWithoutDownstream,
824
+ entries_requiring_satisfaction_review: entriesRequiringSatisfactionReview,
825
+ user_confirmed_satisfied_entries: userConfirmedSatisfied,
826
+ },
827
+ included_fields: [
828
+ ...DECISION_CONTEXT_FIELDS,
829
+ "outcome",
830
+ "downstream_consequence_references",
831
+ "context_complete",
832
+ "missing_fields",
833
+ "compacted",
834
+ "caveats",
835
+ ],
836
+ satisfaction_context: {
837
+ owner: "decision entry",
838
+ state_field: "satisfaction.state",
839
+ evidence_field: "satisfaction.evidence",
840
+ confirmation_field: "satisfaction.user_confirmation",
841
+ review_needed_field: "satisfaction.review_needed",
842
+ confirmation_policy: "Only satisfaction.state=user_confirmed_satisfied with explicit user_confirmation metadata is reported as user-confirmed satisfied.",
843
+ non_inference_policy: "Do not infer satisfaction from feeds_into, commits, downstream files, generated references, or compacted history.",
844
+ },
845
+ normal_deliberation_context: {
846
+ use_complete_for_normal_deliberation_context: true,
847
+ legacy_full_detail_signal: "complete_for_decision_context",
848
+ guidance: "For normal deliberation, use returned entries plus missing_fields, compacted, caveats, " +
849
+ "and satisfaction review state. Do not use the legacy full-detail completeness flag " +
850
+ "as a reason to reread the raw decision artifact.",
851
+ },
852
+ decision_context_truth_table: {
853
+ full_detail_entries: {
854
+ full_detail_complete: true,
855
+ normal_deliberation_context_complete: true,
856
+ raw_artifact_read_required: false,
857
+ },
858
+ compacted_archive_entries: {
859
+ full_detail_complete: false,
860
+ normal_deliberation_context_complete: true,
861
+ raw_artifact_read_required: false,
862
+ carry_forward: ["missing_fields", "compacted", "caveats"],
863
+ },
864
+ entries_with_missing_full_detail_fields: {
865
+ full_detail_complete: false,
866
+ normal_deliberation_context_complete: true,
867
+ raw_artifact_read_required: false,
868
+ carry_forward: ["missing_fields", "caveats"],
869
+ },
870
+ satisfaction_review_needed: {
871
+ full_detail_complete: false,
872
+ normal_deliberation_context_complete: true,
873
+ raw_artifact_read_required: false,
874
+ carry_forward: ["satisfaction.review_needed", "caveats"],
875
+ },
876
+ filtered_no_match: {
877
+ full_detail_complete: true,
878
+ normal_deliberation_context_complete: true,
879
+ raw_artifact_read_required: false,
880
+ meaning: "The artifact exists, but no returned decisions matched the filter.",
881
+ },
882
+ missing_or_unavailable_artifact: {
883
+ full_detail_complete: false,
884
+ normal_deliberation_context_complete: false,
885
+ raw_artifact_read_required: false,
886
+ meaning: "No decision state is available from the CLI result; use CLI fallback or diagnostics before raw artifact repair.",
887
+ },
888
+ },
889
+ missing_full_detail_boundary: {
890
+ applies_when: "returned decisions have missing_fields or context_complete=false",
891
+ normal_behavior: "Use present structured fields only and preserve missing_fields/caveats downstream.",
892
+ raw_artifact_read_required: false,
893
+ do_not: "Do not infer absent reasoning, alternatives, confidence, feeds_into, outcome, or downstream references.",
894
+ },
895
+ missing_artifact_boundary: {
896
+ applies_when: "source.exists=false",
897
+ normal_behavior: "Treat decision context as unavailable from this result; do not infer historical decisions.",
898
+ raw_artifact_read_required: false,
899
+ diagnostic_boundary: "Raw artifact access is reserved for explicit artifact repair/corruption or CLI-defect investigation.",
900
+ },
901
+ filtered_result_boundary: {
902
+ applies_when: "filters are present and entries=[] while source.exists=true",
903
+ normal_behavior: "Treat the result as no matching returned decisions, not as missing decision state.",
904
+ raw_artifact_read_required: false,
905
+ },
906
+ satisfaction_review_boundary: {
907
+ applies_when: "one or more entries have satisfaction.review_needed=true",
908
+ normal_behavior: "Carry satisfaction review pressure forward; only user confirmation can make a decision user-confirmed satisfied.",
909
+ raw_artifact_read_required: false,
910
+ do_not: "Do not infer satisfaction from downstream references, commits, generated files, or compacted history.",
911
+ },
912
+ compacted_history_boundary: {
913
+ applies_when: "returned entries have compacted=true",
914
+ normal_behavior: "Use the compact summary and retained fields; preserve compacted/missing_fields/caveats downstream.",
915
+ raw_artifact_read_required: false,
916
+ do_not: "Do not expand archive decisions or reconstruct missing context from git history.",
917
+ },
918
+ raw_artifact_access_boundary: {
919
+ normal_deliberation: "skip raw `.agentera/decisions.yaml` reads when complete_for_normal_deliberation_context=true",
920
+ allowed_raw_artifact_uses: [
921
+ "Resonera-owned decision writes or repairs",
922
+ "artifact corruption diagnostics",
923
+ "CLI defect investigation",
924
+ ],
925
+ },
926
+ raw_artifact_reads_required: false,
927
+ raw_artifact_read_policy: "Use `agentera decisions --format json` for normal deliberation context and key normal use off " +
928
+ "complete_for_normal_deliberation_context. " +
929
+ "Do not read `.agentera/decisions.yaml` unless investigating artifact corruption or CLI defects; " +
930
+ "historical compacted gaps are exposed through missing_fields and caveats.",
931
+ caveats,
932
+ fallback_behavior: {
933
+ normal: "Use this command's entries and source_contract; no raw decision artifact read is required for returned full-detail or compacted decision entries.",
934
+ filtered_result: "The same per-decision guarantees apply after filters; an empty filtered result means no matching returned decisions.",
935
+ missing_or_incomplete: "If a required field is missing, treat only the present structured fields as authoritative and do not infer absent context.",
936
+ satisfaction: "Use only each entry's satisfaction object for satisfaction state. Missing, open, provisional, or unconfirmed satisfaction requires review and must not be reported as user-confirmed satisfied.",
937
+ compacted_history: "Compacted archive decisions are included with explicit missing_fields and caveats; treat absent historical context as unavailable during normal deliberation.",
938
+ },
939
+ fallback_policy: "If the decision artifact is missing or CLI state appears defective, use CLI fallback/diagnostic paths before raw artifact repair; do not raw-read merely because returned decisions are compacted or incomplete.",
940
+ filters: activeFilters,
941
+ };
942
+ }
943
+ export function queryDecisions(args, schemas, io) {
944
+ const o = out(io);
945
+ const e = err(io);
946
+ const info = schemas.decisions;
947
+ if (!info) {
948
+ e(missingSchemaError("decisions") + "\n");
949
+ return 1;
950
+ }
951
+ const p = artifactPath(info, "decisions");
952
+ const data = loadArtifact(p);
953
+ let entries = extractDecisionEntries(data);
954
+ const topic = args.topic ?? null;
955
+ if (topic)
956
+ entries = filterDecisionsByTopic(entries, topic, info.fields);
957
+ const format = args.format ?? "text";
958
+ if (format !== "text") {
959
+ const enriched = entries.map((entry) => decisionContextEntry(entry));
960
+ const source = sourceMetadata("decisions", p);
961
+ const filters = { topic };
962
+ return emitStateStructured("decisions", structuredState("decisions", enriched, source, {
963
+ filters,
964
+ sourceContract: decisionSourceContract(source, enriched, filters),
965
+ }), format, args.fields, o, e);
966
+ }
967
+ if (entries.length === 0)
968
+ return 0;
969
+ const disp = displayFields(info.fields);
970
+ for (const entry of entries) {
971
+ const parts = [];
972
+ for (const fn of disp) {
973
+ const v = entry[fn];
974
+ if (v !== null && v !== undefined && v !== "" && !Array.isArray(v) && typeof v !== "object") {
975
+ parts.push(`${fn}=${v}`);
976
+ }
977
+ }
978
+ if (parts.length > 0)
979
+ o(parts.join(" | ") + "\n");
980
+ }
981
+ return 0;
982
+ }
983
+ const STATE_COMMAND_HANDLERS = {
984
+ progress: queryProgress,
985
+ plan: queryPlan,
986
+ health: queryHealth,
987
+ docs: queryDocs,
988
+ objective: queryObjective,
989
+ experiments: queryExperiments,
990
+ todo: queryTodo,
991
+ decisions: queryDecisions,
992
+ };
993
+ export function isPortedStateCommand(command) {
994
+ return command in STATE_COMMAND_HANDLERS;
995
+ }
996
+ export function cmdState(args, io) {
997
+ const e = err(io);
998
+ try {
999
+ validateFilterValues(args, COMMAND_FILTERS[args.command] ?? []);
1000
+ if (args.limit !== null && args.limit !== undefined && args.limit < 0) {
1001
+ throw new Error("limit must be zero or greater");
1002
+ }
1003
+ const schemas = loadSchemas(discoverSchemasDir());
1004
+ const handler = STATE_COMMAND_HANDLERS[args.command];
1005
+ return handler(args, schemas, io);
1006
+ }
1007
+ catch (exc) {
1008
+ e(`Error: ${exc.message}\n`);
1009
+ return 2;
1010
+ }
1011
+ }
1012
+ //# sourceMappingURL=state.js.map