devflow-kit 3.7.0 → 3.8.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.
Files changed (184) hide show
  1. package/CHANGELOG.md +359 -1
  2. package/README.md +11 -11
  3. package/dist/agents/code.md +2 -4
  4. package/dist/agents/design.md +1 -1
  5. package/dist/agents/fix.md +6 -7
  6. package/dist/agents/git.md +1 -1
  7. package/dist/agents/harden.md +1 -1
  8. package/dist/agents/refactor.md +2 -4
  9. package/dist/agents/review.md +4 -4
  10. package/dist/agents/skim.md +2 -2
  11. package/dist/agents/triage.md +2 -2
  12. package/dist/cli/commands/capture.js +1 -1
  13. package/dist/cli/commands/curation-move-io.js +102 -0
  14. package/dist/cli/commands/curation-move-step.js +374 -0
  15. package/dist/cli/commands/{learning.js → curation.js} +302 -99
  16. package/dist/cli/commands/gate-level-prompts.js +426 -0
  17. package/dist/cli/commands/gates.js +34 -11
  18. package/dist/cli/commands/init-seed.js +11 -8
  19. package/dist/cli/commands/init.js +240 -54
  20. package/dist/cli/commands/memory.js +2 -2
  21. package/dist/cli/commands/prompt-io.js +37 -0
  22. package/dist/cli/commands/uninstall.js +81 -9
  23. package/dist/cli.js +2 -2
  24. package/dist/commands/bug-analysis.md +24 -35
  25. package/dist/commands/code-review.md +32 -36
  26. package/dist/commands/debug.md +4 -4
  27. package/dist/commands/dynamic-build.md +25 -24
  28. package/dist/commands/dynamic-plan.md +4 -4
  29. package/dist/commands/dynamic-profile.md +4 -4
  30. package/dist/commands/dynamic-tickets.md +4 -4
  31. package/dist/commands/explore.md +5 -5
  32. package/dist/commands/implement.md +52 -81
  33. package/dist/commands/plan.md +5 -5
  34. package/dist/commands/release.md +4 -4
  35. package/dist/commands/research.md +5 -5
  36. package/dist/commands/resolve.md +28 -30
  37. package/dist/commands/self-review.md +4 -12
  38. package/dist/core/assets.js +20 -20
  39. package/dist/core/curate-tuning-config.js +5 -6
  40. package/dist/core/curation-move-notice.js +84 -0
  41. package/dist/core/curation-move-skip.js +36 -0
  42. package/dist/core/curation-move.js +35 -0
  43. package/dist/core/curation-queue-cleanup.js +134 -0
  44. package/dist/core/curation-store.js +98 -0
  45. package/dist/core/{learning-variants.js → curation-variants.js} +65 -41
  46. package/dist/core/echo-value.js +11 -5
  47. package/dist/core/evidence-policy.js +1 -1
  48. package/dist/core/feature-switch.js +95 -19
  49. package/dist/core/fs-atomic.js +1 -1
  50. package/dist/core/gate-level.js +10 -2
  51. package/dist/core/git.js +16 -14
  52. package/dist/core/ledger-root.js +82 -22
  53. package/dist/core/linked-path.js +4 -4
  54. package/dist/core/manifest-lock.js +238 -0
  55. package/dist/core/manifest.js +58 -14
  56. package/dist/core/migrations.js +1 -13
  57. package/dist/core/observations.js +2 -2
  58. package/dist/core/plugins.js +15 -15
  59. package/dist/core/pool.js +26 -0
  60. package/dist/core/project-paths.js +103 -34
  61. package/dist/core/queue-drain.js +2 -2
  62. package/dist/core/tracked-areas.js +35 -0
  63. package/dist/core/tracker.js +1 -1
  64. package/dist/{learning-off → curation-off}/agents/code.md +2 -4
  65. package/dist/{learning-off → curation-off}/agents/fix.md +6 -7
  66. package/dist/{learning-off → curation-off}/agents/refactor.md +2 -4
  67. package/dist/{learning-off → curation-off}/agents/review.md +3 -3
  68. package/dist/{learning-off → curation-off}/agents/triage.md +1 -1
  69. package/dist/{learning-off → curation-off}/commands/bug-analysis.md +20 -31
  70. package/dist/{learning-off → curation-off}/commands/code-review.md +29 -33
  71. package/dist/{learning-off → curation-off}/commands/debug.md +1 -1
  72. package/dist/{learning-off → curation-off}/commands/dynamic-build.md +22 -21
  73. package/dist/{learning-off → curation-off}/commands/explore.md +1 -1
  74. package/dist/{learning-off → curation-off}/commands/implement.md +49 -78
  75. package/dist/{learning-off → curation-off}/commands/plan.md +1 -1
  76. package/dist/{learning-off → curation-off}/commands/resolve.md +25 -27
  77. package/dist/{learning-off → curation-off}/commands/self-review.md +1 -9
  78. package/dist/hud/components/{learning-counts.js → curation-counts.js} +36 -17
  79. package/dist/hud/config.js +1 -1
  80. package/dist/hud/index.js +6 -6
  81. package/dist/hud/render.js +3 -3
  82. package/dist/skills/git/references/pr/validate-branch.md +8 -5
  83. package/dist/skills/git/references/tracker/github/ensure-pr-ready.md +13 -5
  84. package/dist/skills/git/references/tracker/jira/ensure-pr-ready.md +13 -5
  85. package/dist/skills/git/references/tracker/linear/ensure-pr-ready.md +13 -5
  86. package/dist/targets/claude-code/{learning-install.js → curation-install.js} +85 -65
  87. package/dist/targets/claude-code/installer.js +15 -15
  88. package/dist/targets/claude-code/language-stamp.js +5 -5
  89. package/dist/targets/claude-code/post-install.js +2 -2
  90. package/dist/targets/claude-code/tracker-servers.js +1 -1
  91. package/package.json +3 -2
  92. package/src/assets/agents/_partials/_code.mds +11 -11
  93. package/src/assets/agents/code.mds +2 -2
  94. package/src/assets/agents/curate.md +8 -8
  95. package/src/assets/agents/debug.mds +6 -6
  96. package/src/assets/agents/design.mds +18 -18
  97. package/src/assets/agents/fix.mds +6 -5
  98. package/src/assets/agents/git.mds +1 -1
  99. package/src/assets/agents/harden.mds +7 -7
  100. package/src/assets/agents/knowledge.mds +23 -23
  101. package/src/assets/agents/refactor.mds +2 -2
  102. package/src/assets/agents/research.mds +15 -15
  103. package/src/assets/agents/review.mds +43 -43
  104. package/src/assets/agents/skim.mds +11 -11
  105. package/src/assets/agents/triage.mds +22 -22
  106. package/src/assets/agents/validate.md +13 -26
  107. package/src/assets/commands/_partials/_decisions.mds +13 -13
  108. package/src/assets/commands/_partials/_engine.mds +8 -8
  109. package/src/assets/commands/_partials/_knowledge.mds +29 -15
  110. package/src/assets/commands/_partials/_preamble.mds +4 -4
  111. package/src/assets/commands/_partials/_settings.mds +2 -2
  112. package/src/assets/commands/_partials/_wave.mds +7 -7
  113. package/src/assets/commands/bug-analysis.mds +37 -48
  114. package/src/assets/commands/code-review.mds +46 -50
  115. package/src/assets/commands/debug.mds +14 -14
  116. package/src/assets/commands/dynamic-build.mds +38 -37
  117. package/src/assets/commands/dynamic-plan.mds +22 -22
  118. package/src/assets/commands/dynamic-profile.mds +2 -2
  119. package/src/assets/commands/dynamic-tickets.mds +8 -8
  120. package/src/assets/commands/explore.mds +20 -20
  121. package/src/assets/commands/implement.mds +77 -98
  122. package/src/assets/commands/plan.mds +27 -27
  123. package/src/assets/commands/release.mds +12 -12
  124. package/src/assets/commands/research.mds +19 -19
  125. package/src/assets/commands/resolve.mds +56 -50
  126. package/src/assets/commands/self-review.mds +20 -20
  127. package/src/assets/mds/git/_ops.mds +3 -1
  128. package/src/assets/mds/git/_ops_pr.mds +1 -1
  129. package/src/assets/mds/git/_ops_steps.mds +10 -4
  130. package/src/assets/mds/git/_pr.mds +7 -4
  131. package/src/assets/rules/quality.md +1 -0
  132. package/src/assets/scripts/hooks/background-memory-update +2 -2
  133. package/src/assets/scripts/hooks/capture-prompt +12 -12
  134. package/src/assets/scripts/hooks/capture-question +11 -11
  135. package/src/assets/scripts/hooks/capture-turn +12 -12
  136. package/src/assets/scripts/hooks/{learning-lock → curation-lock} +2 -2
  137. package/src/assets/scripts/hooks/curation-move +293 -0
  138. package/src/assets/scripts/hooks/ensure-devflow-init +45 -13
  139. package/src/assets/scripts/hooks/ensure-proxy +4 -4
  140. package/src/assets/scripts/hooks/ensure-root-gitignore +4 -4
  141. package/src/assets/scripts/hooks/git-marker +81 -0
  142. package/src/assets/scripts/hooks/json-helper.cjs +134 -51
  143. package/src/assets/scripts/hooks/json-parse +1 -1
  144. package/src/assets/scripts/hooks/lib/curation-move.cjs +1582 -0
  145. package/src/assets/scripts/hooks/lib/{learning-store.cjs → curation-store.cjs} +242 -118
  146. package/src/assets/scripts/hooks/lib/decisions-format.cjs +3 -3
  147. package/src/assets/scripts/hooks/lib/mkdir-lock.cjs +24 -7
  148. package/src/assets/scripts/hooks/lib/project-paths.cjs +132 -39
  149. package/src/assets/scripts/hooks/lib/render-decisions.cjs +34 -22
  150. package/src/assets/scripts/hooks/lib/tracked-areas.cjs +259 -0
  151. package/src/assets/scripts/hooks/memory-worker +1 -1
  152. package/src/assets/scripts/hooks/pre-compact-memory +6 -16
  153. package/src/assets/scripts/hooks/queue-append +228 -103
  154. package/src/assets/scripts/hooks/resolve-project-root +2 -2
  155. package/src/assets/scripts/hooks/session-start-context +143 -69
  156. package/src/assets/scripts/hooks/session-start-memory +3 -43
  157. package/src/assets/scripts/lib/project-config.cjs +12 -5
  158. package/src/assets/scripts/resolve-base.cjs +1043 -0
  159. package/src/assets/scripts/resolve-settings.cjs +42 -18
  160. package/src/assets/skills/agent-references/SKILL.md +5 -2
  161. package/src/assets/skills/agent-references/references/commands/implement-levels.md +27 -0
  162. package/src/assets/skills/agent-references/references/commands/implement-revalidate.md +6 -4
  163. package/src/assets/skills/agent-references/references/commands/resolve-levels.md +24 -0
  164. package/src/assets/skills/apply-decisions/SKILL.md +1 -1
  165. package/src/assets/skills/docs-framework/SKILL.md +7 -7
  166. package/src/assets/skills/docs-framework/references/patterns.md +3 -4
  167. package/src/assets/skills/quality-gates/SKILL.md +1 -1
  168. package/src/assets/skills/worktree-support/references/roots.md +2 -2
  169. package/templates/lint-pack/.lint-pack.conf +86 -0
  170. package/templates/lint-pack/README.md +190 -0
  171. package/templates/lint-pack/lint-pack.sh +905 -0
  172. package/dist/core/learning-queue-cleanup.js +0 -27
  173. package/dist/core/learning-store.js +0 -61
  174. /package/dist/{learning-off → curation-off}/agents/debug.md +0 -0
  175. /package/dist/{learning-off → curation-off}/agents/design.md +0 -0
  176. /package/dist/{learning-off → curation-off}/agents/harden.md +0 -0
  177. /package/dist/{learning-off → curation-off}/agents/knowledge.md +0 -0
  178. /package/dist/{learning-off → curation-off}/agents/research.md +0 -0
  179. /package/dist/{learning-off → curation-off}/agents/skim.md +0 -0
  180. /package/dist/{learning-off → curation-off}/commands/dynamic-plan.md +0 -0
  181. /package/dist/{learning-off → curation-off}/commands/dynamic-profile.md +0 -0
  182. /package/dist/{learning-off → curation-off}/commands/dynamic-tickets.md +0 -0
  183. /package/dist/{learning-off → curation-off}/commands/release.md +0 -0
  184. /package/dist/{learning-off → curation-off}/commands/research.md +0 -0
