@antoneeo/agentic-sdlc-skill 1.20.2 → 1.21.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 CHANGED
@@ -2,6 +2,259 @@
2
2
 
3
3
  Tutte le modifiche significative a questa skill saranno documentate in questo file.
4
4
 
5
+ ## [1.21.0 / kb 1.4.0 / mkt 0.4.0] - 2026-08-03
6
+
7
+ F-028 — several people on one project. `templates.md` had claimed the workstream
8
+ registry was "Parallel-safe by construction" since F-019, and nothing had ever exercised
9
+ it. Two workstreams opened from one base conflict **twice in one file**: on the row
10
+ insert, and on the file-global `Date:` header. Row-level ownership cannot save a file
11
+ that has a file-level field.
12
+
13
+ ### Changed
14
+ - **`audit/handoff.md` is now GENERATED** from one `HANDOFF_[unit].md` per open
15
+ workstream, whose frontmatter IS the row. Two writers on two workstreams touch two
16
+ different files, and the `Date:` header is derived — from the newest `updated:` VALUE
17
+ in the sources, never a filesystem timestamp (git does not preserve mtimes, and an
18
+ mtime-derived header would make the file regenerate differently in every fresh clone).
19
+ - **`HANDOFF_[unit].md` is now written for every OPEN workstream**, with or without
20
+ volatile state — no file, no row. It still carries the resume logistics, and deleting
21
+ it at closure *is* what removes the row. The DRY boundary against the ANALYSIS Diary
22
+ is restated in the template, because what used to keep narrative out of that file was
23
+ its rarity, and the rarity is gone.
24
+ - Project-wide notes move to their own source, `audit/project_notes.md`, so generating
25
+ the registry cannot destroy notes that belong to no workstream.
26
+
27
+ ### Added
28
+ - **`validate` errors when the registry disagrees with its sources** — which is what
29
+ turns a merge resolved carelessly from permanent into loud. Resolution is mechanical:
30
+ re-run `index`. The generated view can still conflict; the authored truth does not.
31
+ - **`index` refuses to write while anything in the file is unaccounted for**, and names
32
+ it. Converting one row at a time is the state that loses the others, so conversion is
33
+ per project. A project with no sources is untouched and sees no new finding.
34
+ - **`init` writes a `.gitattributes` stanza** giving the append-only review log
35
+ `merge=union` — a **built-in** driver, unlike `merge=ours`, which silently does
36
+ nothing until every clone runs `git config` and leaves the file wrong even then.
37
+ Create-only; a user's own `.gitattributes` is never clobbered.
38
+ - `scripts/test_merge_safety.py` (shared, ×3): the experiment that found the defect,
39
+ kept as a regression test — two workstreams from one base, merged, with the assertion
40
+ that only the generated view may conflict and that regenerating loses no state. Plus
41
+ the mixed-state, fresh-mtime, ordering, cap and duplicate-id guards, each
42
+ mutation-verified.
43
+ - A warning when two files claim the same workstream: the collision this design does
44
+ **not** fix (two people opening the same work under two names) must not pass as two
45
+ ordinary rows.
46
+
47
+ The mechanism is files and a generator: **it works with no VCS at all.** The
48
+ `.gitattributes` stanza is defence in depth — without it the outcome is today's, one
49
+ conflict resolved by hand, never a lost row.
50
+
51
+ ### Upgrading
52
+ Nothing happens until you convert: with no `HANDOFF_*.md` sources, `index` and
53
+ `validate` behave exactly as before. When you convert, convert the whole registry at
54
+ once — `index` will tell you what is still unaccounted for.
55
+
56
+ ## [kb 1.3.0] - 2026-08-03
57
+
58
+ F-031 — from the field: *"the ingestion agent takes shortcuts, and a lot of information
59
+ is lost. The graph works only if all of a file's information is poured into it."* An
60
+ agent handed a 200-page manual emitted a few dozen claims and reported done. Nothing it
61
+ did broke a rule — and that is the finding. `distillation.md` carried a floor ("the
62
+ extractor invents nothing") and no target, so an agent optimizing against it stops the
63
+ moment nothing it wrote is false. **Nothing the field agent emitted was wrong.** Third
64
+ appearance of one class: a rule that describes a good output and never says which
65
+ outputs must exist.
66
+
67
+ ### Added
68
+ - **A north star at the top of `distillation.md`**, above the rules rather than beside
69
+ them: *not one assertion the source makes may be lost, and not one it does not make
70
+ may appear.* One sentence, deliberately — two rules a paragraph apart get optimized
71
+ whichever was read last. The unit is the **assertion**, not the byte: layout and page
72
+ furniture are not assertions, exhaustive means **read** and never *a row per page*.
73
+ - **`extracted_through:`** on the artifact's own sidecar (`p=<n>`, `L<n>`, `complete`) —
74
+ required once any claim cites it. It is what makes "I am finished" falsifiable, and it
75
+ makes the rows and the field check each other: claims with no coverage recorded error;
76
+ a claim addressing past the declared coverage, or coverage past the end of the stored
77
+ bytes, is a contradiction and errors; coverage short of the end warns, because partial
78
+ work is legal mid-ingestion. An artifact nobody has extracted from owes nothing.
79
+ - **Bounded reading windows** — 30 pages by default, *the plan states the window used*
80
+ (a hard number baked into doctrine ages badly across models and page densities). One
81
+ plan task per window: the existing `PLAN_[topic].md` ledger is the register an
82
+ ingestion resumes from across sessions, so **no second register was built** — one
83
+ would have been the work board this method refuses.
84
+ - **A coverage cell in `corpus/INDEX.md`**, printed for **every** artifact including the
85
+ finished ones. A list of only what is behind is the dashboard the Vision rejects, and
86
+ a test fails the suite if the report ever becomes one.
87
+ - Cold-run scenario `long_source_is_exhausted_not_sampled.md`: sampling a long source and
88
+ reporting it ingested is the FAIL — and so is manufacturing a row per page.
89
+
90
+ The limit is stated wherever the field is written, as with `original_sha256`: **nothing
91
+ proves a page was read.** A field advanced without extracting is invisible to any
92
+ checker, precisely because a page that asserts nothing legitimately yields no rows — that
93
+ direction belongs to the ingestion review. What changed is that the shortcut must now be
94
+ written down to pass, and a written claim can be reopened by anyone who cares to.
95
+
96
+ ### Upgrading an existing corpus
97
+ `check` will error on every `corpus/given/` artifact that has claims and no
98
+ `extracted_through:`. That is the migration, and it is the point: state how far each
99
+ source was actually read (`complete` if it was finished). The message names the artifact,
100
+ the first row citing it, and the three accepted forms. `corpus/INDEX.md` gains the
101
+ coverage cell, so run `sdlc_check.py index` once — until then `validate` reports it
102
+ out of alignment, as it does for any generated index.
103
+
104
+ ## [kb 1.2.0] - 2026-08-03
105
+
106
+ F-030 — knowledge built in one project could not leave it. A practitioner who grounded
107
+ 82 claims against a vendor's manuals started the next project with nothing and paid the
108
+ whole ingestion again from the same sources. The Core Problem this methodology exists
109
+ against is that understanding evaporates; it was evaporating at the **project boundary**.
110
+
111
+ ### Added
112
+ - **`export --out <dir>`** bundles a subgraph together with **the bytes its claims
113
+ cite** — a closure, not a selection. A claim whose source cannot be reopened is model
114
+ knowledge arriving by another route, so the artifacts, sidecars and extractions travel
115
+ with it. The closure also pulls in the other half of any `CONTESTED` set, because the
116
+ symmetry check refuses a set that lost members — and says which topics it added, never
117
+ silently.
118
+ - **`import <dir>`** merges a bundle **additively**: never overwrites a node, never
119
+ deletes, and computes the whole plan before writing a byte (an import that half-applies
120
+ leaves a tree whose checks fail and whose owner cannot tell what landed). Refuses on a
121
+ path escaping the docs root, an artifact whose name matches an existing one with
122
+ different bytes, a directory carrying no `MANIFEST.md`, and a broken conflict set.
123
+ Placing an incoming concept stays the placement pass's job (`taxonomy.md`) — the import
124
+ reports the skipped node and decides nothing.
125
+ - **`prov: IMPORTED`** (owner ruling, 2026-08-03). Knowledge crosses a project boundary;
126
+ authority does not. A ruling from another project keeps its text, span and original
127
+ `basis:` verbatim, must declare `imported_from:`, and **cannot supersede a local row**
128
+ — the validator errors on it. Re-ratification is one honest act: your own note, your
129
+ own basis, `prov: RULING`. Relabelling it `DERIVED` was rejected because the row would
130
+ then lie about where it came from.
131
+ - **`portability.md`**, the doctrine the two commands cite.
132
+
133
+ The feature is small because of one property it did not have to build: `kb_claim_id`
134
+ hashes `path#locator#qty` with the **text excluded**, so the same artifact cited at the
135
+ same span mints the same id in every project. Cross-project de-duplication is therefore
136
+ mechanical rather than a judgement call, and importing the same bundle twice is a
137
+ provable no-op.
138
+
139
+ ## [kb 1.1.1] - 2026-08-03
140
+
141
+ Three inconsistencies the same field practitioner found by reading 1.1.0 against
142
+ their own corpus — all of the class 1.1.0 exists to remove: the doctrine and the
143
+ machinery disagreeing, where an agent reads one and the checker obeys the other.
144
+
145
+ ### Fixed
146
+ - **`SKILL.md` never named `anchor`.** The command shipped working and listed in
147
+ `--help`, while the support-file line still said "the knowledge overlay: `graph`,
148
+ `corpus`, `claim-id`" — so an agent reading only the doctrine never learned it
149
+ exists, which is how the practitioner found it (from the prose, by accident). New
150
+ kb invariant derives the expected list from `INTERCEPTED` and fails when SKILL.md
151
+ omits any of it; deriving is the point, a second hand-maintained list would be the
152
+ same defect again.
153
+ - **Two rules gave opposite outcomes on a binary corpus.** The Write Triggers row for
154
+ `corpus/given/*` still read "verbatim copy … non-text originals **also** get their
155
+ stored canonical extraction", contradicting the extraction-as-artifact rule added to
156
+ `distillation.md` §1 in 1.1.0. The row now states both forms and names §1 as the
157
+ owner of the rule.
158
+ - **`anchor` only worked from inside the docs root**, an asymmetry with `graph`,
159
+ `corpus` and `check`, which take `--root`. Those scan a tree and this one takes a
160
+ path, so the fix is to make the path resolve rather than to document where to stand:
161
+ a path that does not resolve from the current directory is retried under the docs
162
+ root, which means it can be given exactly as a claim's `source` cell carries it.
163
+
164
+ ## [kb 1.1.0] - 2026-08-03
165
+
166
+ Scoped to `@antoneeo/kb-agentic-skill`. `agentic-sdlc-skill` (1.20.3) and
167
+ `mkt-agentic-sdlc` (0.3.1) are unchanged in what they ship: the shared invariant
168
+ added here lives in `test_skill_invariants.py`, which no distribution packages.
169
+
170
+ F-029 — six defects from the first full field application of `kb-agentic` by a
171
+ practitioner other than its author (233 MB of manuals, 51 corpus artifacts, 22 topic
172
+ nodes, 82 offset-verified claims). **None was an adherence failure**: in every one the
173
+ agent did what it was told and was wrong anyway, which makes them agent-UX defects.
174
+ Analysis: `ai_docs/solutions/ANALYSIS_kb_field_report.md`.
175
+
176
+ ### Fixed
177
+ - **kb's triage levels were undecidable.** L1 and L2 carried the *identical* bound
178
+ ("at most 1-2 files"), so no request could be classified L2 and anything touching
179
+ three files fell to L3 by "when in doubt, go higher". Root cause: kb never performed
180
+ the restatement the Vision requires of every sibling — the file counts were the code
181
+ lens's units, and they contradicted the escalation triggers two lines below them.
182
+ Restated in knowledge units by owner ruling (2026-08-02): one claim row → propagation
183
+ of an already-settled fact → a new knowledge unit. The one limit: propagation that
184
+ changes what a claim *asserts* is not propagation. New shared invariant asserts no two
185
+ graded levels state the same criteria, lens-agnostically (`L1..L3` here, `E1..E3` in
186
+ marketing) — mutation-tested RED before the fix.
187
+ - **The claim model recorded powers and skipped gates**, making every ledger
188
+ systematically optimistic on a corpus whose purpose is to deflate over-promising. A
189
+ query returned three verified rows saying "yes, supported" while omitting that the
190
+ feature ships disabled and needs a second construct — true, and a plan that fails on
191
+ site. `distillation.md` §3 now requires the gates alongside the powers, with the guard
192
+ that keeps it from becoming fabrication: the rule is *ask*, never *produce*.
193
+ - **`--help` hid the knowledge overlay.** Forward-by-default handed `--help` to the
194
+ spine, whose usage lists nine commands and none of kb's, so a user concluded the
195
+ overlay was not installed. Intercepted at `argv[0]` only, and the spine's own usage is
196
+ still rendered — forward-by-default is intact, with a regression test that proves a
197
+ non-intercepted command still reaches the spine.
198
+ - **kb's eval battery tested the wrong skill.** Six scenarios, none covering kb's own
199
+ method, two byte-identical to the code lens's and exercising an architect pass kb does
200
+ not ship — while extraction, placement, reconciliation, the corpus letter and locators
201
+ had no cold-run coverage at all. Rewritten in kb's units, three new scenarios added,
202
+ and a new invariant refuses any scenario citing a support file its distribution lacks.
203
+ The ANALYSIS template's example rows were the code lens's verbatim (Python paths in a
204
+ knowledge template); replaced with topic-graph rows.
205
+
206
+ ### Added
207
+ - **`sdlc_check.py anchor <path> <phrase>`** — the half `claim-id` never had: it turns a
208
+ prose citation into a *verified* span. The check has always demanded resolved locators
209
+ and nothing produced them, so every one was hand-authored against a machine verifier.
210
+ Whitespace in the phrase matches as `\s+`, because a PDF extraction breaks phrases
211
+ mid-line and a probe that pretty-prints collapsed whitespace shows the phrase intact
212
+ while the checker sees the break. Refuses ambiguity and refuses what it cannot anchor,
213
+ and re-verifies every locator with `kb_check_locator` before emitting it — the tool can
214
+ never produce a span its own validator would reject.
215
+ - **Extraction-as-artifact** for large binary corpora (`distillation.md` §1): the stored
216
+ extraction may be the corpus artifact on its own, `sha256:` covering it, with the
217
+ original recorded as `original_path:` + `original_sha256:` instead of copied in. The
218
+ code already allowed this; the doctrine said the extraction came "additionally", so a
219
+ faithful reader copied gigabytes for nothing. The recorded fields state their limit
220
+ where they are defined: `original_sha256` is never checked.
221
+
222
+ ## [1.20.3] - 2026-08-02
223
+
224
+ Three defects found by a field test in which cold agents operated the three published
225
+ skills on real fixtures — a brownfield API, three infrastructure documents, a business
226
+ brief. None of them had been found by any static pass.
227
+
228
+ ### Fixed
229
+ - **The multi-lens routing note named the wrong lens** (shipped in kb 1.0.0 and mkt
230
+ 0.3.0; invisible in the code package, where the literal happened to be right). The row
231
+ for the CURRENT lens was hardcoded as `` `agentic-sdlc` — the **code** lens `` and
232
+ copied verbatim into every distribution, so a kb project listed the code lens twice
233
+ and never named kb. Both the self row AND the sibling table are now derived from the
234
+ `routing.md` lens table — the same authoritative, drift-guarded file the domain router
235
+ reads — so no lens word is restated by hand anywhere. The lookup is lazy: `preuninstall`
236
+ keeps working on an installation that lost `routing.md`, a duplicate row is refused
237
+ instead of silently winning, and a missing row throws.
238
+ - **`FACT` was the way past the URL rule** (marketing lens). `BENCHMARK` owes a source
239
+ URL and `ASSUMPTION` a range, but `FACT` — "user input or primary data" — owed nothing,
240
+ so a researched observation classed FACT with source "see research/VOC.md" entered the
241
+ ledger unsourced. `mkt_check.py` now errors on a FACT with no source, or one pointing at
242
+ a document of the engagement, while exempting a cell that names the client as origin
243
+ (their own primary data may well be a file they handed over). `research.md` states the
244
+ two legal origins.
245
+ - **A review verdict could be delivered nowhere.** `review.md` (all three copies) now says
246
+ the verdict travels as the reviewer's final output, and says it on both sides — the
247
+ requester's and the reviewer's. A reviewer that messages the requester mid-run depends
248
+ on a channel it cannot verify and which fails silently; a requester waiting for that
249
+ message stalls holding a verdict that already exists.
250
+
251
+ ### Changed
252
+ - The guarding test for the routing note asserted that it named the detected SIBLING,
253
+ never itself — which is why the bug shipped. It now asserts this lens is named, with
254
+ its own lens word and no duplicates, and is mutation-tested against the original
255
+ defect. `A_SIBLING` is derived from the lens table rather than parsed out of the file
256
+ under test.
257
+
5
258
  ## [1.20.2] - 2026-08-01
6
259
 
7
260
  ### Fixed
package/README.md CHANGED
@@ -9,6 +9,7 @@
9
9
  - **Architect pass — capabilities before files**: at L3, before listing what changes, the feature is stated as the *capabilities* it needs and each is ruled against the platform (EXISTS / INADEQUATE / MISSING); what is missing is designed as a component with its own contract, of which the feature is one consumer — never inlined into the feature's code path. A `## Component Map` in `strategic/architecture.md` is the durable inventory the pass reads, so the platform is not re-derived from source every session. On a codebase the methodology arrives in late, the map's silence is treated as **unread, not empty**: it can never ground a MISSING verdict.
10
10
  - **Execution disciplines**: explicit TDD (RED/GREEN/REFACTOR), systematic debugging, an L3 spec-elicitation round, and a single code-review definition wired into the workflow phases.
11
11
  - **Operative + comprehension guides + agent-global KB**: distil user-provided indications into source-faithful operative `GUIDE_*.md` (`source_kind: document`), and let the agent autonomously author **code-comprehension guides** (`source_kind: code`) for complex components — a source-faithful mental-model map that survives across sessions, so the next session doesn't re-derive and break the component from partial understanding. Consulted before work; shared cross-project via `~/.agentic-sdlc`.
12
+ - **Several people, one project**: the workstream registry (`audit/handoff.md`) is **generated** from one file per open workstream, so two people opening or closing two workstreams on two branches edit two different files and their merge is clean. Row-per-workstream alone was not enough — a file-global `Date:` header defeats row-level ownership — so the header is derived from the sources and no writer touches it. The generated view can still conflict; that conflict is resolved by re-running `index`, never by hand, and `validate` refuses CLEAN until the file matches its sources. The append-only review log gets `merge=union` (a built-in driver, no per-clone configuration). It all works with no VCS at all: it is files and a generator.
12
13
  - **Opt-in subagent execution**: an approved design projects into a validated executable plan an orchestrator can drive through subagents.
13
14
  - **Self-activating**: a SessionStart hook emits repo-sourced orientation; a deterministic self-eval battery guards the skill's own doctrine as the release gate.
14
15
  - **Standalone complete**: works fully with local `ai_docs/` without requiring devPNT.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-sdlc-skill",
3
- "version": "1.20.2",
3
+ "version": "1.21.0",
4
4
  "description": "Documentation-First SDLC protocol with triage, Vision governance and optional devPNT integration.",
5
5
  "author": "Antonio Pinto (https://github.com/Antoneeo)"
6
6
  }
