kibi-agent-core 0.8.1 → 0.9.1

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # kibi-agent-core
2
2
 
3
+ ## 0.9.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 45036a3: Signoff guidance no longer tells agents to attach `latest.html` as a file. Chat apps (the Claude apps, Slack and most others) show an attached HTML file as raw source or a download, so agents now share the page only as a rendered page, such as a Claude Artifact, and otherwise leave the message text as the whole view. Updates the kibi-decisions and kibi-commit-review skills (1.2.1), the `kibi signoff` page note and the stop-hook reminder.
8
+
9
+ ## 0.9.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 180196c: The requirements signoff view now reads well on every host, not only in the hosts that draw Kibi's fenced block.
14
+ - `kibi signoff` prints plain Markdown by default (`--format chat`): headings, quoted statements and lists that render in any chat window, and in messaging tools for agents whose replies go through one (cloud and project sessions). The path of the self-contained page `.kb/briefs/signoff/latest.html` goes to stderr, so an agent can attach or publish it next to the message. `--format md` keeps the fenced block for the OpenCode terminal card, and `KIBI_SIGNOFF_FORMAT` sets the default per host.
15
+ - After a session writes a requirement, the Claude Code, Codex, Cursor and ZCode stop hooks ask once for the signoff view before the work is reported done, unless `kibi signoff` already ran since. A requirement the agent wrote is put to the person through the view, not retold in the agent's words.
16
+ - `/kibi-signoff` is a new command in Claude Code, Cursor and ZCode.
17
+ - The `kibi-decisions` and `kibi-commit-review` skills (1.2.0) say how to show the view on each host, and `kibi-usage` (2.22.0) points to `kibi signoff` when it says to leave `approved_by` to the person. The OpenCode guidance asks for `--format md` so the terminal card still renders.
18
+ - The Claude Code plugin README shows the `.claude/settings.json` snippet that loads the plugin in cloud sessions.
19
+
3
20
  ## 0.8.1
4
21
 
5
22
  ### Patch Changes
@@ -55,7 +55,7 @@ export type DecisionSession = {
55
55
  sessionId: string | undefined;
56
56
  };
57
57
  /** Session markers the decision guard keeps. */
58
- export type DecisionFlag = "source-edited" | "kb-recorded" | "rule-prompt" | "capture-asked";
58
+ export type DecisionFlag = "source-edited" | "kb-recorded" | "rule-prompt" | "capture-asked" | "requirement-recorded" | "signoff-asked";
59
59
  /** Set a session marker; best effort. */
60
60
  export declare function markDecisionFlag(session: DecisionSession, flag: DecisionFlag): void;
61
61
  export declare function hasDecisionFlag(session: DecisionSession, flag: DecisionFlag): boolean;
@@ -77,6 +77,21 @@ export declare function requestWords(session: DecisionSession): string[];
77
77
  * not been asked yet (claiming the ask).
78
78
  */
79
79
  export declare function claimCaptureReminder(session: DecisionSession): boolean;
80
+ /** Where `kibi signoff` keeps the latest view, relative to the workspace. */
81
+ export declare const SIGNOFF_LATEST_JSON: string;
82
+ /**
83
+ * Whether a kb_upsert call's input writes a requirement (not a dry run).
84
+ * Hosts pass the MCP arguments, sometimes wrapped in `arguments`.
85
+ */
86
+ export declare function isRequirementUpsert(toolInput: unknown): boolean;
87
+ /**
88
+ * Whether the stop should ask for a signoff view: the session wrote a
89
+ * requirement, `kibi signoff` has not written a view since, and the session
90
+ * has not been asked yet (claiming the ask).
91
+ */
92
+ export declare function claimSignoffReminder(session: DecisionSession, workspaceRoot: string): boolean;
93
+ /** Stop-time note for a session that recorded requirements without a signoff view. */
94
+ export declare function signoffReminder(): string;
80
95
  /** Firm requirements the agent was already told about this session. */
81
96
  export declare function settledFirmRequirements(session: DecisionSession): Set<string>;
82
97
  /** Remember that the agent was told about these firm requirements. */
@@ -212,6 +212,57 @@ export function claimCaptureReminder(session) {
212
212
  !hasDecisionFlag(session, "kb-recorded") &&
213
213
  claimDecisionFlag(session, "capture-asked"));
214
214
  }
215
+ // implements REQ-kibi-signoff-views
216
+ /** Where `kibi signoff` keeps the latest view, relative to the workspace. */
217
+ export const SIGNOFF_LATEST_JSON = path.join(".kb", "briefs", "signoff", "latest.json");
218
+ function record(value) {
219
+ return typeof value === "object" && value !== null && !Array.isArray(value)
220
+ ? value
221
+ : undefined;
222
+ }
223
+ // implements REQ-kibi-signoff-views
224
+ /**
225
+ * Whether a kb_upsert call's input writes a requirement (not a dry run).
226
+ * Hosts pass the MCP arguments, sometimes wrapped in `arguments`.
227
+ */
228
+ export function isRequirementUpsert(toolInput) {
229
+ const input = record(toolInput);
230
+ const args = record(input?.arguments) ?? record(input?.args) ?? input;
231
+ return args?.type === "req" && args.dryRun !== true;
232
+ }
233
+ function mtimeMs(file) {
234
+ if (!file)
235
+ return undefined;
236
+ try {
237
+ return fs.statSync(file).mtimeMs;
238
+ }
239
+ catch {
240
+ return undefined;
241
+ }
242
+ }
243
+ // implements REQ-kibi-signoff-views
244
+ /**
245
+ * Whether the stop should ask for a signoff view: the session wrote a
246
+ * requirement, `kibi signoff` has not written a view since, and the session
247
+ * has not been asked yet (claiming the ask).
248
+ */
249
+ export function claimSignoffReminder(session, workspaceRoot) {
250
+ const recorded = mtimeMs(sessionPath(session, "requirement-recorded"));
251
+ if (recorded === undefined)
252
+ return false;
253
+ const shown = mtimeMs(path.join(workspaceRoot, SIGNOFF_LATEST_JSON));
254
+ if (shown !== undefined && shown >= recorded)
255
+ return false;
256
+ return claimDecisionFlag(session, "signoff-asked");
257
+ }
258
+ // implements REQ-kibi-signoff-views
259
+ /** Stop-time note for a session that recorded requirements without a signoff view. */
260
+ export function signoffReminder() {
261
+ return [
262
+ "Kibi: this session recorded or changed requirements, and the person has not seen them as a signoff view.",
263
+ "Before reporting the work done or asking to commit, run `kibi signoff` and put its output in the reply unchanged; a requirement the agent wrote waits for the person's approval, so ask for it with this view, never in your own words. When replies go through a messaging tool, pass the output there as the message text, and share `.kb/briefs/signoff/latest.html` only as a rendered page (the Artifact tool in Claude apps), never as an attached file, which chat apps show as raw source (kibi-decisions, resources/signoff-views.md).",
264
+ ].join("\n");
265
+ }
215
266
  function readSettled(file) {
216
267
  if (!file)
217
268
  return [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kibi-agent-core",
3
- "version": "0.8.1",
3
+ "version": "0.9.1",
4
4
  "description": "Shared low-latency hook helpers for Kibi agent adapters",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -66,6 +66,6 @@
66
66
  "@types/node": "^25.9.8",
67
67
  "semver": "^7.8.5",
68
68
  "typescript": "^5.7.0",
69
- "yaml": "^2.9.0"
69
+ "yaml": "^2.9.1"
70
70
  }
71
71
  }