@rse/ase 2.0.2 → 2.0.4

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 (236) hide show
  1. package/dst/ase-agent-definition-core.js +111 -87
  2. package/dst/ase-agent-fleet.js +1 -1
  3. package/dst/ase-agent-runtime-claim.js +5 -3
  4. package/dst/ase-agent-runtime-engine.js +1 -1
  5. package/dst/ase-agent-runtime-phase.js +1 -1
  6. package/dst/ase-agent-runtime-request.js +1 -1
  7. package/dst/ase-agent-runtime.js +3 -5
  8. package/dst/ase-artifact.js +3 -3
  9. package/dst/ase-config-core.js +2 -16
  10. package/dst/ase-config-schema.js +1 -3
  11. package/dst/ase-config.js +2 -0
  12. package/dst/ase-hook.js +13 -13
  13. package/dst/ase-lib-daemon-cli.js +117 -4
  14. package/dst/ase-lib-server-cli.js +4 -5
  15. package/dst/ase-lib-version.js +14 -5
  16. package/dst/ase-man-catalog.js +229 -0
  17. package/dst/ase-man-render.js +278 -0
  18. package/dst/ase-man-tui.js +636 -0
  19. package/dst/ase-man.js +33 -27
  20. package/dst/ase-mcp.js +4 -4
  21. package/dst/ase-service-getopt.js +2 -2
  22. package/dst/ase-service-otel.js +4 -4
  23. package/dst/ase-service-skills.js +5 -15
  24. package/dst/ase-service.js +87 -210
  25. package/dst/ase-setup-common.js +1 -2
  26. package/dst/ase-setup-settings.js +6 -9
  27. package/dst/ase-setup.js +4 -5
  28. package/dst/ase-spec.js +103 -20
  29. package/dst/ase-statusline.js +170 -170
  30. package/dst/ase-task-board-filter.js +5 -4
  31. package/dst/ase-task-board-flow.js +7 -6
  32. package/dst/ase-task-board-graph.js +5 -4
  33. package/dst/ase-task-board-tui-control.js +41 -35
  34. package/dst/ase-task-board-tui-model.js +185 -167
  35. package/dst/ase-task-board-tui-popup.js +2 -3
  36. package/dst/ase-task-board-tui-view.js +74 -70
  37. package/dst/ase-task-board-web-client.js +27 -27
  38. package/dst/ase-task-board-web-server.js +2 -2
  39. package/dst/ase-task-board.js +1 -1
  40. package/dst/ase-task-format.js +1 -1
  41. package/dst/ase-task-store-client.js +17 -5
  42. package/dst/ase-task-store-core.js +5 -7
  43. package/dst/ase-task-store-issues.js +16 -1
  44. package/dst/ase-task-store-plugin-ase.js +7 -3
  45. package/dst/ase-task-store-plugin-gitea.js +9 -32
  46. package/dst/ase-task-store-plugin-github.js +3 -12
  47. package/dst/ase-task-store-plugin-gitlab.js +2 -18
  48. package/dst/ase-task.js +51 -23
  49. package/dst/ase-util-compat.js +1 -1
  50. package/dst/ase-util-diagram.js +13 -37
  51. package/dst/ase.js +5 -5
  52. package/dst/man/ase-agent-adhoc.md +1165 -0
  53. package/dst/man/ase-agent-condenser.md +383 -0
  54. package/dst/man/ase-agent-editor.md +441 -0
  55. package/dst/man/ase-agent-estimator.md +477 -0
  56. package/dst/man/ase-agent-fleet.md +358 -0
  57. package/dst/man/ase-agent-implementer.md +521 -0
  58. package/dst/man/ase-agent-integrator.md +449 -0
  59. package/dst/man/ase-agent-qualifier.md +426 -0
  60. package/dst/man/ase-agent-rebooter.md +384 -0
  61. package/dst/man/ase-agent-relay.md +262 -0
  62. package/dst/man/ase-agent-researcher.md +478 -0
  63. package/dst/man/ase-agent.md +628 -0
  64. package/dst/man/ase-artifact-list.md +57 -0
  65. package/dst/man/ase-artifact-name.md +56 -0
  66. package/dst/man/ase-artifact.md +92 -0
  67. package/dst/man/ase-config-delete.md +74 -0
  68. package/dst/man/ase-config-edit.md +83 -0
  69. package/dst/man/ase-config-get.md +70 -0
  70. package/dst/man/ase-config-init.md +110 -0
  71. package/dst/man/ase-config-list.md +68 -0
  72. package/dst/man/ase-config-set.md +92 -0
  73. package/dst/man/ase-config.md +426 -0
  74. package/dst/man/ase-hook-permission-request.md +61 -0
  75. package/dst/man/ase-hook-pre-tool-use.md +96 -0
  76. package/dst/man/ase-hook-session-end.md +71 -0
  77. package/dst/man/ase-hook-session-persona.md +65 -0
  78. package/dst/man/ase-hook-session-start.md +184 -0
  79. package/dst/man/ase-hook-stop.md +52 -0
  80. package/dst/man/ase-hook-user-prompt-submit.md +54 -0
  81. package/dst/man/ase-hook.md +93 -0
  82. package/dst/man/ase-man.md +195 -0
  83. package/dst/man/ase-mcp.md +102 -0
  84. package/dst/man/ase-service-log.md +59 -0
  85. package/dst/man/ase-service-send.md +60 -0
  86. package/dst/man/ase-service-start.md +93 -0
  87. package/dst/man/ase-service-status.md +58 -0
  88. package/dst/man/ase-service-stop.md +52 -0
  89. package/dst/man/ase-service.md +124 -0
  90. package/dst/man/ase-setup-disable.md +67 -0
  91. package/dst/man/ase-setup-enable.md +66 -0
  92. package/dst/man/ase-setup-install.md +116 -0
  93. package/dst/man/ase-setup-mcp.md +213 -0
  94. package/dst/man/ase-setup-status.md +101 -0
  95. package/dst/man/ase-setup-statusline.md +162 -0
  96. package/dst/man/ase-setup-telemetry.md +166 -0
  97. package/dst/man/ase-setup-uninstall.md +85 -0
  98. package/dst/man/ase-setup-update.md +117 -0
  99. package/dst/man/ase-setup.md +156 -0
  100. package/dst/man/ase-spec-export.md +99 -0
  101. package/dst/man/ase-spec-init.md +57 -0
  102. package/dst/man/ase-spec-lint.md +74 -0
  103. package/dst/man/ase-spec-preview.md +57 -0
  104. package/dst/man/ase-spec.md +85 -0
  105. package/dst/man/ase-statusline.md +330 -0
  106. package/dst/man/ase-task-assign.md +138 -0
  107. package/dst/man/ase-task-board.md +651 -0
  108. package/dst/man/ase-task-delete.md +46 -0
  109. package/dst/man/ase-task-edit.md +73 -0
  110. package/dst/man/ase-task-idscheme.md +92 -0
  111. package/dst/man/ase-task-lifecycle.md +92 -0
  112. package/dst/man/ase-task-list.md +86 -0
  113. package/dst/man/ase-task-load.md +48 -0
  114. package/dst/man/ase-task-newid.md +100 -0
  115. package/dst/man/ase-task-purge.md +49 -0
  116. package/dst/man/ase-task-rename.md +69 -0
  117. package/dst/man/ase-task-request.md +108 -0
  118. package/dst/man/ase-task-save.md +78 -0
  119. package/dst/man/ase-task-status.md +79 -0
  120. package/dst/man/ase-task-store.md +377 -0
  121. package/dst/man/ase-task-view.md +50 -0
  122. package/dst/man/ase-task.md +335 -0
  123. package/dst/man/ase-util-compat.md +38 -0
  124. package/dst/man/ase-util-diagram.md +140 -0
  125. package/dst/man/ase-util-meta.md +68 -0
  126. package/dst/man/ase-util-metric.md +74 -0
  127. package/dst/man/ase-util-mint.md +85 -0
  128. package/dst/man/ase-util-worktree.md +109 -0
  129. package/dst/man/ase-util.md +81 -0
  130. package/dst/man/ase.md +228 -0
  131. package/package.json +12 -17
  132. package/plugin/.claude-plugin/plugin.json +1 -1
  133. package/plugin/.codex-plugin/plugin.json +1 -1
  134. package/plugin/.github/plugin/plugin.json +1 -1
  135. package/plugin/agents/ase-code-lint.md +3 -3
  136. package/plugin/agents/ase-docs-proofread.md +3 -3
  137. package/plugin/agents/ase-docs-refine.md +3 -3
  138. package/plugin/agents/ase-spec-lint.md +338 -0
  139. package/plugin/meta/ase-skill.md +7 -0
  140. package/plugin/mods/ase-mods.ts +10 -7
  141. package/plugin/mods/claude-code.d.ts +26 -3
  142. package/plugin/skills/ase-code-analyze/SKILL.md +18 -10
  143. package/plugin/skills/ase-code-analyze/help.md +11 -6
  144. package/plugin/skills/ase-code-lint/SKILL.md +37 -23
  145. package/plugin/skills/ase-code-lint/help.md +10 -5
  146. package/plugin/skills/ase-help-intent/data.md +204 -13
  147. package/plugin/skills/ase-help-skill/catalog.md +1 -0
  148. package/plugin/skills/ase-meta-workflow/workflow.txt +2 -0
  149. package/plugin/skills/ase-repo-commit/SKILL.md +1 -0
  150. package/plugin/skills/ase-repo-merge/SKILL.md +1 -0
  151. package/plugin/skills/ase-repo-review/SKILL.md +5 -3
  152. package/plugin/skills/ase-repo-review/help.md +3 -1
  153. package/plugin/skills/ase-spec-edit/SKILL.md +3 -3
  154. package/plugin/skills/ase-spec-edit/help.md +1 -1
  155. package/plugin/skills/ase-spec-lint/SKILL.md +695 -0
  156. package/plugin/skills/ase-spec-lint/help.md +171 -0
  157. package/plugin/skills/ase-task-implement/SKILL.md +24 -6
  158. package/plugin/skills/ase-task-implement/help.md +11 -1
  159. package/dst/man/ase-agent-adhoc.1 +0 -515
  160. package/dst/man/ase-agent-condenser.1 +0 -193
  161. package/dst/man/ase-agent-editor.1 +0 -212
  162. package/dst/man/ase-agent-estimator.1 +0 -214
  163. package/dst/man/ase-agent-fleet.1 +0 -185
  164. package/dst/man/ase-agent-implementer.1 +0 -233
  165. package/dst/man/ase-agent-integrator.1 +0 -213
  166. package/dst/man/ase-agent-qualifier.1 +0 -214
  167. package/dst/man/ase-agent-rebooter.1 +0 -193
  168. package/dst/man/ase-agent-relay.1 +0 -128
  169. package/dst/man/ase-agent-researcher.1 +0 -217
  170. package/dst/man/ase-agent.1 +0 -264
  171. package/dst/man/ase-artifact-list.1 +0 -38
  172. package/dst/man/ase-artifact-name.1 +0 -39
  173. package/dst/man/ase-artifact.1 +0 -56
  174. package/dst/man/ase-config-delete.1 +0 -45
  175. package/dst/man/ase-config-edit.1 +0 -48
  176. package/dst/man/ase-config-get.1 +0 -46
  177. package/dst/man/ase-config-init.1 +0 -60
  178. package/dst/man/ase-config-list.1 +0 -42
  179. package/dst/man/ase-config-set.1 +0 -52
  180. package/dst/man/ase-config.1 +0 -231
  181. package/dst/man/ase-hook-permission-request.1 +0 -36
  182. package/dst/man/ase-hook-pre-tool-use.1 +0 -59
  183. package/dst/man/ase-hook-session-end.1 +0 -47
  184. package/dst/man/ase-hook-session-persona.1 +0 -37
  185. package/dst/man/ase-hook-session-start.1 +0 -81
  186. package/dst/man/ase-hook-stop.1 +0 -34
  187. package/dst/man/ase-hook-user-prompt-submit.1 +0 -34
  188. package/dst/man/ase-hook.1 +0 -51
  189. package/dst/man/ase-man.1 +0 -67
  190. package/dst/man/ase-mcp.1 +0 -61
  191. package/dst/man/ase-service-log.1 +0 -43
  192. package/dst/man/ase-service-send.1 +0 -47
  193. package/dst/man/ase-service-start.1 +0 -54
  194. package/dst/man/ase-service-status.1 +0 -46
  195. package/dst/man/ase-service-stop.1 +0 -37
  196. package/dst/man/ase-service.1 +0 -85
  197. package/dst/man/ase-setup-disable.1 +0 -44
  198. package/dst/man/ase-setup-enable.1 +0 -45
  199. package/dst/man/ase-setup-install.1 +0 -73
  200. package/dst/man/ase-setup-mcp.1 +0 -124
  201. package/dst/man/ase-setup-status.1 +0 -60
  202. package/dst/man/ase-setup-statusline.1 +0 -92
  203. package/dst/man/ase-setup-telemetry.1 +0 -92
  204. package/dst/man/ase-setup-uninstall.1 +0 -59
  205. package/dst/man/ase-setup-update.1 +0 -64
  206. package/dst/man/ase-setup.1 +0 -93
  207. package/dst/man/ase-spec-export.1 +0 -62
  208. package/dst/man/ase-spec-lint.1 +0 -40
  209. package/dst/man/ase-spec-preview.1 +0 -40
  210. package/dst/man/ase-spec.1 +0 -46
  211. package/dst/man/ase-statusline.1 +0 -189
  212. package/dst/man/ase-task-assign.1 +0 -71
  213. package/dst/man/ase-task-board.1 +0 -384
  214. package/dst/man/ase-task-delete.1 +0 -35
  215. package/dst/man/ase-task-edit.1 +0 -46
  216. package/dst/man/ase-task-idscheme.1 +0 -65
  217. package/dst/man/ase-task-lifecycle.1 +0 -57
  218. package/dst/man/ase-task-list.1 +0 -47
  219. package/dst/man/ase-task-load.1 +0 -36
  220. package/dst/man/ase-task-newid.1 +0 -61
  221. package/dst/man/ase-task-purge.1 +0 -37
  222. package/dst/man/ase-task-rename.1 +0 -44
  223. package/dst/man/ase-task-request.1 +0 -61
  224. package/dst/man/ase-task-save.1 +0 -48
  225. package/dst/man/ase-task-status.1 +0 -55
  226. package/dst/man/ase-task-store.1 +0 -194
  227. package/dst/man/ase-task-view.1 +0 -40
  228. package/dst/man/ase-task.1 +0 -160
  229. package/dst/man/ase-util-compat.1 +0 -25
  230. package/dst/man/ase-util-diagram.1 +0 -76
  231. package/dst/man/ase-util-meta.1 +0 -45
  232. package/dst/man/ase-util-metric.1 +0 -54
  233. package/dst/man/ase-util-mint.1 +0 -59
  234. package/dst/man/ase-util-worktree.1 +0 -72
  235. package/dst/man/ase-util.1 +0 -50
  236. package/dst/man/ase.1 +0 -124
