@antoneeo/agentic-sdlc-skill 1.51.0 → 1.52.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,34 @@
2
2
 
3
3
  Tutte le modifiche significative a questa skill saranno documentate in questo file.
4
4
 
5
+ ## [1.52.0] - 2026-11-01
6
+
7
+ ### What's new
8
+
9
+ **A session that writes only documents no longer costs you a branch.** When you run several sessions with a coordinator, a session working only on design documents can work in the folder the others already use, instead of a worktree of its own. It writes only its own unit's files, runs no git command that changes the folder, and leaves index regeneration and its closure steps to the coordinator, so you no longer merge one branch per documents-only unit. A session that writes code still holds the code lease, or works in its own worktree.
10
+
11
+ **Every file several sessions touch has one writer.** Each session adds only its own rows to the review log. Translation catalogs count as code, so in the shared folder only the session holding the code lease writes them. devPNT's store goes in the Shared section of a commit map.
12
+
13
+ **The coordinator survives compaction and changes only when you say so.** After its context is compacted, the coordinator rereads the leases and the shared request record before acting, instead of trusting its summary. A session it starts does not become coordinator. To change coordinator, name the new session: it records your words, tells the previous coordinator, which stops, and sends you anything written in between.
14
+
15
+ **Branches that add review rows merge without a conflict.** When two branches both add rows to the review log and your project has no merge rule for that file, merging them stops on a conflict you resolve by hand. The check the agent runs when it closes a piece of work now notices the missing rule and prints the exact line to add to `.gitattributes`, so the agent sees what to fix while it works, without anyone reading release notes. Nothing changes at session start, and the note never makes a check fail.
16
+
17
+ #### What to do
18
+
19
+ **1. Update (everyone).** The changes arrive only with the update.
20
+ 1. Run `npm install -g @antoneeo/agentic-sdlc-skill@latest`, then `agentic-sdlc-install-skill`.
21
+ 2. Close and reopen your agent sessions: the new version loads only at startup.
22
+
23
+ To check: `npm ls -g @antoneeo/agentic-sdlc-skill` shows 1.52.0.
24
+
25
+ ### Changed
26
+ - `coordination.md` (F-089): the checkout a runtime mounts is the one exception to «own worktree» under coordination — the code-writer lease holder, a documents-only part (its own unit's files under the docs root and its own review-log rows; no git command that changes the checkout, no `index` or `mark`) and the coordinator, which alone runs `index`, `review-map` and `mark` there; the switch/stash/reset bans hold. «Code» defined (translation catalogs included). §1 retitled «Shared files: one writer each»: review log, translation catalogs, an external tool's store tracked in git. Who coordinates: the named conversation keeps the role across compaction and rereads `leases.md` and the shared record; a session another starts never inherits it; a new owner entry changes it, with a handover window up to the previous coordinator's answer. `leases.md` opens with a `coordinator` line. Ruling r42.
27
+ - `SKILL.md` Phase 4: the shared checkout, not the code-writer lease alone, is the exception to the own worktree; the bans hold there and only its coordinator runs `index`.
28
+ - `templates.md`: `leases.md` opening line; a commit-map Shared example for devPNT's store.
29
+ - The shared validator (F-090): `check` prints a `[note]` when the review log (`<docs>/audit/reviews/REVIEW_LOG.md`) has no `merge` attribute, naming the line to add to `.gitattributes` at the repository root (`git check-attr`, with personal and system attribute files ignored; a per-clone `.git/info/attributes` still counts). A deliberate non-union driver is respected. The exit code is unchanged, and session orientation still runs no git.
30
+ - `ENFORCEMENT.md`: «A review log git would not merge cleanly -- `check` names it» (F-090).
31
+ - `templates.md`: the `.gitattributes` stanza's note says `check` names a missing stanza; `coordination.md` §1: the coordinator adds it (F-090).
32
+
5
33
  ## [1.51.0] - 2026-10-31
6
34
 
7
35
  ### What's new
package/README.md CHANGED
@@ -4,13 +4,15 @@
4
4
 
5
5
  <!-- whats-new:begin -->
6
6
  <!-- generated by scripts/whats_new.js from CHANGELOG.md: edit the CHANGELOG, then run node scripts/whats_new.js --write -->
7
- ## What's new in 1.51.0
7
+ ## What's new in 1.52.0
8
8
 
9
- **Several sessions can work on one repository, one of them coordinating.** When you run several agent sessions on the same project at once and tell one of them that it coordinates the others, they follow shared rules. Each request record has a single writer, so its entries are never numbered twice. A resource only one session can use at a time, such as the development container or the test database, is taken and released through the coordinator, so one session no longer restarts what another is running against. An authorization you gave one session is not passed to another by message. A session that stops reports what it did, and the coordinator checks it before telling you the work is done. Before a commit that carries several sessions' work, the coordinator checks that every changed file is assigned to the right unit. If you name no coordinator, nothing changes.
9
+ **A session that writes only documents no longer costs you a branch.** When you run several sessions with a coordinator, a session working only on design documents can work in the folder the others already use, instead of a worktree of its own. It writes only its own unit's files, runs no git command that changes the folder, and leaves index regeneration and its closure steps to the coordinator, so you no longer merge one branch per documents-only unit. A session that writes code still holds the code lease, or works in its own worktree.
10
10
 
11
- **Decisions taken on your behalf are labelled.** In the request record, a decision a session took under a delegation you gave it, and words you gave one session for work another session records, now carry their own heading. They are never read later as something you said yourself, and a delegated decision never overrides one of yours: a choice that would change it comes back to you as a question.
11
+ **Every file several sessions touch has one writer.** Each session adds only its own rows to the review log. Translation catalogs count as code, so in the shared folder only the session holding the code lease writes them. devPNT's store goes in the Shared section of a commit map.
12
12
 
13
- **The reminder of what must not break also covers files written from the shell.** From 1.49.0 the agent is reminded of a unit's constraints before it edits a file; a file it writes through a shell command never triggered that reminder, so the agent now looks the constraints up itself.
13
+ **The coordinator survives compaction and changes only when you say so.** After its context is compacted, the coordinator rereads the leases and the shared request record before acting, instead of trusting its summary. A session it starts does not become coordinator. To change coordinator, name the new session: it records your words, tells the previous coordinator, which stops, and sends you anything written in between.
14
+
15
+ **Branches that add review rows merge without a conflict.** When two branches both add rows to the review log and your project has no merge rule for that file, merging them stops on a conflict you resolve by hand. The check the agent runs when it closes a piece of work now notices the missing rule and prints the exact line to add to `.gitattributes`, so the agent sees what to fix while it works, without anyone reading release notes. Nothing changes at session start, and the note never makes a check fail.
14
16
 
15
17
  #### What to do
16
18
 
@@ -18,17 +20,7 @@
18
20
  1. Run `npm install -g @antoneeo/agentic-sdlc-skill@latest`, then `agentic-sdlc-install-skill`.
19
21
  2. Close and reopen your agent sessions: the new version loads only at startup.
20
22
 
21
- To check: `npm ls -g @antoneeo/agentic-sdlc-skill` shows 1.51.0.
22
-
23
- **2. Coordinating several sessions (only if you run them in parallel).**
24
- - **This concerns you if** you run more than one agent session on the same repository at the same time.
25
- - **Why:** without a coordinator, sessions can write the same record at once, restart a container another session is using, or leave one commit nobody can split by unit.
26
- - **Steps:** tell the session you want as coordinator, in your own words, that it coordinates the others; it records your words, and the rules apply from then on. Each other session asks it before using a shared resource. Before committing several sessions' work together, it writes the commit map and runs `sdlc_check.py commit-map <map file>`.
27
- - **To check:** when a session takes a shared resource, `ai_docs/audit/leases.md` gains a `take` line naming it.
28
-
29
- | New file | Skill | Who reads it |
30
- |---|---|---|
31
- | `coordination.md` | agentic-sdlc | the agent, only while several sessions share a repository |
23
+ To check: `npm ls -g @antoneeo/agentic-sdlc-skill` shows 1.52.0.
32
24
 
33
25
  Full history: [CHANGELOG](https://github.com/Antoneeo/agentic-sdlc-skill/blob/main/CHANGELOG.md)
34
26
  <!-- whats-new:end -->
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-sdlc-skill",
3
- "version": "1.51.0",
3
+ "version": "1.52.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,6 +1,6 @@
1
1
  {
2
2
  "name": "@antoneeo/agentic-sdlc-skill",
3
- "version": "1.51.0",
3
+ "version": "1.52.0",
4
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
5
  "keywords": [
6
6
  "claude-code",
@@ -183,6 +183,16 @@ not see them, because the wired hook legitimately lives in the git-ignored
183
183
  mechanism (Gemini today) keeps the note -- read it as the manual-reads reminder; a
184
184
  `.codex/hooks.json` wired in a shape other than the documented one keeps it too.
185
185
 
186
+ **A review log git would not merge cleanly -- `check` names it (F-090).** When the docs
187
+ root holds `audit/reviews/REVIEW_LOG.md` and git reports no `merge` attribute for it (no
188
+ committed `.gitattributes` line covers it: a project set up before the stanza, a custom
189
+ docs root, a project below the repository root, a course project), `check` prints one
190
+ `[note]` with the exact line to add at the repository root. Same contract as above:
191
+ informational, never the exit code, never a `validate` warning. Personal attribute files
192
+ (except the per-clone `.git/info/attributes`) are ignored, so the note matches what a
193
+ teammate's clone does; a deliberate driver other
194
+ than `union` is respected. Session orientation does not run it: it stays zero-execution.
195
+
186
196
  **Installing the package wires the hook machine-wide (F-042).** On Claude Code
187
197
  with Python, `npm i -g` (and every update) wires a SessionStart orient hook into
188
198
  the USER-level settings (`$CLAUDE_CONFIG_DIR/settings.json` when set, else
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: agentic-sdlc
3
- version: 1.51.0
3
+ version: 1.52.0
4
4
  description: Documentation-First SDLC protocol with risk-proportional triage, Vision as a guide, a complete Standalone mode and optional symbiosis with devPNT. Use for features, significant bugs, refactors, audits and documented maintenance.
5
5
  author: Antonio Pinto (https://github.com/Antoneeo)
6
6
  copyright: (c) 2026 Antonio Pinto
@@ -208,7 +208,7 @@ Hybrid L3:
208
208
  ### 4. Development and Testing
209
209
 
210
210
  - Implement only after the documentation gate required by the level; at L3 it ends with the owner's design approval (`review.md` §When a review is due). **Flip the ANALYSIS frontmatter `PLANNED` → `IN_PROGRESS` when implementation starts** — that flip is what `gate` and the handoff registry key on, and nothing else performs it.
211
- - Isolate the work: run an L3 change on its own branch. In Hybrid, prefer a git worktree from the start — a running devPNT server locks `.devpnt/*.db` and blocks in-place branch switches/merges in the primary worktree. A session that may run while another session uses the same checkout works in its **own git worktree**, and never switches branch, stashes, resets or runs `index` in a checkout another session may be using; under coordination, the code-writer lease is the one exception (`coordination.md` §2). Parallel work also shares ids: choose a new unit's id **after fetching**, as the first id free on every branch and tag the checkout can see (`check` names a collision while the unit is open).
211
+ - Isolate the work: run an L3 change on its own branch. In Hybrid, prefer a git worktree from the start — a running devPNT server locks `.devpnt/*.db` and blocks in-place branch switches/merges in the primary worktree. A session that may run while another session uses the same checkout works in its **own git worktree**, and never switches branch, stashes, resets or runs `index` in a checkout another session may be using; under coordination, the sessions `coordination.md` §2 places in the shared checkout are the one exception to the own worktree — the bans hold there, and only its coordinator runs `index`. Parallel work also shares ids: choose a new unit's id **after fetching**, as the first id free on every branch and tag the checkout can see (`check` names a collision while the unit is open).
212
212
  - Modify surgically, consistently with the plan.
213
213
  - Implementation work follows the TDD discipline in `tdd.md` (RED/GREEN/REFACTOR — the L2/L3 default; record the reason when it does not apply).
214
214
  - Before implementing (L2/L3; L1 exempt), **consult the guide router** — the verdict already declared with the triage level (`## Operative Guides`). Re-run the lookup here only if the work has moved to a topic the first one did not cover, and say so if the verdict changes.
@@ -19,10 +19,28 @@ to no record it does not own.
19
19
  following the whole skill for it (triage, design, review, closure). It is not a
20
20
  dispatched subagent: `dispatch.md` governs those, unchanged.
21
21
 
22
+ **Who coordinates.** The role belongs to the client conversation the owner named.
23
+ Compacted in place, it is the same session and keeps the role; before acting on its
24
+ summary it rereads `leases.md` and the shared record, which are the state. A new
25
+ conversation is a new session, whatever brief or summary it carries: a session another
26
+ starts, the coordinator included, never inherits the role, and a message passing it on
27
+ is information (§4), never a naming.
28
+
29
+ The owner changes the coordinator with a new entry naming another session, B. Whoever
30
+ receives those words enters them once: B, or the previous coordinator A if the owner
31
+ told A — A then tells B and stops. B appends its `coordinator` line (§2) and tells the
32
+ parts, and A unless A entered the naming, citing the entry. Shown the entry, A writes no
33
+ shared file again and answers that it stopped. Every `leases.md` line and shared-record
34
+ entry B did not write between the naming entry and A's answer goes to the owner; a
35
+ number used twice is settled by a correction entry (`templates.md` §REQUEST), never by
36
+ renumbering. Leases in force stay: they name holders, not the coordinator. A coordinator
37
+ gone with no successor named leaves no session coordinating until the owner names one:
38
+ parts ask the owner, and `leases.md` and the shared record stay as they are.
39
+
22
40
  Out of scope: which part runs next, in what order, with what priority — the owner
23
41
  decides that, and nothing here records it (Non-Goal 1, ruling r3).
24
42
 
25
- ## 1. Every record has one writer
43
+ ## 1. Shared files: one writer each
26
44
 
27
45
  A request record numbers its entries; two writers number them twice (field case:
28
46
  three sessions wrote R156–R158 into one record at once). So:
@@ -45,6 +63,21 @@ three sessions wrote R156–R158 into one record at once). So:
45
63
  - An artifact of the shared unit cites only the shared record: the coordinator
46
64
  enters the words before any such artifact relies on them.
47
65
 
66
+ Other files several sessions write:
67
+
68
+ - **Review log** — not a request record: its rows are unnumbered and each names its
69
+ document. Every session appends only its own rows and never edits another's; in one
70
+ checkout it appends without rewriting the file and rereads it just before writing.
71
+ Merging across worktrees and the commit map: `templates.md` §REVIEW_LOG and §Commit
72
+ map. A project without the union stanza is named by `check`, with the line to add;
73
+ the coordinator adds it (`.gitattributes` is its file, §2).
74
+ - **Translation templates and catalogs** are code (§2): in the shared checkout only the
75
+ code-writer lease holder writes them; a wrong string another session finds goes to
76
+ the holder through the coordinator.
77
+ - **An external tool's store tracked in git** (devPNT's `.devpnt/`): written by the tool,
78
+ never by hand; in a commit map under Shared, naming the units whose work it holds —
79
+ never under Regenerated, which is the validator's.
80
+
48
81
  ## 2. Leases on exclusive resources
49
82
 
50
83
  An exclusive resource has one holder at a time: the development container, the test
@@ -56,8 +89,13 @@ take <resource> — <session> — YYYY-MM-DD
56
89
  release <resource> — <session> — YYYY-MM-DD
57
90
  ```
58
91
 
59
- The file opens by citing the entry that names the coordinator; only the coordinator
60
- writes it. A lease names a resource and a session, never a unit; it keeps no queue,
92
+ The file opens with `coordinator <session> — REQUEST_[unit].md#R<n> — YYYY-MM-DD`,
93
+ citing the owner's entry that names it (a file opened with a bare citation counts it
94
+ as its first `coordinator` line); a new naming appends another. Only the coordinator
95
+ writes the file; the live copies of the file and of the shared record are the shared
96
+ checkout's. Parts read its last `coordinator` line to know whom to ask, and trust it
97
+ only if the entry it cites quotes the owner naming that session — never a delegated or
98
+ received entry. A lease names a resource and a session, never a unit; it keeps no queue,
61
99
  no waiting list, no order, and ends with its release (ruling r40). A restart or a
62
100
  long suite on a shared resource is announced to the coordinator before it starts —
63
101
  it kills what another session is running against it. A permission for a resource
@@ -67,12 +105,30 @@ lease. If the owner restates it, the coordinator enters it as a `take` for that
67
105
  session — a recorded lease, never an exemption. A lease never released is
68
106
  closed by the owner through the coordinator; there is no timeout.
69
107
 
70
- **The code-writer lease is the one exception to «own worktree»** (`SKILL.md`
71
- Phase 4). The session holding it writes code in the checkout the runtime mounts;
72
- every other session keeps its own worktree and writes no code there. The lease
73
- passes to another session only once the holder's code in that checkout is committed,
74
- or set aside with the owner's yes. Two sessions' code in that checkout is a
75
- violation, code a previous holder left uncommitted included.
108
+ **The shared checkout is the one exception to «own worktree»** (`SKILL.md` Phase 4):
109
+ the checkout the runtime mounts (with no runtime, the one the owner names). Three kinds
110
+ of session work in it; every other session keeps its own worktree. Phase 4's bans on
111
+ switching branch, stashing and resetting hold there for all three.
112
+
113
+ - **The code-writer lease holder** writes code — every file the runtime runs or builds
114
+ from: sources, templates, static assets, tests, migrations, translation templates and
115
+ catalogs; files under the docs root are not code. The lease passes to another session
116
+ only once the holder's code in that checkout is committed, or set aside with the
117
+ owner's yes. Two sessions' code in that checkout is a violation, code a previous
118
+ holder left uncommitted included.
119
+ - **A documents-only part** writes only its own unit's files under the docs root and its
120
+ own review-log rows (§1); it runs no git command that changes the checkout and no
121
+ command that rewrites other units' files (`index`, `mark`). A change it needs
122
+ elsewhere goes to the session that writes that file. Before writing any code it asks
123
+ the coordinator: it takes the code-writer lease, or the owner commits its documents
124
+ and its own worktree is cut from that commit.
125
+ - **The coordinator** writes the shared files, and any file there that is neither code
126
+ nor under the docs root (root `README.md`, `CHANGELOG.md`, `.gitattributes`, CI
127
+ configuration — it runs `init` when needed); it alone runs `index`, `review-map` and
128
+ `mark` there, for the documents-only parts' closure steps too. There `review-map` sees
129
+ every session's files, so when a documents-only part closes, the coordinator writes
130
+ that unit's section of the commit map (§6) and the part's merge brief takes its file
131
+ table from it, and says so.
76
132
 
77
133
  ## 3. Decisions taken under delegation
78
134
 
@@ -111,6 +167,9 @@ Open points:
111
167
  Needs the owner:
112
168
  ```
113
169
 
170
+ A documents-only part in the shared checkout lists under `Open points` the closure
171
+ steps it left to the coordinator (§2).
172
+
114
173
  The coordinator checks each claim on the diff and the run output, never on the
115
174
  message (`review.md`, an unproven completion claim), then tells the owner what is
116
175
  done, what is left and what needs them.
@@ -1377,9 +1377,12 @@ def _open_units(root):
1377
1377
  return units
1378
1378
 
1379
1379
 
1380
- def _git_out(root, *args, timeout=30):
1380
+ def _git_out(root, *args, timeout=30, env=None):
1381
+ # `env` is merged into the inherited environment, never a replacement: a bare
1382
+ # dict would drop PATH and fail silently on Windows.
1381
1383
  r = subprocess.run(["git", *args], cwd=str(root), capture_output=True, text=True,
1382
- encoding="utf-8", errors="replace", timeout=timeout)
1384
+ encoding="utf-8", errors="replace", timeout=timeout,
1385
+ env={**os.environ, **env} if env else None)
1383
1386
  return r.stdout if r.returncode == 0 else None
1384
1387
 
1385
1388
 
@@ -2481,10 +2484,64 @@ def cmd_check(root, strict=False, hybrid=False, extra_validate=None, extra_secti
2481
2484
  failed = any(rc for _, rc in rcs)
2482
2485
  print(f"\ncheck: {'NOT CLEAN' if failed else 'CLEAN'} "
2483
2486
  f"({', '.join(f'{title} rc={rc}' for title, rc in rcs)})")
2484
- print_orient_hook_note(root)
2487
+ print_check_notes(root)
2485
2488
  return 1 if failed else 0
2486
2489
 
2487
2490
 
2491
+ def _attr_pattern(path):
2492
+ """A .gitattributes pattern matching exactly `path`. Order matters (probed):
2493
+ a backslash, glob characters and a leading `#` or `!` (comment, negation)
2494
+ are escaped first, then the result is C-quoted when it holds whitespace,
2495
+ `"` or a backslash."""
2496
+ p = re.sub(r"([\\\[*?])", r"\\\1", path)
2497
+ if p.startswith(("#", "!")):
2498
+ p = "\\" + p
2499
+ if re.search(r'[\s"\\]', p):
2500
+ p = '"' + p.replace("\\", "\\\\").replace('"', '\\"') + '"'
2501
+ return p
2502
+
2503
+
2504
+ def review_log_union_note(root):
2505
+ """F-090: the note for a review log git would not merge with union, or None.
2506
+
2507
+ Git itself is asked (`check-attr`), so patterns and nested files count;
2508
+ personal and system attribute files do not, so the answer is the one a
2509
+ teammate's clone gets. Only `unspecified` is a gap: `union` or any other
2510
+ driver is a choice. Residual: `.git/info/attributes` is still read. Any
2511
+ failure -- no git, not a work tree, timeout -- is no note: `check` never
2512
+ breaks on it."""
2513
+ try:
2514
+ log = ai_path(root, "audit", "reviews", "REVIEW_LOG.md")
2515
+ if not log.is_file():
2516
+ return None
2517
+ prefix = _git_out(root, "rev-parse", "--show-prefix", timeout=3)
2518
+ if prefix is None:
2519
+ return None
2520
+ rel = log.resolve().relative_to(Path(root).resolve()).as_posix()
2521
+ out = _git_out(root, "-c", "core.attributesFile=", "check-attr", "-z", "merge",
2522
+ "--", rel, timeout=3, env={"GIT_ATTR_NOSYSTEM": "1"})
2523
+ if out is None:
2524
+ return None
2525
+ fields = out.split("\0")
2526
+ if len(fields) < 3 or fields[2] != "unspecified":
2527
+ return None
2528
+ path = prefix.rstrip("\r\n") + rel # a folder may begin with a space
2529
+ return (f"[note] {path} has no merge attribute: two branches that both add review "
2530
+ "rows conflict when merged. Fix: add this line to .gitattributes at the "
2531
+ f"repository root: {_attr_pattern(path)} merge=union")
2532
+ except Exception:
2533
+ return None
2534
+
2535
+
2536
+ def print_check_notes(root):
2537
+ """Every check-layer note, informational and never an exit code. The one
2538
+ place an overlay that replaces `check` calls, so a new note cannot miss it."""
2539
+ print_orient_hook_note(root)
2540
+ note = review_log_union_note(root)
2541
+ if note:
2542
+ print(note)
2543
+
2544
+
2488
2545
  # --------------------------------------------------------------------- gate
2489
2546
 
2490
2547
  # --- UserPromptSubmit reminder hook (F-046) --------------------------------
@@ -571,7 +571,7 @@ Written only by the coordinating session (`coordination.md` §2); append-only.
571
571
  ```markdown
572
572
  # Leases
573
573
 
574
- Coordinator named in `REQUEST_[unit].md#R<n>`.
574
+ coordinator coordinating session — REQUEST_[unit].md#R<n> — YYYY-MM-DD
575
575
 
576
576
  take dev-container — wave-6 session — YYYY-MM-DD
577
577
  release dev-container — wave-6 session — YYYY-MM-DD
@@ -592,6 +592,7 @@ committed. Each item is a list line whose first code span is the path.
592
592
 
593
593
  ## Shared
594
594
  - `ai_docs/audit/reviews/REVIEW_LOG.md` — F-001, F-002
595
+ - `.devpnt/plans/plans.db` — F-001, F-002 (written by devPNT)
595
596
 
596
597
  ## Regenerated
597
598
  - `ai_docs/INDEX.md`
@@ -809,7 +810,7 @@ Concurrent reviews: `init` writes a `.gitattributes` stanza giving this file
809
810
  Rows are date-stamped and their order carries no meaning, so a union merge keeps
810
811
  both sides instead of asking a human to choose. It is defence in depth: without
811
812
  git, or without the stanza, the outcome is today's — one conflict you resolve by
812
- hand, never a lost row.
813
+ hand, never a lost row. `check` names a missing stanza and the line to add (F-090).
813
814
 
814
815
 
815
816
  ## ai_docs/audit/HANDOFF_[feature].md — one open workstream, its own file