package/package.json CHANGED
@@ -1,50 +1,50 @@
1
- {
2
- "name": "@antoneeo/agentic-sdlc-skill",
3
- "version": "1.20.2",
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/routing.md",
39
- "skills/agentic-sdlc-skill/ENFORCEMENT.md",
40
- "skills/agentic-sdlc-skill/scripts/sdlc_check.py",
41
- "skills/agentic-sdlc-skill/scripts/sdlc_core.py",
42
- "gemini-extension.json",
43
- "README.md",
44
- "CHANGELOG.md",
45
- "scripts/lib.js",
46
- "scripts/init.js",
47
- "scripts/postinstall.js",
48
- "scripts/preuninstall.js"
49
- ]
50
- }
1
+ {
2
+ "name": "@antoneeo/agentic-sdlc-skill",
3
+ "version": "1.21.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/routing.md",
39
+ "skills/agentic-sdlc-skill/ENFORCEMENT.md",
40
+ "skills/agentic-sdlc-skill/scripts/sdlc_check.py",
41
+ "skills/agentic-sdlc-skill/scripts/sdlc_core.py",
42
+ "gemini-extension.json",
43
+ "README.md",
44
+ "CHANGELOG.md",
45
+ "scripts/lib.js",
46
+ "scripts/init.js",
47
+ "scripts/postinstall.js",
48
+ "scripts/preuninstall.js"
49
+ ]
50
+ }
package/scripts/init.js CHANGED
@@ -3,14 +3,7 @@
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
  const { execSync } = require('child_process');
