kibi-agent-core 0.3.1 → 0.5.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.
- package/CHANGELOG.md +22 -0
- package/dist/knowledge-index.d.ts +5 -1
- package/dist/knowledge-index.js +22 -1
- package/dist/snippets.d.ts +4 -2
- package/dist/snippets.js +11 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# kibi-agent-core
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- cd4723e: Rules a person wrote or imported are no longer treated as an agent's own default choice when they carry no `firmness`. A requirement or ADR without `firmness` now reads as `firm` unless an agent wrote it, so an agent asks before replacing it, and bootstrap records the rules it imports from your documents as firm with a reference to the passage. The usage skill now treats any request that conflicts with a recorded rule as a question: the agent names the rule and asks, whatever the rule's firmness, and changes it only when the person says so. Run `kibi migrate --yes` to move a KB to schema 10; existing supersedes are acknowledged and no source file is rewritten.
|
|
8
|
+
- `effectiveFirmness` takes the entity's origin: an absent value is `default` for `origin.kind: agent` and `firm` otherwise (human, import, migration or no origin). `kb_query` rows and `kb_search` answers show the derived value.
|
|
9
|
+
- Hook snippets label a current firm decision `[firm: ask before changing]` (was `[firm]`) and no longer label retired decisions. The Claude Code and ZCode session-start context adds one sentence: a request that conflicts with a recorded requirement or ADR is a question, so the agent names the rule and asks before changing the code or the rule.
|
|
10
|
+
- `decision-firm-superseded` applies to origin-derived firm targets; `decision-firm-unreferenced` still applies only to an explicit `firmness: firm`.
|
|
11
|
+
- KB schema 10: the `firmness-from-origin-v10` step and the automatic `firm_supersede_acknowledge` plan action record pre-existing supersedes of such decisions in `.kb/manifest.json` `firmSupersedeAcknowledged` (`FROM -> TO`); only listed edges are exempt, and never an explicitly firm target.
|
|
12
|
+
- Bootstrap intent-claim and normative-markdown requirement steps write `origin: {kind: import, ref}` and `firmness: firm`.
|
|
13
|
+
- Skills: `kibi-usage` 2.17.0 (conflicting request means ask; firmness from origin; write firmness explicitly), `kibi-bootstrap` 3.13.0 (imported rules are firm imports, including hand-authored follow-ups).
|
|
14
|
+
|
|
15
|
+
## 0.4.0
|
|
16
|
+
|
|
17
|
+
### Minor Changes
|
|
18
|
+
|
|
19
|
+
- 5ad4319: Requirements and ADRs can now say how firmly they were decided, so a later agent knows whether it may change a decision on evidence or must ask a human first. Mark a rule a person stated `firmness: firm` (it must cite their words in `origin.ref`, or `approval_ref` on a requirement), a guess `firmness: exploratory`, and leave the rest unset (`default`). `kibi check` now blocks a firm decision without that reference (Kibi checks that it is present, not that it is genuine), a decision that is not firm superseding a firm one, and a current requirement or ADR that supersedes another without a `## Why this changed` section naming the evidence. `kb_search` and `kb_query` show the firmness of each decision; the editor hooks label firm and exploratory ones.
|
|
20
|
+
|
|
21
|
+
Migration: this is a hard rollout with KB schema 9. Run `kibi migrate --yes` once; it records every supersede edge that predates the rule in the manifest (`supersedesReasonAcknowledged`, as `FROM -> TO`), so those do not block, and an advisory `supersedes-reason-acknowledged` diagnostic counts them. No source file is rewritten and no reason is invented. New supersedes must explain themselves, including a new one on an acknowledged decision.
|
|
22
|
+
|
|
23
|
+
Technical summary: new optional `firmness` property (`firm` | `default` | `exploratory`) on `req` and `adr` in the JSON schema, the `kb_upsert` input schema, the markdown extractor and the Prolog entity schema; the schema rejects it on other types. `kb_upsert` judges firmness as it will be written: an update that omits `firmness` keeps the stored value (also in the compiled store), and a write that leaves a decision firm without a reference is rejected. `decision-firm-superseded` checks every superseder, retired ones included, so a chain cannot launder a firm decision; shard edges from deleted entities are ignored. New rules `decision-firm-unreferenced`, `decision-firm-superseded` and `supersedes-reason-missing` (canonical, blocking) and `supersedes-reason-acknowledged` (info) read authored requirements, ADRs, front-matter `supersedes` links and relationship shards, so they agree before a sync. `LATEST_KB_SCHEMA_VERSION` is 9; the `decision-firmness-v9` migration step and the `supersedes-reason-acknowledge` fragment action write only `.kb/manifest.json`. Search answer rows and `kb_query` results carry the effective firmness of requirements and ADRs; hook snippets append `[firm]` or `[exploratory]`. The `kibi-usage` skill gains a "Decision firmness" section.
|
|
24
|
+
|
|
3
25
|
## 0.3.1
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
|
@@ -71,7 +71,11 @@ export type EntitySummary = {
|
|
|
71
71
|
id: string;
|
|
72
72
|
title?: string;
|
|
73
73
|
status?: string;
|
|
74
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* Requirement or ADR firmness: as authored, else what the origin implies
|
|
76
|
+
* (`default` when an agent wrote it, `firm` otherwise). Absent when the
|
|
77
|
+
* front matter could not be read whole.
|
|
78
|
+
*/
|
|
75
79
|
firmness?: string;
|
|
76
80
|
/**
|
|
77
81
|
* Frontmatter `links` (plain string entries read as `relates_to`) merged
|
package/dist/knowledge-index.js
CHANGED
|
@@ -714,10 +714,24 @@ export function readEntitySummary(workspaceRoot, entityId) {
|
|
|
714
714
|
const summary = { id: entityId };
|
|
715
715
|
const authored = [];
|
|
716
716
|
let inLinks = false;
|
|
717
|
+
let inOrigin = false;
|
|
718
|
+
let originKind;
|
|
719
|
+
let closed = false;
|
|
717
720
|
let pending;
|
|
718
721
|
for (const line of lines.slice(1)) {
|
|
719
|
-
if (line.trim() === "---")
|
|
722
|
+
if (line.trim() === "---") {
|
|
723
|
+
closed = true;
|
|
720
724
|
break;
|
|
725
|
+
}
|
|
726
|
+
// implements REQ-kb-decision-firmness-from-origin
|
|
727
|
+
const flowOrigin = /^origin:\s*\{.*\bkind:\s*["']?([a-z]+)/.exec(line);
|
|
728
|
+
if (flowOrigin)
|
|
729
|
+
originKind = flowOrigin[1];
|
|
730
|
+
const nestedKind = inOrigin ? /^\s+kind:\s*["']?([a-z]+)/.exec(line) : null;
|
|
731
|
+
if (nestedKind)
|
|
732
|
+
originKind = nestedKind[1];
|
|
733
|
+
if (/^\S/.test(line))
|
|
734
|
+
inOrigin = /^origin:\s*$/.test(line);
|
|
721
735
|
const match = /^(title|status|firmness):\s*(.*)$/.exec(line);
|
|
722
736
|
if (match?.[1] === "title" && match[2])
|
|
723
737
|
summary.title = unquote(match[2]);
|
|
@@ -754,6 +768,13 @@ export function readEntitySummary(workspaceRoot, entityId) {
|
|
|
754
768
|
pending.bare = unquote(body);
|
|
755
769
|
}
|
|
756
770
|
flushLink(authored, pending);
|
|
771
|
+
// A decision without authored firmness is a person's (firm) unless an
|
|
772
|
+
// agent wrote it; with the front matter cut off, the origin is unknown.
|
|
773
|
+
// implements REQ-kb-decision-firmness-from-origin
|
|
774
|
+
if (summary.firmness === undefined &&
|
|
775
|
+
closed &&
|
|
776
|
+
(lane[1] === "requirements" || lane[1] === "adr"))
|
|
777
|
+
summary.firmness = originKind === "agent" ? "default" : "firm";
|
|
757
778
|
const links = [];
|
|
758
779
|
const seen = new Set();
|
|
759
780
|
for (const link of [
|
package/dist/snippets.d.ts
CHANGED
|
@@ -26,8 +26,10 @@ export declare function editFocus(absolutePath: string, toolInput: unknown): Lin
|
|
|
26
26
|
export declare function isRetiredStatus(status: string | undefined): boolean;
|
|
27
27
|
/**
|
|
28
28
|
* `ID (status) [firmness]: title`, with the status shown only when it is
|
|
29
|
-
* retired and the firmness only
|
|
30
|
-
*
|
|
29
|
+
* retired and the firmness only on a current decision: `[firm: ask before
|
|
30
|
+
* changing]` says what a firm rule asks of the agent where it reads it, and
|
|
31
|
+
* `[exploratory]` marks a guess. An unlabeled current decision is `default`,
|
|
32
|
+
* an agent's choice.
|
|
31
33
|
*/
|
|
32
34
|
export declare function describeEntity(summary: EntitySummary): string;
|
|
33
35
|
/** Discovery note for a source file none of whose symbols implement a requirement. */
|
package/dist/snippets.js
CHANGED
|
@@ -100,16 +100,22 @@ const RETIRED_STATUS = /supersed|deprecat|reject|obsolete|retired/i;
|
|
|
100
100
|
export function isRetiredStatus(status) {
|
|
101
101
|
return status !== undefined && RETIRED_STATUS.test(status);
|
|
102
102
|
}
|
|
103
|
-
// implements REQ-agent-core-edit-snippets, REQ-claude-code-kibi-plugin-v1, REQ-opencode-kibi-plugin-v1, REQ-kb-decision-firmness
|
|
103
|
+
// implements REQ-agent-core-edit-snippets, REQ-claude-code-kibi-plugin-v1, REQ-opencode-kibi-plugin-v1, REQ-kb-decision-firmness, REQ-kb-decision-firmness-from-origin
|
|
104
104
|
/**
|
|
105
105
|
* `ID (status) [firmness]: title`, with the status shown only when it is
|
|
106
|
-
* retired and the firmness only
|
|
107
|
-
*
|
|
106
|
+
* retired and the firmness only on a current decision: `[firm: ask before
|
|
107
|
+
* changing]` says what a firm rule asks of the agent where it reads it, and
|
|
108
|
+
* `[exploratory]` marks a guess. An unlabeled current decision is `default`,
|
|
109
|
+
* an agent's choice.
|
|
108
110
|
*/
|
|
109
111
|
export function describeEntity(summary) {
|
|
110
112
|
const retired = isRetiredStatus(summary.status) ? ` (${summary.status})` : "";
|
|
111
|
-
|
|
112
|
-
|
|
113
|
+
// A retired decision binds nothing, however firmly it was once made.
|
|
114
|
+
const firmness = !retired &&
|
|
115
|
+
(summary.firmness === "firm" || summary.firmness === "exploratory")
|
|
116
|
+
? summary.firmness === "firm"
|
|
117
|
+
? " [firm: ask before changing]"
|
|
118
|
+
: " [exploratory]"
|
|
113
119
|
: "";
|
|
114
120
|
const notable = `${retired}${firmness}`;
|
|
115
121
|
return summary.title
|