@antoneeo/kb-agentic-skill 1.26.0 → 1.28.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/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/skills/kb-agentic-skill/SKILL.md +2 -2
- package/skills/kb-agentic-skill/docs_site/app.js +9 -3
- package/skills/kb-agentic-skill/review.md +28 -3
- package/skills/kb-agentic-skill/scripts/docs_site.py +22 -5
- package/skills/kb-agentic-skill/scripts/sdlc_core.py +12 -1
- package/skills/kb-agentic-skill/templates.md +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
Every significant change to this skill is recorded here.
|
|
4
4
|
|
|
5
|
+
## [1.28.0] - 2026-10-19
|
|
6
|
+
|
|
7
|
+
Includes everything listed under [1.27.0], which was tagged but never published to npm.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Docs site: each card in Open work and each feature in Features links its merge review and its end-to-end test script, when they exist. They were reachable only inside a feature's chain page; who merges looks in Open work while the work is open, who tests looks in Features after it closed.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Docs site: Features are listed newest first by their declared start date; those without a start date come last.
|
|
14
|
+
|
|
15
|
+
## [1.27.0] - 2026-10-18
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
- F-071: a review weighs effort against what the owner asked for. In a design review, each outcome the owner named (the opening request, any entry widening scope, an approved north star) is a row of the conformance statement, saying where the design serves it and what share of the design goes to it; an outcome no section serves, or one served by a minor share while a secondary concern takes the bulk, is a finding. `review.md` §Reviewing.
|
|
19
|
+
- F-071: a review runs where something is left to judge. At level 2 the closure review is due only on a security-sensitive area the lens's Rule Zero names, or at the owner's request; otherwise it does not run and logs no row. After a design or closure PASS, a delta made only of version and release metadata, regenerated indexes and audit-mark records, tool-verified copies of a shared file, and CHANGELOG lines adding no claim is not reviewed: its own check runs and a `NOT DUE` row records it. README or overview prose, an E2E script, a rulings row, doctrine, behaviour, tests and any correction of a review finding are still reviewed. `review.md` §When a review is due.
|
|
20
|
+
- `sdlc_check.py benefit` counts `NOT DUE` rows apart, in no review or findings figure.
|
|
21
|
+
|
|
22
|
+
## [1.26.1] - 2026-10-18
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- F-072 (field run): the `SKILL.md` line that announces the docs site now reads `scripts/docs_site.py --root <project> --open` and says to use it to show the project state. Asked for the state, an agent had opened the site in its own client pane, where it renders blank, and improvised a local server; `--open` opens it in the user's browser, where it works offline.
|
|
26
|
+
|
|
5
27
|
## [1.26.0] - 2026-10-18
|
|
6
28
|
|
|
7
29
|
### Added
|
package/gemini-extension.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kb-agentic-skill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.0",
|
|
4
4
|
"description": "Knowledge-Base & Document-First protocol with risk triage, Vision governance, signal distillation and optional devPNT integration.",
|
|
5
5
|
"author": "Antonio Pinto (https://github.com/Antoneeo)"
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antoneeo/kb-agentic-skill",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.0",
|
|
4
4
|
"description": "Knowledge-Base & Document-First protocol for Claude Code, Gemini CLI, Google Antigravity and Codex with risk triage, Vision governance, signal distillation and optional devPNT integration.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kb-agentic
|
|
3
|
-
version: 1.
|
|
3
|
+
version: 1.28.0
|
|
4
4
|
description: Knowledge-Base & Document-First protocol with risk-proportional triage, Vision as a guide, Signal Distillation, a complete Standalone mode and optional symbiosis with devPNT. Use for user documentation, knowledge extraction, SOPs, research notes, decision logs, knowledge management — and for answering project questions from the claim ledger and topic graph.
|
|
5
5
|
author: Antonio Pinto (https://github.com/Antoneeo)
|
|
6
6
|
copyright: (c) 2026 Antonio Pinto
|
|
@@ -25,7 +25,7 @@ Support files in the skill directory:
|
|
|
25
25
|
- `dispatch.md`: opt-in subagent execution of an approved plan, plus the family-wide delegation boundary (what may be delegated at all) — that part applies at any level.
|
|
26
26
|
- `routing.md`: which lens owns this unit of work. Read ONLY when a sibling lens skill is installed alongside this one; a single-lens install never reads it.
|
|
27
27
|
- `scripts/sdlc_check.py` + `scripts/sdlc_core.py`: the mechanical validator for the docs root (`check`, `validate`, `index`, `mark`, `benefit`, `gate`, `plan`, `orient`, `migrate`, and the knowledge overlay: `graph`, `corpus`, `claim-id`, `anchor`, `export`, `import`, `stale` (spine staleness plus `## claims` -- the time cycle's consolidated view), plus `remind` — the opt-in per-turn one-line reminder, ENFORCEMENT §4). Keep the entry point, `scripts/sdlc_core.py` and `scripts/knowledge.py` together; the last supplies common memory and KB integrity.
|
|
28
|
-
- `scripts/docs_site.py --root <project
|
|
28
|
+
- `scripts/docs_site.py --root <project> --open`: opens in the user's browser a read-only site of what the agent reads; use it to show the project state.
|
|
29
29
|
- `ENFORCEMENT.md`: optional setup for CI and hooks.
|
|
30
30
|
|
|
31
31
|
Read these files only when needed. `SKILL.md` is the operating contract; the support files are progressive resources.
|
|
@@ -273,6 +273,11 @@
|
|
|
273
273
|
C.chronology.length ? eventList(C.chronology) : el("p", { "class": "empty", text: t("chronology_empty") }));
|
|
274
274
|
}
|
|
275
275
|
|
|
276
|
+
function verifyLinks(o) {
|
|
277
|
+
return [o.merge ? docLink(o.merge, t("chain_merge")) : null,
|
|
278
|
+
o.e2e ? docLink(o.e2e, t("chain_e2e")) : null].filter(Boolean);
|
|
279
|
+
}
|
|
280
|
+
|
|
276
281
|
function pageWork() {
|
|
277
282
|
setNav("work");
|
|
278
283
|
var w = C.work;
|
|
@@ -289,7 +294,7 @@
|
|
|
289
294
|
el("h3", { text: c.name }),
|
|
290
295
|
el("dl", null, rows),
|
|
291
296
|
c.next ? el("div", { "class": "next" }, el("b", { text: t("work_next") }), c.next) : null,
|
|
292
|
-
el("div", { "class": "links" }, docLink(c.path, t("work_resume"))));
|
|
297
|
+
el("div", { "class": "links" }, docLink(c.path, t("work_resume")), verifyLinks(c)));
|
|
293
298
|
}))
|
|
294
299
|
: el("p", { "class": "empty", text: t("work_empty") });
|
|
295
300
|
main(heading(t("work_title"), t("work_why")), cards,
|
|
@@ -331,14 +336,15 @@
|
|
|
331
336
|
return el("div", { "class": "unit" },
|
|
332
337
|
el("span", { "class": "id", text: u.id || "" }),
|
|
333
338
|
docLink(u.path, u.name),
|
|
334
|
-
el("div", { "class": "muted" }, [u.status, u.level ? levelLabel(u.level) : null, lensName(u.lens), dates(u)].filter(written).join(" · "))
|
|
339
|
+
el("div", { "class": "muted" }, [u.status, u.level ? levelLabel(u.level) : null, lensName(u.lens), dates(u)].filter(written).join(" · ")),
|
|
340
|
+
verifyLinks(u).length ? el("div", { "class": "links" }, verifyLinks(u)) : null);
|
|
335
341
|
}));
|
|
336
342
|
}));
|
|
337
343
|
} else {
|
|
338
344
|
body = el("table", { "class": "list" },
|
|
339
345
|
el("thead", null, el("tr", null, [t("units_id"), t("units_name"), t("work_status"), t("work_level"), t("units_lens"), t("units_dates")].map(function (h) { return el("th", { text: h }); }))),
|
|
340
346
|
el("tbody", null, shown.map(function (u) {
|
|
341
|
-
return el("tr", null, el("td", null, el("code", { text: u.id || "" })), el("td", null, docLink(u.path, u.name)),
|
|
347
|
+
return el("tr", null, el("td", null, el("code", { text: u.id || "" })), el("td", null, docLink(u.path, u.name), verifyLinks(u).length ? el("div", { "class": "links" }, verifyLinks(u)) : null),
|
|
342
348
|
el("td", null, u.status ? statusPill(u.status, u.group) : ""), el("td", { text: u.level ? levelLabel(u.level) : "" }),
|
|
343
349
|
el("td", { text: lensName(u.lens) }), el("td", { text: dates(u) }));
|
|
344
350
|
})));
|
|
@@ -15,7 +15,24 @@ Two moments, and they review different things:
|
|
|
15
15
|
|---|---|---|---|
|
|
16
16
|
| **1. Design review** | End of Phase 3 — **before any implementation** | the ANALYSIS (Standalone) / the `E-ISP`+`E-TDD` (Hybrid) | L3 |
|
|
17
17
|
| **1b. Late arrival** | Work that became L3 *after* code existed — an L1/L2 reclassified mid-flight, or a design increment on a feature already implemented — runs moment 1 **now**, before any further implementation, logged `design (late)` | same | L3 |
|
|
18
|
-
| **2. Closure review** | Phase 5, before DONE | the actual diff, against that approved design | L2 / L3 —
|
|
18
|
+
| **2. Closure review** | Phase 5, before DONE | the actual diff, against that approved design | L2 / L3 — at level 2 (L2; E2 in a lens that counts E-levels) it is due only on a security-sensitive area the lens's Rule Zero names, or at the owner's request, and otherwise does not run and logs no row; every review that runs logs its row |
|
|
19
|
+
|
|
20
|
+
**A delta after a PASS reopens a review only where it changes what was judged.**
|
|
21
|
+
A review lowers one risk — a judgement its author is blind to — at the cost of a
|
|
22
|
+
deep reviewer's full read. After a design or closure PASS, a delta made only of
|
|
23
|
+
these kinds carries no new judgement, and the closure review is **not due** on it:
|
|
24
|
+
version numbers and release metadata; regenerated indexes and audit-mark records;
|
|
25
|
+
copies of a shared file that a tool verifies identical to the reviewed one; and
|
|
26
|
+
CHANGELOG lines that state nothing the reviewed artifacts do not already state. The
|
|
27
|
+
list is closed and content governs it: a CHANGELOG line adding a claim is judged
|
|
28
|
+
work, and a change answering a review finding is never in it (§Review-driven
|
|
29
|
+
corrections governs that). Such a delta is verified by its own check and logged as a
|
|
30
|
+
row with `tier` `closure`, `model` `none (not due)`, findings `0`, rounds `0` and
|
|
31
|
+
verdict `NOT DUE: <the kinds; the check that ran and its result>`; a failing check
|
|
32
|
+
makes the delta judged work. Any other change after the PASS — README or overview
|
|
33
|
+
prose, an E2E script, a rulings row, doctrine, design, behaviour, a test — is
|
|
34
|
+
reviewed, scoped to that part. In Hybrid, devPNT doctrine §4.6 adds to this rule,
|
|
35
|
+
never yields to it.
|
|
19
36
|
|
|
20
37
|
**The agent review comes first, the human's after — never instead (Hybrid).**
|
|
21
38
|
No governed artifact that this file reviews — the design (`E-ISP`, `E-TDD`),
|
|
@@ -172,7 +189,7 @@ logging only passes would erase exactly that evidence. The row goes in
|
|
|
172
189
|
`| date | doc_key | tier | model | reviewer | findings_raised | findings_real | verdict | revise_rounds |`,
|
|
173
190
|
with `tier` = `design` or `closure` in Standalone. **`model` records the capability
|
|
174
191
|
tier that actually ran** — `deep`, `light`, `economy`, `single (client exposes no
|
|
175
|
-
choice)`,
|
|
192
|
+
choice)`, `below floor: <reason>`, or `none (not due)` on a NOT DUE row — never a provider name in doctrine (a project
|
|
176
193
|
may of course write its own model names in its own log). Without it the floor above
|
|
177
194
|
is a belief: the row would say a gate ran and never whether it could do its job, and
|
|
178
195
|
the correlation with `revise_rounds` and `findings_real` — the only evidence the
|
|
@@ -394,7 +411,15 @@ When you are the reviewer:
|
|
|
394
411
|
every use-case/user-need (and the Actor it serves — a use-case with no defined Actor,
|
|
395
412
|
or an Actor UX expectation the solution does not meet, is a finding), every threat, and
|
|
396
413
|
every applicable Vision benefit/Non-Goal, state WHERE the artifact satisfies it (section
|
|
397
|
-
or `file:line`) or raise it as a finding.
|
|
414
|
+
or `file:line`) or raise it as a finding. **For an L3/E3 unit, each outcome the owner
|
|
415
|
+
named — in the request record (the opening request and every entry widening scope) or
|
|
416
|
+
in an approved north star — is a row too, weighed by effort**: where the design serves
|
|
417
|
+
it and what share of the design (its sections and planned changes) goes to it. An
|
|
418
|
+
outcome no section serves, or one served by a minor share while a secondary concern
|
|
419
|
+
takes the bulk, is a finding — the drift every per-constraint row misses when each
|
|
420
|
+
constraint is met. In the lens whose `SKILL.md` defines Execute-Before-Specify, an
|
|
421
|
+
outcome whose owner's words name a comparative effect also needs, as evidence, the
|
|
422
|
+
probe that shows it, red on the baseline; you rule whether the words name one. A PASS/approve is **not valid on "found nothing"** — the conformance
|
|
398
423
|
statement is the proof the check ran; an unfalsifiable "I checked" is the review
|
|
399
424
|
theater this discipline exists to prevent (the reviewer-side twin of §Receiving's
|
|
400
425
|
silent-drop rule). Plain code reviews stay findings-only.
|
|
@@ -947,6 +947,21 @@ def analysis_chain(body):
|
|
|
947
947
|
return [{"step": s, "sections": found[s]} for s in CHAIN_STEPS]
|
|
948
948
|
|
|
949
949
|
|
|
950
|
+
def companion_paths(stem):
|
|
951
|
+
"""The documents named after a unit's stem: (key, docs-relative path). One list,
|
|
952
|
+
read by the chain page and by the work and feature lists."""
|
|
953
|
+
return (("merge", "solutions/MERGE_REVIEW_%s.md" % stem),
|
|
954
|
+
("e2e", "solutions/E2E_TEST_%s.md" % stem),
|
|
955
|
+
("request", "audit/requests/REQUEST_%s.md" % stem))
|
|
956
|
+
|
|
957
|
+
|
|
958
|
+
def verify_links(docs, stem):
|
|
959
|
+
"""The merge brief and E2E script of a unit, where they exist: who merges reads the
|
|
960
|
+
first while the work is open, who tests reads the second after it closed."""
|
|
961
|
+
return {key: path for key, path in companion_paths(stem)
|
|
962
|
+
if key in ("merge", "e2e") and (docs / path).is_file()}
|
|
963
|
+
|
|
964
|
+
|
|
950
965
|
def link_companions(docs, pages):
|
|
951
966
|
"""Each analysis's merge brief, E2E script and request record, where they exist,
|
|
952
967
|
and the project's North Star (R25)."""
|
|
@@ -962,11 +977,8 @@ def link_companions(docs, pages):
|
|
|
962
977
|
continue
|
|
963
978
|
stem = chain.pop("_stem")
|
|
964
979
|
chain["north_star"] = north_star
|
|
965
|
-
chain["companions"] = {
|
|
966
|
-
|
|
967
|
-
for key, path in (("merge", "solutions/MERGE_REVIEW_%s.md" % stem),
|
|
968
|
-
("e2e", "solutions/E2E_TEST_%s.md" % stem),
|
|
969
|
-
("request", "audit/requests/REQUEST_%s.md" % stem))}
|
|
980
|
+
chain["companions"] = {key: path if path in pages else None
|
|
981
|
+
for key, path in companion_paths(stem)}
|
|
970
982
|
|
|
971
983
|
|
|
972
984
|
def orientation_sources(docs):
|
|
@@ -1055,6 +1067,7 @@ def build_work(project, docs, facts):
|
|
|
1055
1067
|
for key in ("status", "level", "since", "updated", "branch", "next"):
|
|
1056
1068
|
if _v(meta, key):
|
|
1057
1069
|
card[key] = _v(meta, key)
|
|
1070
|
+
card.update(verify_links(docs, p.stem[len("HANDOFF_"):]))
|
|
1058
1071
|
cards.append(card)
|
|
1059
1072
|
cards.sort(key=lambda c: c["name"].lower())
|
|
1060
1073
|
cards.sort(key=lambda c: c.get("updated", ""), reverse=True)
|
|
@@ -1083,8 +1096,12 @@ def build_units(project, lens):
|
|
|
1083
1096
|
u[key] = _v(meta, field)
|
|
1084
1097
|
if "id" not in u and _v(meta, "feature"):
|
|
1085
1098
|
u["id"] = _v(meta, "feature")
|
|
1099
|
+
u.update(verify_links(sdlc_core.ai_path(project), p.stem[len("ANALYSIS_"):]))
|
|
1086
1100
|
units.append(u)
|
|
1101
|
+
# newest first by declared start date (owner, 2026-10-19); undated last, by id
|
|
1087
1102
|
units.sort(key=lambda u: (u.get("id", ""), u["path"]))
|
|
1103
|
+
units.sort(key=lambda u: u.get("start", ""), reverse=True)
|
|
1104
|
+
units.sort(key=lambda u: not u.get("start"))
|
|
1088
1105
|
return units
|
|
1089
1106
|
|
|
1090
1107
|
|
|
@@ -2598,6 +2598,13 @@ def _is_pass(verdict):
|
|
|
2598
2598
|
return re.search(r"\bPASS\b", (verdict or "").upper()) is not None
|
|
2599
2599
|
|
|
2600
2600
|
|
|
2601
|
+
def _is_not_due(verdict):
|
|
2602
|
+
"""A review ruled not due (review.md, a delta that only restates judged
|
|
2603
|
+
work): logged so a skip stays visible, but it is neither a review nor a
|
|
2604
|
+
finding, so it stays out of every count below (F-071)."""
|
|
2605
|
+
return (verdict or "").strip().upper().startswith("NOT DUE")
|
|
2606
|
+
|
|
2607
|
+
|
|
2601
2608
|
def _print_read_cost():
|
|
2602
2609
|
"""The cost side, printed with the benefit and NEVER without it: a catch
|
|
2603
2610
|
rate with no cost term justifies unbounded doctrine, and a cost term with
|
|
@@ -2638,6 +2645,8 @@ def cmd_benefit(root):
|
|
|
2638
2645
|
_print_read_cost()
|
|
2639
2646
|
return 0
|
|
2640
2647
|
rows, unparsed = parse_review_log(read_text(log))
|
|
2648
|
+
not_due = [r for r in rows if _is_not_due(r["verdict"])]
|
|
2649
|
+
rows = [r for r in rows if not _is_not_due(r["verdict"])]
|
|
2641
2650
|
# `tier` carries the MOMENT in Standalone (design / closure) and the
|
|
2642
2651
|
# reviewer WEIGHT in Hybrid (deep / light / code / guide / vision). A
|
|
2643
2652
|
# Hybrid row is a real review whose moment this column does not state, so
|
|
@@ -2662,9 +2671,11 @@ def cmd_benefit(root):
|
|
|
2662
2671
|
unstated_code += n
|
|
2663
2672
|
classified = moments["design"] + moments["closure"]
|
|
2664
2673
|
print("rows parsed: %d rows unparsed: %d%s"
|
|
2665
|
-
% (len(rows), len(unparsed),
|
|
2674
|
+
% (len(rows) + len(not_due), len(unparsed),
|
|
2666
2675
|
(" -> " + "; ".join("line %d: %s" % u for u in unparsed[:5]))
|
|
2667
2676
|
if unparsed else ""))
|
|
2677
|
+
print("reviews ruled not due (logged, counted in no figure below): %d"
|
|
2678
|
+
% len(not_due))
|
|
2668
2679
|
print("reviews with a stated moment: %d moment not stated by `tier`: %d%s"
|
|
2669
2680
|
% (len(classified), sum(unstated.values()),
|
|
2670
2681
|
(" (" + ", ".join("%s x%d" % (t, n) for t, n
|
|
@@ -555,7 +555,8 @@ columns: Standalone adds `reviewer`, a Hybrid row adds `instrument` and
|
|
|
555
555
|
and `closure` (Standalone); `deep`, `light`, `code`, `guide`, `vision` (devPNT gates
|
|
556
556
|
and the Vision blind check). `model` is a different question about the same review: `tier` says WHICH GATE ran,
|
|
557
557
|
`model` says WHAT CAPABILITY ran it (`deep`, `light`, `economy`,
|
|
558
|
-
`single (client exposes no choice)`, `below floor: <reason
|
|
558
|
+
`single (client exposes no choice)`, `below floor: <reason>`, `none (not due)` on a
|
|
559
|
+
NOT DUE row — the floor and its
|
|
559
560
|
arbitration are `review.md` §The capability floor). The two columns share the words
|
|
560
561
|
`deep`/`light` and mean different things by them, which is why they are read by
|
|
561
562
|
header and never by position. The validator reads this column by its header name, so
|
|
@@ -580,6 +581,7 @@ round verifies them (`review.md` §Receiving) — and 3 is the ceiling, past whi
|
|
|
580
581
|
residue goes to the user rather than into a fourth round. `verdict` carries the
|
|
581
582
|
round-1 verdict and the final one when they differ (`FAIL → PASS`): collapsing a
|
|
582
583
|
first-round FAIL into a bare `PASS` erases the evidence this log exists to keep.
|
|
584
|
+
A restating delta ruled not due (`review.md` §When a review is due) is still a row: `tier` `closure`, `model` `none (not due)`, findings and rounds `0`, verdict `NOT DUE: <the kinds; the check that ran and its result>`; `benefit` counts it apart.
|
|
583
585
|
Concurrent reviews: `init` writes a `.gitattributes` stanza giving this file
|
|
584
586
|
`merge=union` — a **built-in** driver (no per-clone `git config`, unlike
|
|
585
587
|
`merge=ours`, which silently does nothing until every clone configures it).
|