@@ -0,0 +1,190 @@
1
+ # Lint pack template
2
+
3
+ A lint pack is a small script that catches the faults a linter does not: a removed flag that the docs still name, a plan ID or a tombstone phrase in a comment, and an oversized function. This folder holds a template for one.
4
+
5
+ You copy the template into your repository and you own the copy. devflow never runs the template itself, and it never installs or updates your copy. During `/implement` at the `lean` gate level, Validate runs your wired copy after the build, typecheck, lint and test commands that your project has pass. At any other level, nothing runs it.
6
+
7
+ ## Where to find the template
8
+
9
+ - `$(npm root -g)/devflow-kit/templates/lint-pack/` after a global install of `devflow-kit`.
10
+ - `templates/lint-pack/` in the devflow repository.
11
+
12
+ The folder holds three files:
13
+
14
+ | File | Purpose |
15
+ |---|---|
16
+ | `lint-pack.sh` | The script. Copy it, for example to `scripts/lint-pack.sh`. |
17
+ | `.lint-pack.conf` | The example config. Copy it to the root of your repository. Every check is off. |
18
+ | `README.md` | This file. |
19
+
20
+ ## Wiring
21
+
22
+ Validate finds the pack under one name, `lint-pack`. If the project has a root `package.json` script of that name, Validate uses it, else it uses the root `Makefile` target. Add one of these entries.
23
+
24
+ - A root `package.json` script. Validate runs it as `npm run -s lint-pack -- <sha>`.
25
+
26
+ ```json
27
+ { "scripts": { "lint-pack": "bash scripts/lint-pack.sh" } }
28
+ ```
29
+
30
+ - A root `Makefile` target. Validate passes the base SHA as `BASE`.
31
+
32
+ ```make
33
+ lint-pack:
34
+ @bash scripts/lint-pack.sh $(BASE)
35
+ ```
36
+
37
+ Then copy `.lint-pack.conf` to the repository root, turn on the checks you want, and commit both files. The script needs bash 3.2 or newer, git 2.30 or newer, and a POSIX `awk`, `grep`, `sort` and `sed`. It works on the bash 3.2 that macOS ships.
38
+
39
+ Run it by hand like this:
40
+
41
+ ```bash
42
+ bash scripts/lint-pack.sh "$(git merge-base origin/main HEAD)"
43
+ ```
44
+
45
+ ## What it reads
46
+
47
+ The script takes one argument: the base commit, as a full 40-digit lower-case SHA that is an ancestor of `HEAD`. It reads the committed change `<base>..HEAD`. It reads `.lint-pack.conf` from the `HEAD` commit, never from the work tree, and only as data. It never sources or evaluates the config. An uncommitted edit to the config changes no result, but the run prints a `pack-dirty .lint-pack.conf` line. A config that is not a regular file at `HEAD`, for example a symlink or a directory, stops the run with `bad-config 0`.
48
+
49
+ The script checks the arguments, the git version, the repository and the base before it reads the config.
50
+
51
+ The `size.arg` key runs a command that the committed config names. Treat the config as code. Review a change to it as you review code. Do not run the pack on a branch that you do not trust.
52
+
53
+ ## Output
54
+
55
+ All output goes to stdout. The script prints no added text. The lines come in the order of the table below. The last line is always the `LINT_PACK:` line.
56
+
57
+ ```
58
+ plan-id src/app.ts:12 tp
59
+ stale-symbol docs/guide.md:3 --legacy-mode
60
+ pack-changed .lint-pack.conf
61
+ base 3f2a9c1d0e8b7a6f5e4d3c2b1a0f9e8d7c6b5a4f
62
+ LINT_PACK: matches 2
63
+ ```
64
+
65
+ | Line | Meaning |
66
+ |---|---|
67
+ | `<check-id> <path>:<line> <id>` | One match. The check id is `stale-symbol`, `plan-id` or `function-size`. The id is the symbol, the pattern id, or `function-size`. A path keeps the quoted form that git uses for odd names. |
68
+ | `+<k> more` | The matches beyond the first 50. Records are sorted by check id, path and line number. |
69
+ | `pack-changed <path>` | A pack file that the branch changed. At most 20 are listed, then `+<k> more`. These lines also print before an error line. See "No self-silencing". |
70
+ | `pack-dirty <path>` | A pack file that differs from `HEAD` in the work tree or the index, or that is untracked and not ignored. At most 20 are listed, then `+<k> more`. These lines come after the `pack-changed` lines, and they also print before an error line. |
71
+ | `skipped-binary <path>` | A file that git treats as binary, so the script did not search it. At most 10 are listed, then `+<k> more`. |
72
+ | `symbol-cap <n>` | The number of symbols left out because the script searches at most 500. |
73
+ | `unsafe-tokens <n>` | The number of symbols dropped because they are longer than 64 bytes or hold characters outside `A-Za-z0-9_.:/-`. |
74
+ | `unmatched-diagnostics <n>` | The number of linter diagnostics on a path that is not in the diff. Look at the linter's path form if this is not zero. |
75
+ | `dropped-long-lines <n>` | The number of lines longer than 200 bytes that the script did not print. A dropped match still counts in `matches`. |
76
+ | `base <sha>` | The commit that the run compared. It is the line before the `LINT_PACK:` line on every run that got past the base checks, an error run included. |
77
+ | `LINT_PACK: clean` | A check ran and found nothing. Exit 0. |
78
+ | `LINT_PACK: no-config` | No config at `HEAD`, or no check is enabled. Exit 0. |
79
+ | `LINT_PACK: matches <n>` | `n` matches in all, printed or not. Exit 1. |
80
+ | `LINT_PACK: error <reason>` | The run could not finish. Exit 2. A pack error is never a pass. |
81
+
82
+ The error reasons are a closed set: `usage`, `git-too-old`, `not-a-repo`, `bad-base`, `base-not-ancestor`, `bad-config <line>`, `bad-pattern <id>`, `git-failed`, `interrupted`, `linter-missing` and `linter-exit <n>`. A pattern error names the pattern id, or `stale-symbol` or `size-match`. `git-too-old` means that git is older than 2.30. `interrupted` means that the run got SIGTERM or SIGINT, for example from a timeout. `bad-config 0` means that the config at `HEAD` is not a regular file.
83
+
84
+ If the work tree matches `HEAD`, the same base, the same `HEAD` and the same config give the same bytes on stdout and the same exit code. The script clears the git pathspec variables, `GIT_DIFF_OPTS` and the grep variables, and sets `LC_ALL=C`. It pins its git calls against hostile `diff.*`, `grep.*`, `color.*`, `core.quotePath` and `submodule.recurse` settings.
85
+
86
+ ## The config
87
+
88
+ One `key=value` per line. A blank line and a line that starts with `#` are skipped. A repeated key adds one more item to its list. A key that takes one value may appear once. An unknown key, a malformed line, an empty value or a repeated single key stops the run with `bad-config <line>`. An enabled check without its required keys stops the run with the line of its `enabled` key.
89
+
90
+ A glob is a shell glob in which `*` also matches `/`. A pattern is a POSIX extended regular expression. The script rejects `\d`, `\w`, `\s`, `\b`, back-references, and a pattern that matches the empty string. Use `[0-9]`, `[A-Za-z0-9_]` and `[[:space:]]`. Add patterns as data: examples use placeholders such as `ADR-NNN`, never a real ID.
91
+
92
+ ### Check 1: stale symbols
93
+
94
+ A symbol qualifies when it is on a removed line in the source globs, on no added line in the source globs, and in no tracked file at `HEAD` outside the doc and help globs. Each line at `HEAD` in the doc and help globs that names the symbol is a match. This includes a line that the branch added. A file that git treats as binary is not searched, so a symbol in it never counts as in use. A submodule is not searched. The search is whole-word and fixed-string, with `git grep` on `HEAD` only.
95
+
96
+ | Key | Meaning |
97
+ |---|---|
98
+ | `stale.enabled` | `true` or `false`. Default `false`. Needs `stale.source` and `stale.symbol`. |
99
+ | `stale.source` | A glob for the files whose removed lines supply symbols. |
100
+ | `stale.doc` | A glob for files that must not name a removed symbol. Default `*.md`. |
101
+ | `stale.help` | A glob for help-only files, such as a usage text or a man page. |
102
+ | `stale.symbol` | An ERE that pulls symbols out of the removed lines. |
103
+ | `stale.min-length` | The shortest symbol to search for, from 1 to 64. The example sets 6. |
104
+ | `stale.allow` | A glob for paths whose matches are expected. |
105
+
106
+ ### Check 2: plan IDs and tombstones
107
+
108
+ Each pattern matches as a whole word on added lines.
109
+
110
+ | Key | Meaning |
111
+ |---|---|
112
+ | `ids.enabled` | `true` or `false`. Default `false`. Needs at least one `ids.pattern`. |
113
+ | `ids.pattern` | `<id> <ERE>`. The id is 1 to 32 characters of `a-z`, `0-9` and `-`. The pattern follows the first space. |
114
+ | `ids.allow` | A glob for paths where such text is fine. The example allows `CHANGELOG.md`. |
115
+
116
+ ### Check 3: function size
117
+
118
+ The script runs your linter on the work tree, from the repository root. It keeps only the `path:line:` diagnostics that fall inside the lines the branch added. It strips the absolute repository root from a path. A diagnostic on a path that is not in the diff is counted on the `unmatched-diagnostics` line.
119
+
120
+ | Key | Meaning |
121
+ |---|---|
122
+ | `size.enabled` | `true` or `false`. Default `false`. Needs at least one `size.arg`. |
123
+ | `size.arg` | One word of the linter command per line. The command runs as argv, with no shell. |
124
+ | `size.match` | An ERE. A diagnostic line must match it. Default: every line. |
125
+ | `size.ok-exit` | An exit status that is not an error. Repeat to add. Default: `0` and `1`. |
126
+ | `size.allow` | A glob for paths whose diagnostics are expected. |
127
+
128
+ An exit status outside `size.ok-exit` gives `linter-exit <n>`. The statuses 126 and 127 give `linter-missing`. A non-zero status with no `<path>:<line>:` line in the output also gives `linter-exit <n>`, even when `size.ok-exit` accepts the status. A linter that printed no diagnostic did not run, and the script never reads that as clean.
129
+
130
+ **ESLint.** Run `eslint --format unix` and match the rule name. ESLint 9 moved the `unix` formatter to the package `eslint-formatter-unix`, so install it first. Name the local binary. Do not use `npx`: it can fetch an unpinned package from the registry. A linter that is not installed gives `linter-missing`.
131
+
132
+ ```
133
+ size.arg=./node_modules/.bin/eslint
134
+ size.arg=--format
135
+ size.arg=unix
136
+ size.match=max-lines-per-function
137
+ ```
138
+
139
+ **Clippy.** Print short messages, allow nothing but one lint, and set `too-many-lines-threshold` in `clippy.toml`. Do not use `too_many_arguments`. The short message reads `this function has too many lines (n/m)`, so match that text. Clippy prints to stderr, and the script captures stdout and stderr together. Clippy exits 0, or 101 when it fails to compile.
140
+
141
+ ```
142
+ size.arg=cargo
143
+ size.arg=clippy
144
+ size.arg=--message-format
145
+ size.arg=short
146
+ size.arg=--
147
+ size.arg=-A
148
+ size.arg=clippy::all
149
+ size.arg=-W
150
+ size.arg=clippy::too_many_lines
151
+ size.match=too many lines
152
+ ```
153
+
154
+ ## No self-silencing
155
+
156
+ A branch must not clear a match by editing the pack. The script never checks its own files: the config and the script are skipped by all three checks. It prints `pack-changed <path>` for each pack file the branch changed, so a reviewer sees the change. It prints `pack-dirty <path>` for each pack file that has an uncommitted change. The files are:
157
+
158
+ - `.lint-pack.conf`, including a config that the branch deleted or renamed away.
159
+ - The script itself.
160
+ - Any `.gitattributes`, in the root or in a subdirectory, because a `binary` entry hides a file from a search.
161
+ - The build files `package.json`, `Makefile`, `makefile` and `GNUmakefile`. A changed line in one of them that names `lint-pack` or `BASE` counts as a pack change.
162
+
163
+ The `pack-changed` and `pack-dirty` lines print even when the result is `no-config`, and they print before an error line. Fix never edits the lint pack, its config, its build-file entry or any `.gitattributes` to clear a match. It never silences the linter to clear a match. Silencing the linter means a disable comment or a change to the linter's own config. Fix reports the match under Blockers.
164
+
165
+ ## Limits
166
+
167
+ - An edited line counts as an added line. An old plan ID on a line that you touch is a match.
168
+ - Checks 1 and 2 read committed changes, and the config at `HEAD`. Commit your work before you run the script.
169
+ - Check 3 runs the linter on the work tree. It sees a diagnostic only on an added line, which is usually the first line of a function.
170
+ - Help globs name help-only files. A file outside the doc and help globs counts as code.
171
+ - A symbol that only occurs inside a longer symbol on the same line is not searched on its own.
172
+ - A file that git treats as binary, for example through `.gitattributes`, is not searched. The script prints a `skipped-binary` line instead of passing it silently.
173
+ - The script searches `HEAD` with `git grep`. It never follows a symlink out of the repository.
174
+ - The linter must finish within the Bash timeout that Validate sets for the run. If the timeout stops the script with SIGTERM or SIGINT, the script prints `LINT_PACK: error interrupted`. Validate then reports the pack as `UNVERIFIED`.
175
+ - A `pack-dirty` line lists an untracked file only when git does not ignore it.
176
+ - The pack prints the base it compared (`base <sha>`), but Validate does not check that base yet, and issue #537 adds that check. A changed build-file line that names `lint-pack` or `BASE` inside the compared range is still reported as a pack change.
177
+
178
+ ## False positives
179
+
180
+ Fix may not edit the pack or silence the linter, so a match that you judge false halts `/implement` after two Fix attempts. To clear it:
181
+
182
+ 1. Add an allow glob for that path to the matching key: `stale.allow`, `ids.allow` or `size.allow`. For a code line, you can also add the disable comment of your linter.
183
+ 2. Commit the change.
184
+ 3. Ask `/implement` to re-validate the branch.
185
+
186
+ The next run prints a `pack-changed .lint-pack.conf` line, so the review sees the change. An allow list and a disable comment are the project's decision, and a person makes them.
187
+
188
+ ## Tests
189
+
190
+ devflow keeps a fixture suite for the template in `tests/lint-pack-template.test.ts`. It builds real git repositories and compares the output with hand-written expected text. It runs under bash 3.2 on macOS and under bash 5 on Linux.