6
- const { SKILL_SOURCE, CLIENTS, clientDetected, skillTarget, loadTemplates, templateFor } = require('./lib');
7
-
8
- // Sibling lenses of the same family: one shared core, one `ai_docs/` tree, a different
9
- // fidelity discipline each. Keyed by the installed skill directory name.
10
- const SIBLING_LENSES = {
11
- 'kb-agentic': 'knowledge',
12
- 'mkt-agentic-sdlc': 'marketing',
13
- };
6
+ const { SKILL_SOURCE, INSTALLED_SKILL_NAME, SELF_LENS, SIBLING_LENSES, CLIENTS, clientDetected, skillTarget, loadTemplates, templateFor } = require('./lib');
14
7
 
15
8
  const cwd = process.cwd();
16
9
 
@@ -119,6 +112,34 @@ const writeIfNotExists = (relPath, content, description) => {
119
112
 
120
113
  seedFiles.forEach(([relPath, content]) => writeIfNotExists(relPath, content));
121
114
 
115
+ const EOL = String.fromCharCode(10);
116
+ // 5b. Merge hygiene for the append-only review log (F-028, defence in depth).
117
+ // `merge=union` is a BUILT-IN driver: no per-clone `git config`, unlike
118
+ // `merge=ours`, which silently does nothing until every clone configures it.
119
+ // Rows are date-stamped, so interleaving them loses no information and their
120
+ // order carries none. Create-only, and appended rather than rewritten: a user's
121
+ // own .gitattributes is never clobbered.
122
+ const gitattributes = () => {
123
+ const marker = 'ai_docs/audit/reviews/REVIEW_LOG.md';
124
+ const stanza = [
125
+ '',
126
+ '# agentic-sdlc: the review log is append-only and its rows are date-stamped,',
127
+ '# so a union merge keeps both sides instead of asking a human to pick one.',
128
+ marker + ' merge=union',
129
+ '',
130
+ ].join(EOL);
131
+ const filePath = path.join(cwd, '.gitattributes');
132
+ if (!fs.existsSync(path.join(cwd, '.git'))) return; // not a git repo: nothing to do
133
+ const current = fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : '';
134
+ if (current.includes(marker)) {
135
+ console.log('SKIP .gitattributes already covers the review log.');
136
+ return;
137
+ }
138
+ fs.writeFileSync(filePath, current + stanza, 'utf8');
139
+ console.log('OK .gitattributes: review log set to merge=union (concurrent reviews merge cleanly).');
140
+ };
141
+ gitattributes();
142
+
122
143
  // 6. Client discovery and protocol pointers
123
144
  console.log('\n--- Environment Analysis ---');
124
145
 
@@ -168,7 +189,7 @@ if (siblings.size > 0) {
168
189
  This project has more than one lens of the Agentic SDLC family installed:
169
190
 
170
191
  ${list}
171
- - \`agentic-sdlc\` — the **code** lens
192
+ - \`${INSTALLED_SKILL_NAME}\` — the **${SELF_LENS}** lens
172
193
 
173
194
  One \`ai_docs/\` tree, one project default (\`default_domain:\` in \`ai_docs/README.md\`),
174
195
  one lens per unit of work. Before acting on any L2, L3 or Spike, run the domain router
@@ -196,7 +217,7 @@ Delete it once the merge is done.
196
217
  `, 'multi-lens routing note');
197
218
  if (wrote && protocolPreexisting) {
198
219
  console.log(' ⚠️ A protocol pointer already existed and was NOT overwritten.');
199
- console.log(' Merge the code-lens ladder from AGENTIC_MULTI_LENS.md into it by hand.');
220
+ console.log(` Merge the ${SELF_LENS}-lens ladder from AGENTIC_MULTI_LENS.md into it by hand.`);
200
221
  }
201
222
  }
202
223