@antoneeo/agentic-sdlc-skill 1.31.0 → 1.33.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 +133 -24
- package/README.md +32 -2
- package/gemini-extension.json +6 -6
- package/package.json +51 -50
- package/scripts/lib.js +105 -0
- package/scripts/postinstall.js +13 -1
- package/skills/agentic-sdlc-skill/ENFORCEMENT.md +50 -1
- package/skills/agentic-sdlc-skill/SKILL.md +283 -354
- package/skills/agentic-sdlc-skill/dispatch.md +39 -1
- package/skills/agentic-sdlc-skill/guides.md +16 -12
- package/skills/agentic-sdlc-skill/hybrid.md +106 -0
- package/skills/agentic-sdlc-skill/review.md +80 -3
- package/skills/agentic-sdlc-skill/scripts/sdlc_check.py +11 -2
- package/skills/agentic-sdlc-skill/scripts/sdlc_core.py +293 -4
- package/skills/agentic-sdlc-skill/templates.md +15 -8
package/CHANGELOG.md
CHANGED
|
@@ -2,30 +2,139 @@
|
|
|
2
2
|
|
|
3
3
|
Tutte le modifiche significative a questa skill saranno documentate in questo file.
|
|
4
4
|
|
|
5
|
-
## [1.
|
|
6
|
-
|
|
7
|
-
###
|
|
8
|
-
- **
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
- **
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
5
|
+
## [1.33.0] - 2026-09-12
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **F-048: the capability floor, and what may be delegated at all.** A review
|
|
9
|
+
run below the capability its judgement needs certifies the omission it was
|
|
10
|
+
there to catch. `review.md` now carries a floor — which tier may run which
|
|
11
|
+
role — with the rule that a tier may be lowered only where a **threshold
|
|
12
|
+
signal** scores the cheap answer, and an arbitration for the case where the
|
|
13
|
+
only independent rung sits under it (independence wins, both facts recorded).
|
|
14
|
+
`dispatch.md` gains the family-wide delegation boundary, keyed on whether a
|
|
15
|
+
pass's output is falsifiable and on its read/report ratio: a task whose brief
|
|
16
|
+
cannot be expressed as POINTERS is not delegable. `REVIEW_LOG` gains a
|
|
17
|
+
`model` column — tiers are client-relative capability levels, never provider
|
|
18
|
+
names. External evidence: cascade routing pays only where a threshold signal
|
|
19
|
+
exists, and multi-agent execution costs 3-15x the tokens and buys context
|
|
20
|
+
isolation rather than savings.
|
|
21
|
+
- **F-049: the floor reaches the AUTHOR, not only the gates.** A session's
|
|
22
|
+
floor is the highest floor among the roles it performs itself, and authoring
|
|
23
|
+
a governed artifact is a deep-floor role — its output is judgement and
|
|
24
|
+
nothing downstream scores it. Fails open by construction: a session that
|
|
25
|
+
cannot determine its own tier owes nothing. The reliably working half is
|
|
26
|
+
addressed to the user, in each package's README.
|
|
27
|
+
- **F-050: `benefit` — what the process caught, beside what it costs to read.**
|
|
28
|
+
The product's central claim becomes computable instead of asserted. It always
|
|
29
|
+
exits 0 and carries no verdict: a measurement that can fail a build becomes a
|
|
30
|
+
target, and a targeted measurement stops measuring.
|
|
31
|
+
- **F-051: the Hybrid seam leaves the mandatory read.** The devPNT ownership
|
|
32
|
+
matrix, triage equivalence, feature-state mapping and shadow discipline move
|
|
33
|
+
to a triggered `hybrid.md`; `SKILL.md` keeps a pointer carrying the trigger
|
|
34
|
+
and the consequence. Conservation is guarded by a digest stamped in the moved
|
|
35
|
+
file and computed from the PRE-MOVE source.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
- **F-053: nine defects a review on a DIFFERENT model found after six units
|
|
39
|
+
shipped.** Each of those six was reviewed in isolation, and each by the same
|
|
40
|
+
model family as its author; six rows reading "all findings folded" are one
|
|
41
|
+
loop, not two eyes. The scoped re-review `review.md` mandates had never been
|
|
42
|
+
run for seven unreleased rows — it has been now, late, and each row states
|
|
43
|
+
both verdicts WITH its limitation, because 35 findings across six of them
|
|
44
|
+
have no surviving per-finding record and no late round can certify them.
|
|
45
|
+
`benefit` printed "the share above is a floor, not a ceiling", which is
|
|
46
|
+
backwards — folding the post-implementation rows LOWERS the design share —
|
|
47
|
+
and excluded 46 of 117 rows in silence; it now prints a computed interval,
|
|
48
|
+
names the rows that state no count, and prints the read-cost TOTAL with the
|
|
49
|
+
support files itemised, because printing only the two terms let the one that
|
|
50
|
+
FELL be quoted while the one that GREW stayed lumped.
|
|
51
|
+
- **The mechanism behind five of those units' probes, recorded as an ADR.** Ten
|
|
52
|
+
assertions across six units were satisfiable by a LITERAL, because the probe
|
|
53
|
+
looked for a SHAPE in the output instead of recomputing the VALUE and
|
|
54
|
+
comparing. Every probe over a computed output now recomputes and compares and
|
|
55
|
+
carries a positive control on synthetic data; every probe over prose is
|
|
56
|
+
labelled a wording anchor.
|
|
57
|
+
|
|
58
|
+
### Read cost
|
|
59
|
+
- `SKILL.md` **-7.9%** (49,413 -> 45,518 B) for a Standalone session. A Hybrid
|
|
60
|
+
L3 session reads **+5.6%** (`SKILL.md` + `hybrid.md`), and the package's
|
|
61
|
+
support files grow **+10.8%**: the cost did not fall so much as MOVE out of
|
|
62
|
+
the file the report prints. Stated here because the Vision's ceremony clause
|
|
63
|
+
counts relocated cost.
|
|
64
|
+
|
|
65
|
+
## [1.32.1] - 2026-09-06
|
|
66
|
+
|
|
67
|
+
### Fixed
|
|
68
|
+
- **F-046 shipped a hook that wired nowhere.** `wireRemindHookInto` used the
|
|
69
|
+
ORIENT hook's opt-out marker (`orient-hook-wired`) as its own. That file is
|
|
70
|
+
present on every machine that ever installed the skill, so the installer read
|
|
71
|
+
it as "the user opted out of the per-turn reminder" and never wrote the hook —
|
|
72
|
+
for everyone. Two smaller faults in the same function: the marker was checked
|
|
73
|
+
BEFORE testing whether the hook was already present, and no marker was ever
|
|
74
|
+
written after a successful wire, so the real opt-out could never arm. The hook
|
|
75
|
+
now has its own `remind-hook-wired` marker, checked after the presence test and
|
|
76
|
+
written only on success. Regression pinned in `scripts/test_clients.js` (red
|
|
77
|
+
against 1.32.0: an orient-marked machine got no hook).
|
|
78
|
+
|
|
79
|
+
## [1.32.0] - 2026-09-06
|
|
80
|
+
|
|
81
|
+
### Added
|
|
82
|
+
- **F-046: the protocol reaches every turn (`remind`, UserPromptSubmit, wired by
|
|
83
|
+
default).** `orient` fires once at session start and decays; a session that
|
|
84
|
+
never loads the skill never had the protocol at all. Measured 2026-09-06: a
|
|
85
|
+
release ran against a `GUIDE_release.md` the session never consulted, because
|
|
86
|
+
`SKILL.md` -- where the duty is written -- had not been read. `remind` prints
|
|
87
|
+
ONE constant line at every prompt, and its first duty is that one: decide
|
|
88
|
+
whether the skill governs the work in front of you and, if it does, LOAD it
|
|
89
|
+
once. The carrier is kb's F-041 item B, LIFTED into the shared spine rather
|
|
90
|
+
than duplicated, so all three lenses share one machine; each lens declares its
|
|
91
|
+
own line in `set_profile(remind_line=...)`. Installing the package wires it
|
|
92
|
+
machine-wide on Claude Code alongside the orientation hook, never instead of
|
|
93
|
+
it; removing the hook entry is a standing opt-out. Per-turn cost disclosed and
|
|
94
|
+
accepted by the owner (`vision/rulings.md` r19, the "no ceremony ratchet"
|
|
95
|
+
Non-Goal's second door), and bounded to stay flat by a contract the new shared
|
|
96
|
+
`scripts/test_remind.py` guards: constant text, zero reads, one line under 500
|
|
97
|
+
characters, argv ignored whole, always exit 0.
|
|
98
|
+
|
|
99
|
+
### Changed
|
|
100
|
+
- **`guides.md` said something false about code guides.** It claimed `stale`
|
|
101
|
+
works unchanged for `source_kind: code` because "the code-excerpt snapshot
|
|
102
|
+
drifts when the code changes". A snapshot is a frozen copy and never drifts:
|
|
103
|
+
freshness is NOT mechanized there, and the duty is the author's twice -- when
|
|
104
|
+
you MODIFY code a comprehension guide describes, and when you merely READ one
|
|
105
|
+
before trusting it. Measured 2026-09-06: the guided module had gained 388
|
|
106
|
+
lines and lost 71 across four commits with `stale` silent.
|
|
107
|
+
|
|
108
|
+
- **The guide question moves to the analysis phase (SKILL.md).** Two lines in the
|
|
109
|
+
ANALYSIS -- does a CURRENT guide cover what I am about to touch, and did
|
|
110
|
+
understanding this force a model of a high-complexity component none covers.
|
|
111
|
+
The Phase-5 Comprehension checkpoint stays the backstop for a signal that only
|
|
112
|
+
became visible later; it is no longer the moment of first asking.
|
|
113
|
+
|
|
114
|
+
## [1.31.0] - 2026-09-05
|
|
115
|
+
|
|
116
|
+
### Changed
|
|
117
|
+
- **Execute-Before-Specify now covers text-about-text (SKILL.md, Phase 3).** A
|
|
118
|
+
deliverable that is itself text -- doctrine, a schema, a prompt, a reviewer
|
|
119
|
+
definition -- is probed the same way as code: replay it against the recorded
|
|
120
|
+
case that motivated it (the incident artifact, the tool-usage transcript, the
|
|
121
|
+
review that missed the defect), red under the old text, green under the new.
|
|
122
|
+
"No probe is possible" is shown, never declared. The exemption an earlier
|
|
123
|
+
proposal would have granted was rejected on evidence: the unit cited as
|
|
124
|
+
unprobeable text was a code unit that modified six production modules and
|
|
125
|
+
shipped four assertion harnesses, while doctrine and prompt changes have been
|
|
126
|
+
measured here by replay (three headless probes of a prompt change; an ad-hoc
|
|
127
|
+
checklist that caught in one round what ten rounds missed). Paid for per this
|
|
128
|
+
skill's own `vision.md` cumulative-ratchet rule: 67 words of illustration and
|
|
129
|
+
rationale deleted from the same paragraph, net -2 words.
|
|
130
|
+
- **Form budget belongs to the first draft (shared spine `review.md`,
|
|
131
|
+
byte-identical x3).** The lean operative form is the FIRST draft's form, not
|
|
132
|
+
the round-3 rescue: the review request states the artifact's line count
|
|
133
|
+
against a budget the author fixed before drafting, and an artifact over budget
|
|
134
|
+
is the reviewer's first finding, before content. The ~1,250 -> ~500 line
|
|
135
|
+
measurement already in the file is its anchor. Spine delta is synced in the
|
|
136
|
+
repo; kb and mkt ship it at their next release.
|
|
137
|
+
|
|
29
138
|
## [1.30.0] - 2026-09-01
|
|
30
139
|
|
|
31
140
|
### Added
|
package/README.md
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
- **devPNT symbiosis**: when devPNT is available, Master Plan, Action Plan, M-VISION, and governed artifacts become the authoritative planning layer, with independent fresh-context reviews of technical artifacts and diffs.
|
|
17
17
|
- **Independent review, twice**: the design is reviewed before it is implemented and the diff before the work is declared done — by somebody other than its author. Three rungs of independence (fresh-context subagent > one-shot run > a declared self-pass, legal only when no higher rung is usable: absent, or permission-gated and declined — a gated rung is asked about, never silently skipped, and the log says which), capped at 3 rounds, one log line per review, and a PASS is invalid on "found nothing" — it must state where each constraint is satisfied.
|
|
18
18
|
- **Question discipline**: a question to the user is legal only when the agent searched first and names the search with its result, and names the decision the answer unblocks. Otherwise it proceeds on a declared assumption — same evidence duty, batched, never a stream of "shall I proceed?".
|
|
19
|
-
- **Installed support files**: Claude, Codex, Gemini, and Google Antigravity receive the full skill folder, including `templates.md`, `architect.md`, `guides.md`, `vision.md`, `tdd.md`, `debugging.md`, `elicitation.md`, `review.md`, `dispatch.md`, `routing.md`, `ENFORCEMENT.md`, and the validator's two files, `scripts/sdlc_check.py` + `scripts/sdlc_core.py`.
|
|
20
|
-
- **Mechanical checks**: optional validator for document structure, generated feature history, stale audit areas, and protected-path gates — `check`, `validate`, `index`, `stale`, `mark`, `gate`, `plan`, `orient`, `migrate`.
|
|
19
|
+
- **Installed support files**: Claude, Codex, Gemini, and Google Antigravity receive the full skill folder, including `templates.md`, `architect.md`, `guides.md`, `vision.md`, `tdd.md`, `debugging.md`, `elicitation.md`, `review.md`, `dispatch.md`, `routing.md`, `hybrid.md`, `ENFORCEMENT.md`, and the validator's two files, `scripts/sdlc_check.py` + `scripts/sdlc_core.py`.
|
|
20
|
+
- **Mechanical checks**: optional validator for document structure, generated feature history, stale audit areas, and protected-path gates — `check`, `validate`, `index`, `stale`, `mark`, `benefit`, `gate`, `plan`, `orient`, `migrate`. `benefit` reports what the review gates have already caught, beside what the doctrine costs to read — it always exits 0 and carries no verdict, because a measurement that can fail a build becomes a target.
|
|
21
21
|
|
|
22
22
|
## Installation
|
|
23
23
|
|
|
@@ -84,6 +84,7 @@ skills/agentic-sdlc-skill/
|
|
|
84
84
|
├── review.md
|
|
85
85
|
├── dispatch.md
|
|
86
86
|
├── routing.md
|
|
87
|
+
├── hybrid.md
|
|
87
88
|
├── ENFORCEMENT.md
|
|
88
89
|
└── scripts/
|
|
89
90
|
├── sdlc_check.py
|
|
@@ -138,3 +139,32 @@ For native Gemini Agent Skills, the npm installer now copies the skill folder in
|
|
|
138
139
|
Created by **Antonio Pinto** ([GitHub](https://github.com/Antoneeo)).
|
|
139
140
|
|
|
140
141
|
MIT (c) 2026 Antonio Pinto.
|
|
142
|
+
|
|
143
|
+
## Which model to run it on
|
|
144
|
+
|
|
145
|
+
The skill names **capability tiers**, never providers — a model name in doctrine
|
|
146
|
+
rots at the next release. The binding is yours to make, and the rule is one line:
|
|
147
|
+
|
|
148
|
+
> **A session's floor is the highest floor among the roles it performs itself.**
|
|
149
|
+
|
|
150
|
+
Authoring a governed artifact — the vision, the analysis, the use cases, the
|
|
151
|
+
threat model — is a **deep-tier** role: its output is judgement, and nothing
|
|
152
|
+
downstream scores it. So a session that will DESIGN wants your strongest model.
|
|
153
|
+
A session that only executes an already-approved plan, or does small maintenance,
|
|
154
|
+
can sit a tier lower. The cheapest tier is the wrong choice for the main session
|
|
155
|
+
whatever the task, because the failure there is not a wrong answer — it is
|
|
156
|
+
**silently not applying the process**: a triage never run, a router verdict
|
|
157
|
+
declared without the lookup, a gate nobody noticed. That failure is invisible to
|
|
158
|
+
every check in here.
|
|
159
|
+
|
|
160
|
+
**The reviewer's tier is not automatically yours.** On some clients a subagent
|
|
161
|
+
inherits the session's model; on others it takes one from its own definition, so
|
|
162
|
+
a strong session can be reviewed by a weak one — and a weak session can buy a
|
|
163
|
+
strong review. Set it deliberately; the
|
|
164
|
+
`model` column in the review log is where the choice becomes visible.
|
|
165
|
+
|
|
166
|
+
**Avoid one combination**: authoring below the floor AND reviewing below the floor
|
|
167
|
+
on the same unit. One disclosed weakness is a disclosed weakness; two is an
|
|
168
|
+
artifact nobody competent ever read. Where your client offers nothing better, the
|
|
169
|
+
review still runs and both facts are recorded — a disclosed worst case beats
|
|
170
|
+
skipping the review.
|
package/gemini-extension.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "agentic-sdlc-skill",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Documentation-First SDLC protocol with triage, Vision governance and optional devPNT integration.",
|
|
5
|
-
"author": "Antonio Pinto (https://github.com/Antoneeo)"
|
|
6
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "agentic-sdlc-skill",
|
|
3
|
+
"version": "1.33.0",
|
|
4
|
+
"description": "Documentation-First SDLC protocol with triage, Vision governance and optional devPNT integration.",
|
|
5
|
+
"author": "Antonio Pinto (https://github.com/Antoneeo)"
|
|
6
|
+
}
|
package/package.json
CHANGED
|
@@ -1,50 +1,51 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@antoneeo/agentic-sdlc-skill",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Documentation-First SDLC protocol for Claude Code, Gemini CLI, Google Antigravity and Codex with risk triage, Vision governance, installed support files and optional devPNT integration.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"claude-code",
|
|
7
|
-
"claude-skill",
|
|
8
|
-
"gemini-cli",
|
|
9
|
-
"skill",
|
|
10
|
-
"sdlc",
|
|
11
|
-
"documentation",
|
|
12
|
-
"ai-agent"
|
|
13
|
-
],
|
|
14
|
-
"author": "Antonio Pinto (https://github.com/Antoneeo)",
|
|
15
|
-
"license": "MIT",
|
|
16
|
-
"publishConfig": {
|
|
17
|
-
"access": "public"
|
|
18
|
-
},
|
|
19
|
-
"bin": {
|
|
20
|
-
"agentic-sdlc-init": "scripts/init.js",
|
|
21
|
-
"agentic-sdlc-install-skill": "scripts/postinstall.js"
|
|
22
|
-
},
|
|
23
|
-
"scripts": {
|
|
24
|
-
"postinstall": "node scripts/postinstall.js",
|
|
25
|
-
"preuninstall": "node scripts/preuninstall.js"
|
|
26
|
-
},
|
|
27
|
-
"files": [
|
|
28
|
-
"skills/agentic-sdlc-skill/SKILL.md",
|
|
29
|
-
"skills/agentic-sdlc-skill/templates.md",
|
|
30
|
-
"skills/agentic-sdlc-skill/architect.md",
|
|
31
|
-
"skills/agentic-sdlc-skill/guides.md",
|
|
32
|
-
"skills/agentic-sdlc-skill/vision.md",
|
|
33
|
-
"skills/agentic-sdlc-skill/tdd.md",
|
|
34
|
-
"skills/agentic-sdlc-skill/debugging.md",
|
|
35
|
-
"skills/agentic-sdlc-skill/elicitation.md",
|
|
36
|
-
"skills/agentic-sdlc-skill/review.md",
|
|
37
|
-
"skills/agentic-sdlc-skill/dispatch.md",
|
|
38
|
-
"skills/agentic-sdlc-skill/
|
|
39
|
-
"skills/agentic-sdlc-skill/
|
|
40
|
-
"skills/agentic-sdlc-skill/
|
|
41
|
-
"skills/agentic-sdlc-skill/scripts/
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"scripts/
|
|
47
|
-
"scripts/
|
|
48
|
-
"scripts/
|
|
49
|
-
|
|
50
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@antoneeo/agentic-sdlc-skill",
|
|
3
|
+
"version": "1.33.0",
|
|
4
|
+
"description": "Documentation-First SDLC protocol for Claude Code, Gemini CLI, Google Antigravity and Codex with risk triage, Vision governance, installed support files and optional devPNT integration.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude-code",
|
|
7
|
+
"claude-skill",
|
|
8
|
+
"gemini-cli",
|
|
9
|
+
"skill",
|
|
10
|
+
"sdlc",
|
|
11
|
+
"documentation",
|
|
12
|
+
"ai-agent"
|
|
13
|
+
],
|
|
14
|
+
"author": "Antonio Pinto (https://github.com/Antoneeo)",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"agentic-sdlc-init": "scripts/init.js",
|
|
21
|
+
"agentic-sdlc-install-skill": "scripts/postinstall.js"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"postinstall": "node scripts/postinstall.js",
|
|
25
|
+
"preuninstall": "node scripts/preuninstall.js"
|
|
26
|
+
},
|
|
27
|
+
"files": [
|
|
28
|
+
"skills/agentic-sdlc-skill/SKILL.md",
|
|
29
|
+
"skills/agentic-sdlc-skill/templates.md",
|
|
30
|
+
"skills/agentic-sdlc-skill/architect.md",
|
|
31
|
+
"skills/agentic-sdlc-skill/guides.md",
|
|
32
|
+
"skills/agentic-sdlc-skill/vision.md",
|
|
33
|
+
"skills/agentic-sdlc-skill/tdd.md",
|
|
34
|
+
"skills/agentic-sdlc-skill/debugging.md",
|
|
35
|
+
"skills/agentic-sdlc-skill/elicitation.md",
|
|
36
|
+
"skills/agentic-sdlc-skill/review.md",
|
|
37
|
+
"skills/agentic-sdlc-skill/dispatch.md",
|
|
38
|
+
"skills/agentic-sdlc-skill/hybrid.md",
|
|
39
|
+
"skills/agentic-sdlc-skill/routing.md",
|
|
40
|
+
"skills/agentic-sdlc-skill/ENFORCEMENT.md",
|
|
41
|
+
"skills/agentic-sdlc-skill/scripts/sdlc_check.py",
|
|
42
|
+
"skills/agentic-sdlc-skill/scripts/sdlc_core.py",
|
|
43
|
+
"gemini-extension.json",
|
|
44
|
+
"README.md",
|
|
45
|
+
"CHANGELOG.md",
|
|
46
|
+
"scripts/lib.js",
|
|
47
|
+
"scripts/init.js",
|
|
48
|
+
"scripts/postinstall.js",
|
|
49
|
+
"scripts/preuninstall.js"
|
|
50
|
+
]
|
|
51
|
+
}
|
package/scripts/lib.js
CHANGED
|
@@ -639,6 +639,105 @@ function removeGlobalOrientHooks(removedRoots) {
|
|
|
639
639
|
return removedFrom;
|
|
640
640
|
}
|
|
641
641
|
|
|
642
|
+
// --- Per-turn reminder hook (F-046) ----------------------------------------
|
|
643
|
+
// `orient` fires once and decays; a session that never loads the skill never
|
|
644
|
+
// had the protocol at all. This hook re-arms one constant line every prompt.
|
|
645
|
+
// It is wired ALONGSIDE the orient hook and never instead of it, and it is its
|
|
646
|
+
// own function because `wireOrientHook` returns early when the session hook is
|
|
647
|
+
// already there -- which is the state of every existing installation.
|
|
648
|
+
// Owner-accepted per-turn cost: `ai_docs/vision/rulings.md` r19.
|
|
649
|
+
|
|
650
|
+
const REMIND_HOOK_TIMEOUT = 5;
|
|
651
|
+
|
|
652
|
+
function remindHookCommand(python, validator) {
|
|
653
|
+
return python + ' "' + validator + '" remind';
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
function findRemindHook(settings) {
|
|
657
|
+
const groups = settings && settings.hooks && settings.hooks.UserPromptSubmit;
|
|
658
|
+
if (!Array.isArray(groups)) return null;
|
|
659
|
+
for (const group of groups) {
|
|
660
|
+
if (!group || typeof group !== 'object') continue;
|
|
661
|
+
const inner = Array.isArray(group.hooks) ? group.hooks : [group];
|
|
662
|
+
for (const h of inner) {
|
|
663
|
+
const cmd = h && typeof h.command === 'string' ? h.command : '';
|
|
664
|
+
if (ORIENT_ENTRY_POINTS.some((n) => cmd.includes(n)) && / remind(\s|$)/.test(cmd)) {
|
|
665
|
+
return cmd;
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
return null;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// Writes the hook into `target` (an already-chosen settings file) unless it is
|
|
673
|
+
// there or the user opted out. Returns a code, never throws: an installer must
|
|
674
|
+
// not die on someone's settings file.
|
|
675
|
+
function remindMarkerPath() {
|
|
676
|
+
const root = process.env.AGENTIC_SDLC_KB_ROOT
|
|
677
|
+
|| path.join(os.homedir(), '.agentic-sdlc');
|
|
678
|
+
return path.join(root, 'remind-hook-wired');
|
|
679
|
+
}
|
|
680
|
+
function remindMarkerTargets() {
|
|
681
|
+
try {
|
|
682
|
+
return fs.readFileSync(remindMarkerPath(), 'utf8')
|
|
683
|
+
.split(/\r?\n/).map((x) => x.trim()).filter(Boolean);
|
|
684
|
+
} catch (e) {
|
|
685
|
+
return [];
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
function remindMarkerHas(target) {
|
|
689
|
+
return remindMarkerTargets().some((t) => pathsEqual(t, target));
|
|
690
|
+
}
|
|
691
|
+
function remindMarkerAdd(target) {
|
|
692
|
+
try {
|
|
693
|
+
if (remindMarkerHas(target)) return;
|
|
694
|
+
fs.mkdirSync(path.dirname(remindMarkerPath()), { recursive: true });
|
|
695
|
+
fs.appendFileSync(remindMarkerPath(), target + String.fromCharCode(10), 'utf8');
|
|
696
|
+
} catch (e) { /* fail-open */ }
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
function wireRemindHookInto(target, python, validator) {
|
|
700
|
+
if (!python) return { code: 'no-python' };
|
|
701
|
+
if (!validator || ORIENT_UNSAFE_IN_PATH.test(validator)) return { code: 'unsafe-path', validator };
|
|
702
|
+
const state = orientSettingsState(target);
|
|
703
|
+
if (!state.ok) return { code: 'malformed', target, why: state.why };
|
|
704
|
+
const settings0 = state.settings;
|
|
705
|
+
// Order matters, and the first version had it wrong too: the hook being
|
|
706
|
+
// PRESENT is `already`, and only its ABSENCE plus our marker means the user
|
|
707
|
+
// removed it -- a standing opt-out. Marker-first would refuse to re-check a
|
|
708
|
+
// hook someone still has.
|
|
709
|
+
const present = findRemindHook(settings0);
|
|
710
|
+
if (present) return { code: 'already', target, command: present };
|
|
711
|
+
if (remindMarkerHas(target)) return { code: 'opted-out', target };
|
|
712
|
+
const settings = settings0;
|
|
713
|
+
const existing = null;
|
|
714
|
+
if (existing) return { code: 'already', target, command: existing };
|
|
715
|
+
const command = remindHookCommand(python, validator);
|
|
716
|
+
if (!settings.hooks) settings.hooks = {};
|
|
717
|
+
if (!Array.isArray(settings.hooks.UserPromptSubmit)) settings.hooks.UserPromptSubmit = [];
|
|
718
|
+
settings.hooks.UserPromptSubmit.push({
|
|
719
|
+
hooks: [{ type: 'command', command, timeout: REMIND_HOOK_TIMEOUT }],
|
|
720
|
+
});
|
|
721
|
+
try {
|
|
722
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
723
|
+
fs.writeFileSync(target, JSON.stringify(settings, null, 2) + String.fromCharCode(10), 'utf8');
|
|
724
|
+
} catch (e) {
|
|
725
|
+
return { code: 'write-failed', target, command, error: e.message };
|
|
726
|
+
}
|
|
727
|
+
remindMarkerAdd(target);
|
|
728
|
+
return { code: 'wired', target, command };
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
|
|
732
|
+
// The machine-global twin of wireGlobalOrientHook, same target and validator.
|
|
733
|
+
function wireGlobalRemindHook(options) {
|
|
734
|
+
const client = options.client;
|
|
735
|
+
const validator = path.join(skillTarget(client), 'scripts', ORIENT_ENTRY_POINT);
|
|
736
|
+
if (!fs.existsSync(validator)) return { code: 'no-validator', validator };
|
|
737
|
+
return wireRemindHookInto(path.join(client.home, 'settings.json'), options.python, validator);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
|
|
642
741
|
module.exports = {
|
|
643
742
|
PACKAGE_ROOT,
|
|
644
743
|
SKILL_SOURCE,
|
|
@@ -649,6 +748,12 @@ module.exports = {
|
|
|
649
748
|
clientDetected,
|
|
650
749
|
skillTarget,
|
|
651
750
|
wireOrientHook,
|
|
751
|
+
wireRemindHookInto,
|
|
752
|
+
wireGlobalRemindHook,
|
|
753
|
+
remindMarkerHas,
|
|
754
|
+
remindMarkerAdd,
|
|
755
|
+
remindHookCommand,
|
|
756
|
+
findRemindHook,
|
|
652
757
|
wireGlobalOrientHook,
|
|
653
758
|
removeGlobalOrientHooks,
|
|
654
759
|
detectPython,
|
package/scripts/postinstall.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const fs = require('fs');
|
|
4
4
|
const {
|
|
5
5
|
SKILL_SOURCE, CLIENTS, clientDetected, skillTarget, copyRecursive,
|
|
6
|
-
wireGlobalOrientHook, detectPython,
|
|
6
|
+
wireGlobalOrientHook, wireGlobalRemindHook, detectPython,
|
|
7
7
|
} = require('./lib');
|
|
8
8
|
|
|
9
9
|
function installSkill(client) {
|
|
@@ -39,6 +39,18 @@ for (const client of CLIENTS) {
|
|
|
39
39
|
// marker remembers. A convenience must never fail an npm install: wrapped.
|
|
40
40
|
if (client.key === 'claude' && installed) {
|
|
41
41
|
try {
|
|
42
|
+
// F-046: the per-turn reminder, wired alongside and never instead of
|
|
43
|
+
// the session hook. `orient` decays; this one re-arms one constant line
|
|
44
|
+
// every prompt, and its first duty is the one that was missing -- decide
|
|
45
|
+
// whether the skill governs the work and, if so, load it once, because
|
|
46
|
+
// an unread protocol cannot be applied. Owner-accepted per-turn cost:
|
|
47
|
+
// ai_docs/vision/rulings.md r19.
|
|
48
|
+
const rr = wireGlobalRemindHook({ client, python: detectPython() });
|
|
49
|
+
if (rr.code === 'wired') {
|
|
50
|
+
console.log('🔗 Per-turn protocol reminder wired for every project on this machine');
|
|
51
|
+
console.log(` (${rr.target}). One constant line per prompt; remove that hook`);
|
|
52
|
+
console.log(' entry to opt out — it will not be re-added.');
|
|
53
|
+
}
|
|
42
54
|
const r = wireGlobalOrientHook({ client, python: detectPython() });
|
|
43
55
|
if (r.code === 'wired') {
|
|
44
56
|
console.log('🔗 Session orientation wired for every project on this machine');
|
|
@@ -57,7 +57,7 @@ Semantics: exit code 2 + message on stderr ⇒ the write is blocked and the mess
|
|
|
57
57
|
- The paths in `--protected` are prefixes relative to the project root, separated by `;`.
|
|
58
58
|
- `ai_docs/`, `tests/` and `test/` are always excluded from blocking.
|
|
59
59
|
- The hook assumes the working directory is the project root (standard behavior of Claude Code hooks).
|
|
60
|
-
- **Hybrid/devPNT projects**: add `--hybrid` to the gate command. Governed designs live in the devPNT DB, so the gate also unlocks when an approved E-TDD shadow (`ai_docs/solutions/SHADOW_*tdd*.md`, exported before implementation — see
|
|
60
|
+
- **Hybrid/devPNT projects**: add `--hybrid` to the gate command. Governed designs live in the devPNT DB, so the gate also unlocks when an approved E-TDD shadow (`ai_docs/solutions/SHADOW_*tdd*.md`, exported before implementation — see `hybrid.md` §Shadow discipline) is present. Without the flag the gate would block legitimate governed work. The flag is deliberately explicit: never auto-detected.
|
|
61
61
|
|
|
62
62
|
## 4. SessionStart hook (orientation, recommended default)
|
|
63
63
|
|
|
@@ -157,6 +157,46 @@ Gemini CLI — wire the same command into its startup-hook mechanism if present;
|
|
|
157
157
|
- **Hybrid/devPNT projects**: add `--hybrid` — the hook then appends a one-line pointer to run `devpnt_mcp_get_bootstrap` for the Master Plan / Knowledge Layer and does not replicate them; the filesystem orientation (router + handoff + README) still emits.
|
|
158
158
|
- Like the CI gate (§2), if you copied the validator into the repo, the hook references that copy — keep both files current when you update the skill.
|
|
159
159
|
|
|
160
|
+
### Per-turn reminder: `remind` (UserPromptSubmit -- wired by default)
|
|
161
|
+
|
|
162
|
+
`orient` fires once, at session start; a long session drifts after it, and a session
|
|
163
|
+
that never loads the skill never had the protocol at all. Measured (F-046, 2026-09-06):
|
|
164
|
+
a release ran against a `GUIDE_release.md` the session never consulted, because
|
|
165
|
+
`SKILL.md` -- where the duty is written -- had not been read. `sdlc_check.py remind` prints
|
|
166
|
+
ONE constant line at every prompt, and its first duty is that one: decide whether the
|
|
167
|
+
skill governs the work in front of you and, if it does, load it once.
|
|
168
|
+
|
|
169
|
+
Cost: 478 characters, ~80 tokens per prompt, paid on every turn including
|
|
170
|
+
trivial ones. That is admissible only because the owner accepted it explicitly
|
|
171
|
+
(`ai_docs/vision/rulings.md` r19, the "no ceremony ratchet" Non-Goal's second door) --
|
|
172
|
+
and the acceptance was for a FLAT cost. Hence the contract, guarded by
|
|
173
|
+
`scripts/test_remind.py`: the line is **constant and reads nothing** (so nothing repo-
|
|
174
|
+
or session-controlled rides into the agent's context through it, and the cost cannot
|
|
175
|
+
grow with the session), it is **one line under 500 characters**, and it **can never
|
|
176
|
+
break a prompt** (argv ignored whole, always exit 0). A trivial turn pays a yes/no
|
|
177
|
+
judgement, never a load.
|
|
178
|
+
|
|
179
|
+
Installing the package wires it machine-wide on Claude Code, alongside the orientation
|
|
180
|
+
hook and never instead of it; **removing that hook entry is a standing opt-out.** To
|
|
181
|
+
wire it by hand:
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"hooks": {
|
|
186
|
+
"UserPromptSubmit": [
|
|
187
|
+
{
|
|
188
|
+
"hooks": [
|
|
189
|
+
{
|
|
190
|
+
"type": "command",
|
|
191
|
+
"command": "python \"C:\Users\<user>\.claude\skills\agentic-sdlc\scripts\sdlc_check.py\" remind"
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
]
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
160
200
|
## 5. Skill eval battery (release gate)
|
|
161
201
|
|
|
162
202
|
**Skill development only.** `test_*.py` and `evals/` are deliberately absent from the npm `files` allowlist — they never reach an installed consumer, so this section applies to whoever builds the skill, not to a project that uses it. (Consumers get `sdlc_check.py` + `sdlc_core.py`; §1–§4 are theirs.)
|
|
@@ -176,3 +216,12 @@ It aggregates the test files (`test_plan.py` + `test_session_start.py` + `test_s
|
|
|
176
216
|
**Optional CI** (same shape as §2, not mandatory): add a `run:` step invoking the `unittest discover` command above.
|
|
177
217
|
|
|
178
218
|
**T10 note:** if you copied the validator (both files) and the `test_*.py` battery into the repo for CI, that copy is authoritative — keep it current when you update the skill.
|
|
219
|
+
|
|
220
|
+
## `benefit` is a report, never a CI gate
|
|
221
|
+
|
|
222
|
+
`sdlc_check.py benefit` reports what the review gates caught and what the
|
|
223
|
+
doctrine costs to read. It always exits 0 and emits no warning: **never wire
|
|
224
|
+
it into CI**. It is the criterion by which future units are judged, and a
|
|
225
|
+
measurement that can fail a build becomes a target -- a targeted measurement
|
|
226
|
+
stops measuring. Run it when deciding whether a proposed rule is worth its
|
|
227
|
+
ceremony, not on every push.
|