@@ -0,0 +1,695 @@
1
+ ---
2
+ name: ase-spec-lint
3
+ argument-hint: "[--help|-h] [--auto|-a] [--severity|-S=(AUTO|LOW|MEDIUM|HIGH)] [--include|-i=<aspect>[,...]] [--exclude|-e=<aspect>[,...]] [--staged] [--unstaged] [<spec-reference>]"
4
+ description: >
5
+ Lint the SpecBook-based specification (SPEC) for potential quality
6
+ problems: its syntax, its formatting, its statements, the logical
7
+ gaps of its model, and its completeness for an implementation.
8
+ Use when the user wants to "lint" or "check" the "spec" or
9
+ "specification".
10
+ user-invocable: true
11
+ disable-model-invocation: false
12
+ effort: high
13
+ allowed-tools:
14
+ - "Bash(git rev-parse *)"
15
+ - "Bash(git -C *)"
16
+ ---
17
+
18
+ @${CLAUDE_SKILL_DIR}/../../meta/ase-control.md
19
+ @${CLAUDE_SKILL_DIR}/../../meta/ase-skill.md
20
+ @${CLAUDE_SKILL_DIR}/../../meta/ase-dialog.md
21
+ @${CLAUDE_SKILL_DIR}/../../meta/ase-getopt.md
22
+
23
+ <purpose name="ase-spec-lint">
24
+ Lint Specification
25
+ </purpose>
26
+
27
+ <expand name="getopt"
28
+ arg1="ase-spec-lint"
29
+ arg2="--auto|-a --severity|-S=(AUTO|LOW|MEDIUM|HIGH) --include|-i=(none|S01|S02|S03|S04|S05|S06|S07|S08|S09|S10)... --exclude|-e=(none|S01|S02|S03|S04|S05|S06|S07|S08|S09|S10)... --staged --unstaged">
30
+ $ARGUMENTS
31
+ </expand>
32
+
33
+ <objective>
34
+ *Analyze* the specification of `<getopt-arguments/>` for *potential
35
+ problems* related to a set of specification quality aspects.
36
+ </objective>
37
+
38
+ <flow>
39
+
40
+ 1. <step id="STEP 1: Investigation">
41
+
42
+ <if condition="<ase-project-boxing/> is equal `black` and <getopt-option-severity/> is equal `AUTO`">
43
+
44
+ The project source artifacts are classified as a *black box*, so
45
+ the user does *not* want them inspected or their problems surfaced
46
+ (an *explicitly* given severity floor lifts this skip).
47
+ *Skip* the entire investigation and reporting: do *not* invoke any
48
+ `Bash`, `Glob`, or `Agent` tool and do *not* read any source, only
49
+ output the following <template/> and then *SKIP* the remaining steps
50
+ STEP 2 and STEP 3:
51
+
52
+ <template>
53
+ <ase-tpl-bullet-normal/> **LINT**: *suppressed* (`project.boxing` is `black`)
54
+ </template>
55
+
56
+ </if>
57
+
58
+ Set <condensed>true</condensed> if <ase-project-boxing/> is equal
59
+ `grey` or `black` (the latter reached only under an explicitly given
60
+ severity floor), and <condensed>false</condensed> otherwise: a
61
+ *condensed* report suppresses the full unified diffs of STEP 3.
62
+
63
+ First, determine the *effective aspect set* <aspects/>, i.e., the
64
+ specification quality aspects which are checked at all. For this,
65
+ parse <getopt-option-include/> and <getopt-option-exclude/> as
66
+ comma-separated token lists, silently dropping the `none` sentinel
67
+ and any empty token. If a token <token/> is *not* one of the aspect
68
+ ids `S01`...`S10`, only output the following <template/> and then
69
+ *STOP* the entire flow (do not perform any further steps):
70
+
71
+ <template>
72
+ ⧉ **ASE**: ✪ skill: **ase-spec-lint**, ▶ ERROR: invalid aspect id: **<token/>**
73
+ </template>
74
+
75
+ Otherwise set <aspects/> to *all* ten aspect ids `S01`...`S10` if
76
+ both lists are empty, to the *include* list if only it is non-empty,
77
+ to all ten *minus* the *exclude* list if only it is non-empty, and
78
+ to the *include* list *minus* the *exclude* list if both are
79
+ non-empty. If the resulting <aspects/> is *empty*, only output the
80
+ following <template/> and then *STOP* the entire flow (do not
81
+ perform any further steps):
82
+
83
+ <template>
84
+ ⧉ **ASE**: ✪ skill: **ase-spec-lint**, ▶ ERROR: options `--include` and `--exclude` cancel out to an empty aspect set
85
+ </template>
86
+
87
+ Then split <aspects/> into the *per-file* aspects <file-aspects/>
88
+ (those of `S01`...`S06`) and the *model-wide* aspects
89
+ <model-aspects/> (those of `S07`...`S10`), as the latter can be
90
+ judged on the entire specification model only.
91
+
92
+ Then, use the following <template/> to give a hint on this step:
93
+
94
+ <template>
95
+ <ase-tpl-bullet-secondary/> **LINT INVESTIGATION**
96
+ </template>
97
+
98
+ Dispatch the investigation to *sub-agents* via the `Agent`
99
+ tool so that *no* investigation details leak into the user-visible
100
+ transcript. The sub-agents perform the silent reading and checking;
101
+ only their final structured return values are consumed here.
102
+
103
+ For this, first *silently* resolve the `SPEC` artifacts by calling
104
+ the `ase_artifact_list(kind: [ "spec" ])` tool of the `ase` MCP
105
+ server *once* and set <corpus/> to the returned project-relative
106
+ file list. If <corpus/> is empty, only output the following
107
+ <template/> and then *STOP* the entire flow (do not perform any
108
+ further steps):
109
+
110
+ <template>
111
+ ⧉ **ASE**: ✪ skill: **ase-spec-lint**, ▶ ERROR: no specification artifacts below `<ase-spec-basedir/>`
112
+ </template>
113
+
114
+ <if condition="<getopt-option-staged/> is equal `true` or <getopt-option-unstaged/> is equal `true`">
115
+
116
+ Then *silently* restrict the linting to the *changed* files of the
117
+ Git working copy. Set <changes>staged and unstaged</changes> if
118
+ both <getopt-option-staged/> and <getopt-option-unstaged/> are equal
119
+ `true`, set <changes>staged</changes> if only
120
+ <getopt-option-staged/> is equal `true`, and set
121
+ <changes>unstaged</changes> otherwise. Determine the *repository
122
+ root* by running the command `git rev-parse --show-toplevel` (taken
123
+ exactly as given) and capturing its output into <repo-root/>. Then
124
+ determine the changed files by running the corresponding commands
125
+ (taken exactly as given), each listing one path relative to
126
+ <repo-root/> per line, and collect all listed paths, dropping
127
+ duplicates:
128
+
129
+ <if condition="<getopt-option-staged/> is equal `true`">
130
+ `git -C "<repo-root/>" -c core.quotepath=off diff --cached --name-only --diff-filter=d`
131
+ </if>
132
+
133
+ <if condition="<getopt-option-unstaged/> is equal `true`">
134
+ `git -C "<repo-root/>" -c core.quotepath=off diff --name-only --diff-filter=d`
135
+
136
+ `git -C "<repo-root/>" -c core.quotepath=off ls-files --others --exclude-standard`
137
+ </if>
138
+
139
+ Keep only those listed paths which are contained in <corpus/>. If
140
+ `<getopt-arguments/>` is not empty, keep only those files which lie
141
+ within the specification referenced by it, expanding any directory
142
+ or wildcard references with the `Glob` tool. Set <sources/> to the
143
+ resulting list of individual specification files, preserving order.
144
+
145
+ If <sources/> is empty, only output the following <template/>
146
+ and then *SKIP* the rest of this STEP 1 and the remaining steps
147
+ STEP 2 and STEP 3:
148
+
149
+ <template>
150
+ <ase-tpl-bullet-normal/> **LINT**: *no <changes/> specification files to lint*
151
+ </template>
152
+
153
+ </if>
154
+ <elseif condition="`<getopt-arguments/>` is not empty">
155
+
156
+ Then *silently* resolve `<getopt-arguments/>` to individual files,
157
+ expanding any directory or wildcard references with the `Glob` tool,
158
+ keep only those files which are contained in <corpus/>, and set
159
+ <sources/> to the resulting list, preserving order.
160
+
161
+ If <sources/> is empty (none of the *spec-reference* resolvable to a
162
+ specification file), only output the following <template/> and then
163
+ *STOP* the entire flow (do not perform any further steps):
164
+
165
+ <template>
166
+ ⧉ **ASE**: ✪ skill: **ase-spec-lint**, ▶ ERROR: no specification files to lint in: **<getopt-arguments/>**
167
+ </template>
168
+
169
+ </elseif>
170
+ <else>
171
+
172
+ Then set <sources/> to <corpus/>, i.e., lint the *entire*
173
+ specification.
174
+
175
+ </else>
176
+
177
+ Then set <schema/> to the whitespace-separated entries of
178
+ <ase-spec-schema/>, or to the single entry `std` if
179
+ <ase-spec-schema/> is empty, where each entry `std` is replaced by
180
+ the path of the bundled file `meta/ase-format-specbook.yaml`. Set
181
+ <meta/> to the space-separated paths of the bundled files
182
+ `meta/ase-format-specbook.md` and `meta/ase-tenets.md`. Form each
183
+ bundled file path by joining <ase-plugin-root/> and the file name
184
+ with exactly *one* `/` separator, as <ase-plugin-root/> may or may
185
+ not carry a trailing `/`.
186
+
187
+ <if condition="<aspects/> contains `S01`">
188
+ Then call the `ase_specbook_lint(markdown: true)` tool of the `ase`
189
+ MCP server *once*, which lints the *entire* specification against
190
+ the schema via *SpecBook* and for its generic Markdown formatting
191
+ via *markdownlint*, and set <diagnostics/> to those entries of its
192
+ returned `diagnostics` array whose `file` is contained in
193
+ <sources/>.
194
+ </if>
195
+ <else>
196
+ Then set <diagnostics/> to empty.
197
+ </else>
198
+
199
+ Then dispatch the sub-agents by invoking the following tool once per
200
+ *investigation*, emitting *all* invocations *in one single message*
201
+ so they run in *parallel*:
202
+
203
+ ```text
204
+ Agent(
205
+ description: "Specification Lint Investigation (<index/>/<count/>)",
206
+ subagent_type: "ase:ase-spec-lint",
207
+ prompt: "ASPECTS: <investigation-aspects/>\nFILES: <investigation-files/>\nCORPUS: <corpus/>\nMETA: <meta/>\nSCHEMA: <schema/>\nDIAGNOSTICS:\n<investigation-diagnostics/>",
208
+ run_in_background: false
209
+ )
210
+ ```
211
+
212
+ The *investigations* are determined as follows:
213
+
214
+ - <if condition="<file-aspects/> is not empty">
215
+ Partition <sources/>, preserving order, into at most *eight*
216
+ batches of roughly equal size (a single file yields a single
217
+ batch). Each batch is one *investigation* with
218
+ <investigation-aspects/> set to <file-aspects/>,
219
+ <investigation-files/> set to the files of the batch, and
220
+ <investigation-diagnostics/> set to those entries of
221
+ <diagnostics/> whose `file` is contained in the batch.
222
+ </if>
223
+
224
+ - <if condition="<model-aspects/> is not empty">
225
+ One additional *investigation* covers the entire model, with
226
+ <investigation-aspects/> set to <model-aspects/>,
227
+ <investigation-files/> set to *all* of <sources/>, and
228
+ <investigation-diagnostics/> set to empty.
229
+ </if>
230
+
231
+ Here every aspect list is comma-separated (without any spaces),
232
+ every file list is space-separated, <investigation-diagnostics/>
233
+ carries one line `- <file/>:<line/>:<column/>: <severity/>:
234
+ <message/>` per diagnostic (or the single line `(none)` if empty),
235
+ <index/> is the 1-based index of the investigation, and <count/> is
236
+ the total number of investigations, so that each parallel
237
+ invocation is distinguishable in the progress display.
238
+
239
+ Parse the result message of each `Agent` tool invocation as a JSON
240
+ array and concatenate all those arrays. Determine the *anchor* of
241
+ each problem as its `file` and `line` fields. Then *deduplicate* the
242
+ combined list: when two problems share the same anchor and
243
+ `aspect`, *silently drop* all but the first one (sub-agents may
244
+ have read overlapping *related* files for comprehension). Finally
245
+ sort the list by the anchor `file` and then numerically by the anchor
246
+ `line`, and set <problems/> to that list.
247
+
248
+ Then determine the *effective severity floor* <floor/>: define the
249
+ ordinal rank `LOW`=1, `MEDIUM`=2, `HIGH`=3.
250
+
251
+ <if condition="<getopt-option-severity/> is equal `AUTO`">
252
+ Set <floor>MEDIUM</floor> if <ase-project-boxing/> is equal `grey`
253
+ (grey boxing surfaces only *material* findings of severity `MEDIUM`
254
+ and above), and <floor>LOW</floor> otherwise.
255
+ </if>
256
+ <else>
257
+ Set <floor><getopt-option-severity/></floor>: an *explicitly* given
258
+ severity floor always *wins* over the boxing, both over the `grey`
259
+ floor and over the `black` skip.
260
+ </else>
261
+
262
+ Then *apply the effective severity floor* <floor/>: *Keep* a problem
263
+ in <problems/> if and only if its `severity` field is `ACCEPTED` *or*
264
+ `rank(severity)` is greater than or equal to `rank(<floor/>)`;
265
+ *silently drop* all other problems. With the floor `LOW`, all
266
+ problems are kept. `ACCEPTED` problems are *never* dropped.
267
+
268
+ Finally, sort the surviving problems in <problems/> by their
269
+ `severity` field from highest to lowest in the fixed order `HIGH`,
270
+ `MEDIUM`, `LOW`, `ACCEPTED`, so the subsequent reporting starts with
271
+ the most severe problem. Within the same severity, keep the
272
+ `file`/`line` order established above.
273
+
274
+ You *MUST* *NOT* output anything else in this STEP 1.
275
+
276
+ </step>
277
+
278
+ 2. <step id="STEP 2: Summary">
279
+
280
+ Use the following <template/> to output a summary of the detected
281
+ problems in <problems/> (if any were found), in the original aspect
282
+ ordering `S01 - XXX`...`S10 - XXX`.
283
+
284
+ <template>
285
+ <ase-tpl-bullet-secondary/> **LINT SUMMARY**:
286
+
287
+ <ase-tpl-bullet-signal/> **SX - XXX**: N issues
288
+ <ase-tpl-bullet-signal/> **SX - XXX**: N issues
289
+ [...]
290
+ </template>
291
+
292
+ Else, if no problems were found, use the following <template/> to
293
+ output the summary instead:
294
+
295
+ <template>
296
+ <ase-tpl-bullet-secondary/> **LINT SUMMARY**:
297
+
298
+ *(no problems detected)*
299
+ </template>
300
+
301
+ You *MUST* *NOT* output anything else in this STEP 2.
302
+
303
+ </step>
304
+
305
+ 3. <step id="STEP 3: Correction">
306
+
307
+ 1. *Mark this skill as the active edit-capable skill* so that the
308
+ ASE `pre-tool-use` hook auto-approves the subsequent `Edit`
309
+ invocations on *any* invocation path (slash command *or* `Skill`
310
+ tool). Call the `ase_state_set(key: "skill", val:
311
+ "ase-spec-lint", session: "<ase-session-id/>")` tool
312
+ from the `ase` MCP server. Then call the `ase_timestamp(format:
313
+ "yyyy-LL-dd HH:mm")` tool of the `ase` MCP server *once* to find
314
+ out the current time and store it in <timestamp-modified/>, and
315
+ set <touched/> to empty (the list of files changed by an
316
+ applied correction). Do not output anything in this substep.
317
+
318
+ *Critical safety invariant*: the marker set here grants `Edit`
319
+ auto-approval and *MUST* be cleared again (substep 4 below)
320
+ *before* this skill yields control, *regardless* of how the
321
+ iteration in substep 2 ends - whether it completes normally,
322
+ is aborted early (e.g. an `Edit` failure, an unparseable value,
323
+ or any other unexpected condition), or is otherwise interrupted.
324
+ If you ever stop or bail out of substep 2 early, you *MUST*
325
+ still perform substep 4 first. Never leave this marker active
326
+ for a later, unrelated `Edit`.
327
+
328
+ 2. Set <total/> to the number of problems in <problems/> and
329
+ <index/> to `0`. Then iterate over all problems:
330
+
331
+ <for items="<problems/>">
332
+
333
+ 1. Increment <index/> by one (the 1-based position of the
334
+ current <item/> within <problems/>).
335
+ Set <aspect/> to the `aspect` field of <item/>.
336
+ Set <severity/> to the `severity` field of <item/>.
337
+ Set <description/> to the `description` field of <item/>.
338
+ Set <anchor/> to `` `<anchor-file/>`:<anchor-line/> ``, where
339
+ <anchor-file/> is the `file` and <anchor-line/> the `line` field of <item/>.
340
+ Set <change-set/> to the `change-set` field of <item/>.
341
+ Set <gap/> to `true` if <aspect/> starts with `S09` or
342
+ `S10` (a *gap-filling* best-guess correction), and to
343
+ `false` otherwise.
344
+
345
+ 2. Set <context></context> (set to empty).
346
+ Set <diff></diff> (set to empty).
347
+ Set <diff-condensed></diff-condensed> (set to empty).
348
+
349
+ 3. Iterate over the change set:
350
+
351
+ <for items="<change-set/>">
352
+
353
+ 1. Set <file/> to the `file` field of <item/>.
354
+ Set <change-hunks/> to the `change-hunks` field of <item/>.
355
+
356
+ Unless <condensed/> is equal `true` (where the
357
+ full unified diff is suppressed and no context lines are
358
+ rendered at all), *silently* read the current content of
359
+ <file/> with the `Read` tool - reusing the content read
360
+ for the same <file/> earlier in this iteration, unless
361
+ an `Edit` was applied to it in between - and set
362
+ <file-lines/> to its lines, *stripped* of the
363
+ line-number prefixes the tool adds. Set <file-lines/>
364
+ to empty if the file cannot be read.
365
+
366
+ This content is the *authoritative* source of the
367
+ context lines of substep 2 below, so the rendered diff
368
+ shows real context even when a sub-agent supplied none.
369
+
370
+ Unless <condensed/> is equal `true` (where the
371
+ full unified diff is suppressed and this per-file header is
372
+ unused), set <diff-file/> to the following <template/>:
373
+
374
+ <template>
375
+ --- <file/> (original)
376
+ +++ <file/> (corrected)
377
+ </template>
378
+
379
+ 2. Iterate over the change hunks.
380
+
381
+ <for items="<change-hunks/>">
382
+
383
+ 1. Set <line/> to the `line` field of <item/>.
384
+ Set <context-before/> to the `context_before` field of <item/>.
385
+ Set <old-text/> to the `old_text` field of <item/>.
386
+ Set <new-text/> to the `new_text` field of <item/>.
387
+ Set <context-after/> to the `context_after` field of <item/>.
388
+
389
+ Then *normalize* the hunk to its *minimal* form, so
390
+ that the proposed diff shows exactly the lines the
391
+ later `Edit` will actually change: while the *first*
392
+ line of <old-text/> is identical to the *first* line
393
+ of <new-text/>, *move* that line from both to the
394
+ end of <context-before/> and increment <line/> by
395
+ one; likewise, while the *last* line of <old-text/>
396
+ is identical to the *last* line of <new-text/>,
397
+ *move* that line from both to the front of
398
+ <context-after/>. Finally, *trim* <context-before/>
399
+ to its *last* two lines and <context-after/> to its
400
+ *first* two lines.
401
+
402
+ Then, whenever <file-lines/> is non-empty,
403
+ *re-derive* both context parts from it, *overriding*
404
+ the sub-agent supplied values: set <context-before/>
405
+ to the *up to two* lines of <file-lines/> directly
406
+ *before* line <line/> (empty if <line/> is `1`) and
407
+ <context-after/> to the *up to two* lines of
408
+ <file-lines/> starting at line (<line/> + <n/>),
409
+ where <n/> is the number of lines in <old-text/>
410
+ (empty if that line is beyond the end of the file).
411
+ Keep the sub-agent supplied values only when
412
+ <file-lines/> is empty.
413
+
414
+ 2. *Skip* this substep entirely when <condensed/>
415
+ is equal `true` - the full unified diff is suppressed
416
+ there, so none of the <hunk-body/>, <old-count/>,
417
+ <new-count/>, <old-start/>, or <new-start/> values
418
+ below are consumed (substep 4 builds only the condensed
419
+ one-liner instead).
420
+
421
+ Otherwise, determine the hunk *body* as an ordered list
422
+ of lines, each carrying a one-character prefix (` ` for
423
+ context, `-` for old-side, `+` for new-side). Build it
424
+ by concatenating, in order and *skipping any part that
425
+ is empty*:
426
+
427
+ - one ` `-prefixed line for *each* line of
428
+ <context-before/> (if non-empty),
429
+ - one `-`-prefixed line for *each* line of <old-text/>
430
+ (if non-empty; split <old-text/> on newlines),
431
+ - one `+`-prefixed line for *each* line of <new-text/>
432
+ (if non-empty; split <new-text/> on newlines),
433
+ - one ` `-prefixed line for *each* line of
434
+ <context-after/> (if non-empty).
435
+
436
+ Set <hunk-body/> to those prefixed lines joined by
437
+ newlines.
438
+
439
+ Set <old-count/> to the number of old-side hunk lines,
440
+ i.e., the combined line count of <context-before/>,
441
+ <old-text/>, and <context-after/> (each empty part
442
+ counts as `0`).
443
+ Set <new-count/> to the number of new-side hunk lines,
444
+ i.e., the combined line count of <context-before/>,
445
+ <new-text/>, and <context-after/> (each empty part
446
+ counts as `0`).
447
+
448
+ Set <old-start/> to the 1-based line number of the
449
+ *first* old-side hunk line: if <context-before/> is
450
+ non-empty, that is the line of its *first* context
451
+ line, i.e. <line/> minus the number of lines in
452
+ <context-before/>; otherwise it is <line/> itself
453
+ (the first line of <old-text/>). For a hunk that
454
+ *only inserts* new lines (empty <old-text/> *and*
455
+ empty context), set it to the
456
+ line *before* which the insertion happens, clamped to a
457
+ minimum of `0`, so a top-of-file insertion yields
458
+ `@@ -0,0 ... @@`.
459
+ Set <new-start/> to the same value as <old-start/>, but
460
+ clamped to a minimum of `1` whenever <new-count/> is
461
+ greater than `0` (the corrected side then has a real
462
+ first line).
463
+
464
+ 3. If <context/> is not empty, set
465
+ <context><context/>,</context> (append a comma).
466
+ Then append the following <template/> to <context/>:
467
+
468
+ <template>`<file/>`:<line/></template>
469
+
470
+ 4. <if condition="<condensed/> is equal `true`">
471
+
472
+ The full unified diff is *suppressed* in a condensed
473
+ report (see substep 5 below), so *skip* the full-diff append
474
+ and instead build only a *condensed* one-line
475
+ representation of this hunk: determine <old-snippet/>
476
+ as the *single-line* collapse of <old-text/> (join its
477
+ lines with ` ⏎ `, or `∅` when <old-text/> is empty for
478
+ a pure insertion) and <new-snippet/> as the same
479
+ collapse of <new-text/> (or `∅` when empty for a pure
480
+ deletion). Then append the following <template/> to
481
+ <diff-condensed/> as a new line:
482
+
483
+ <template>
484
+ <ase-tpl-bullet-signal/> `<file/>`:<line/>: `<old-snippet/>` → `<new-snippet/>`
485
+ </template>
486
+
487
+ </if>
488
+ <else>
489
+
490
+ Append the following <template/> to <diff-file/>,
491
+ emitting <hunk-body/> verbatim (one already-prefixed
492
+ line per line, with no extra blank or space-only lines):
493
+
494
+ <template>
495
+ @@ -<old-start/>,<old-count/> +<new-start/>,<new-count/> @@
496
+ <hunk-body/>
497
+ </template>
498
+
499
+ </else>
500
+
501
+ </for>
502
+
503
+ 3. Unless <condensed/> is equal `true` (where
504
+ <diff-file/> is unused), append <diff-file/> to <diff/>.
505
+
506
+ </for>
507
+
508
+ If <context/> is still empty (an empty <change-set/>), set
509
+ <context><anchor/></context>.
510
+
511
+ 4. Report the problem with the following <template/>:
512
+
513
+ <template>
514
+ <ase-tpl-bullet-signal/> [<index/>/<total/>]: **<aspect/> PROBLEM** (`<severity/>`): <context/>
515
+
516
+ <description/>
517
+
518
+ </template>
519
+
520
+ 5. <if condition="<change-set/> is empty">
521
+
522
+ No correction could be derived for this problem, so report
523
+ it with the following <template/>, set <result>REJECT</result>,
524
+ and *skip* the remaining substep 6:
525
+
526
+ <template>
527
+ <ase-tpl-bullet-normal/> **<aspect/> SOLUTION**:
528
+
529
+ *(no correction derivable -- manual action required)*
530
+
531
+ </template>
532
+
533
+ </if>
534
+ <elseif condition="<getopt-option-auto/> is not equal `true` or <gap/> is equal `true`">
535
+
536
+ <if condition="<condensed/> is equal `true`">
537
+
538
+ The project source artifacts are classified as a *grey box* (or
539
+ *black box*), so the user does *not* want the full artifact
540
+ internals surfaced:
541
+ *suppress* the full unified diff and instead show only the
542
+ *condensed* one-line-per-hunk representation. Report the
543
+ solution with the following <template/>:
544
+
545
+ <template>
546
+ <ase-tpl-bullet-normal/> **<aspect/> SOLUTION**:
547
+
548
+ <diff-condensed/>
549
+
550
+ </template>
551
+
552
+ </if>
553
+ <else>
554
+
555
+ Report the solution with the following <template/>:
556
+
557
+ <template>
558
+ <ase-tpl-bullet-normal/> **<aspect/> SOLUTION**:
559
+
560
+ ```diff
561
+ <diff/>
562
+ ```
563
+
564
+ </template>
565
+
566
+ </else>
567
+
568
+ </elseif>
569
+ <else>
570
+
571
+ Report the solution with the following <template/>:
572
+
573
+ <template>
574
+ <ase-tpl-bullet-normal/> **<aspect/> SOLUTION**:
575
+
576
+ *(corresponding change automatically applied)*
577
+
578
+ </template>
579
+
580
+ </else>
581
+
582
+ 6. <if condition="<getopt-option-auto/> is equal `true` and <gap/> is equal `true`">
583
+
584
+ A *gap-filling* correction carries *best-guess* content,
585
+ which is *never* applied unattended. Report this with the
586
+ following <template/> and set <result>REJECT</result>:
587
+
588
+ <template>
589
+ *(best-guess correction not applied under `--auto` -- re-run without `--auto` to review it)*
590
+
591
+ </template>
592
+
593
+ </if>
594
+ <elseif condition="<getopt-option-auto/> is not equal `true`">
595
+
596
+ In the following, you *MUST* *NOT* use your built-in
597
+ <user-dialog-tool/> tool! Instead, you *MUST* just show a
598
+ custom dialog according to the expanded `custom-dialog`
599
+ definition. You *MUST* closely follow this definition:
600
+
601
+ <expand name="custom-dialog" arg1="--other">
602
+ CORRECTION: How would you like to proceed with this proposed correction?
603
+ ACCEPT: Apply this proposed correction.
604
+ REJECT: Skip this proposed correction.
605
+ </expand>
606
+
607
+ </elseif>
608
+ <else>
609
+
610
+ Set <result>ACCEPT</result>.
611
+ You *MUST* *NOT* output anything else in this sub-step 6.
612
+
613
+ </else>
614
+
615
+ 7. Check <result/> and dispatch accordingly:
616
+
617
+ - <if condition="<result/> is 'ACCEPT'">
618
+ Invoke the `Edit` tool to apply the changes exactly
619
+ as given by the hunks of the current <change-set/>
620
+ (rendered as <diff/>, unless suppressed in a condensed
621
+ report). The operation will be auto-approved by the ASE
622
+ `pre-tool-use` hook (which tracks the active skill),
623
+ so *no* interactive permission prompt will appear.
624
+ After applying the changes, add every `file` of
625
+ <change-set/> to <touched/> (dropping duplicates) and
626
+ just continue with the next <item/>.
627
+ </if>
628
+
629
+ - <if condition="<result/> starts with 'OTHER'">
630
+ Generate a *new* proposal for the *same* <item/>
631
+ (incorporating the user's free-text hint from <result/> if
632
+ provided via the "OTHER" prefix). *Reassign* <description/>
633
+ and <change-set/> to reflect this refined proposal (each
634
+ change-hunk's `old_text` stays anchored to the existing
635
+ text at its `file`:`line`; `new_text` carries the
636
+ refinement), keeping the conformance to the **SpecBook**
637
+ format contract and the schema, so that the substep 2/3
638
+ rebuild renders the new <diff/> and any `Edit` applies the
639
+ new proposal rather than the original. Then loop back to
640
+ substep 2 of this iteration. There is *no* cap on
641
+ refinement rounds - keep refining until the user picks
642
+ `ACCEPT` or `REJECT`.
643
+ </if>
644
+
645
+ - <if condition="
646
+ <result/> is 'REJECT' or
647
+ <result/> is 'CANCEL' or
648
+ <result/> starts with 'ERROR'
649
+ ">
650
+ Skip this <item/> without any `Edit` call and continue
651
+ with the next <item/>.
652
+ </if>
653
+
654
+ </for>
655
+
656
+ 3. For every file in <touched/> which carries a `Modified:
657
+ <timestamp-modified-old/>` frontmatter line, invoke the `Edit`
658
+ tool to replace <timestamp-modified-old/> with
659
+ <timestamp-modified/>, keeping the spacing behind `Modified:`
660
+ unchanged. Do not output anything in this substep.
661
+
662
+ 4. *Clear the active edit-capable skill marker* now that all `Edit`
663
+ invocations are done, so a later unrelated `Edit` is *not*
664
+ auto-approved. Call the `ase_state_delete(key: "skill",
665
+ session: "<ase-session-id/>")` tool from the `ase` MCP
666
+ server. Do not output anything in this substep.
667
+
668
+ 5. You *MUST* *NOT* output any further additional explanations or
669
+ summaries at the end of this skill processing, except for the
670
+ following final <template/>:
671
+
672
+ <template>
673
+ <ase-tpl-bullet-secondary/> **LINT FINISHED**
674
+ </template>
675
+
676
+ 6. Finally, give the closing hints by expanding the following
677
+ (which, depending on the configured <ase-guidance-level/>, may
678
+ each expand into nothing and hence emit no output at all):
679
+
680
+ <if condition="at least one problem in <problems/> was left uncorrected">
681
+ <ase-tpl-hint level="normal">
682
+ For problems whose correction demands more than a local edit, use `/ase-spec-edit -g` to resolve them through a grilled one-shot specification edit.
683
+ </ase-tpl-hint>
684
+ </if>
685
+
686
+ <if condition="<getopt-option-auto/> is not equal `true`">
687
+ <ase-tpl-hint level="verbose">
688
+ Use `/ase-spec-lint --auto` to apply all non-gap corrections unattended, `--severity` to raise the reporting floor, `--include`/`--exclude` to narrow the checked aspects, and `--staged`/`--unstaged` to lint only the changed specification files.
689
+ </ase-tpl-hint>
690
+ </if>
691
+
692
+ </step>
693
+
694
+ </flow>
695
+