@1aboveio/skills 1.0.14 → 1.0.15

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 (86) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/.codex-plugin/resources.json +147 -147
  3. package/package.json +4 -4
  4. package/skills/app-dev/airflow/SKILL.md +1 -1
  5. package/skills/app-dev/android-development/SKILL.md +3 -2
  6. package/skills/app-dev/android-development/references/diagnosis.md +5 -0
  7. package/skills/app-dev/android-development/references/feature-work.md +15 -0
  8. package/skills/app-dev/android-development/references/init.md +26 -4
  9. package/skills/app-dev/android-development/scripts/init.mjs +105 -8
  10. package/skills/app-dev/app-debug/SKILL.md +1 -1
  11. package/skills/app-dev/better-auth/SKILL.md +1 -1
  12. package/skills/app-dev/data-catalog/SKILL.md +53 -16
  13. package/skills/app-dev/data-catalog/scripts/persist-conventions-core.mjs +231 -21
  14. package/skills/app-dev/data-catalog/scripts/persist-conventions.mjs +12 -1
  15. package/skills/app-dev/data-quality/SKILL.md +1 -1
  16. package/skills/app-dev/ios-foundation/SKILL.md +1 -1
  17. package/skills/app-dev/monorepo/SKILL.md +1 -1
  18. package/skills/app-dev/nextjs-fullstack/SKILL.md +1 -1
  19. package/skills/app-dev/prisma-setup/SKILL.md +1 -1
  20. package/skills/app-dev/pyspark/SKILL.md +1 -1
  21. package/skills/app-dev/python-backend/SKILL.md +1 -1
  22. package/skills/app-dev/shadcn/SKILL.md +1 -1
  23. package/skills/app-dev/zod-v4/SKILL.md +1 -1
  24. package/skills/cicd/cloud-build/SKILL.md +1 -1
  25. package/skills/cicd/cloud-debug/SKILL.md +1 -1
  26. package/skills/cicd/cloud-deploy/SKILL.md +1 -1
  27. package/skills/cicd/docker/SKILL.md +1 -1
  28. package/skills/cicd/github-actions/SKILL.md +1 -1
  29. package/skills/cicd/github-flow/SKILL.md +10 -1
  30. package/skills/cicd/github-flow/scripts/persist-conventions-core.mjs +231 -21
  31. package/skills/cicd/github-flow/scripts/persist-conventions.mjs +18 -1
  32. package/skills/cicd/google-cloud/SKILL.md +1 -1
  33. package/skills/cicd/mergify/SKILL.md +1 -1
  34. package/skills/cicd/podman/SKILL.md +1 -1
  35. package/skills/content/article-review/SKILL.md +1 -1
  36. package/skills/content/article-to-image/SKILL.md +1 -1
  37. package/skills/content/flowchart-svg/SKILL.md +1 -1
  38. package/skills/content/image-gen/SKILL.md +1 -1
  39. package/skills/content/mermaid/SKILL.md +1 -1
  40. package/skills/content/wechat-article-writer/SKILL.md +1 -1
  41. package/skills/content/wechat-publisher/SKILL.md +1 -1
  42. package/skills/content/wechat-search/SKILL.md +1 -1
  43. package/skills/content/xai-search/SKILL.md +1 -1
  44. package/skills/core/distill-writing/SKILL.md +7 -1
  45. package/skills/core/doc-to-md/SKILL.md +1 -1
  46. package/skills/core/editorial-review/SKILL.md +1 -1
  47. package/skills/core/house-style/SKILL.md +1 -1
  48. package/skills/core/house-style/references/persistence.md +8 -3
  49. package/skills/core/house-style/scripts/init-guidance.mjs +1 -1
  50. package/skills/core/plain-language/SKILL.md +1 -1
  51. package/skills/core/polish-cn/SKILL.md +1 -1
  52. package/skills/core/reg-parser/SKILL.md +1 -1
  53. package/skills/core/terminology/SKILL.md +1 -1
  54. package/skills/core/terminology/references/init.md +11 -0
  55. package/skills/core/write-doc/SKILL.md +1 -1
  56. package/skills/core/write-report/SKILL.md +1 -1
  57. package/skills/engineering/better-review/SKILL.md +1 -1
  58. package/skills/engineering/e2e-test/SKILL.md +1 -1
  59. package/skills/engineering/engineering/SKILL.md +19 -4
  60. package/skills/engineering/engineering/references/init-scope.md +5 -2
  61. package/skills/engineering/engineering/references/scope-management.md +4 -2
  62. package/skills/engineering/engineering/scripts/init.mjs +34 -9
  63. package/skills/engineering/engineering/scripts/persist-conventions-core.mjs +231 -21
  64. package/skills/engineering/engineering/scripts/persist-conventions.mjs +48 -21
  65. package/skills/engineering/engineering-runtime/SKILL.md +1 -1
  66. package/skills/engineering/engineering-runtime/coherence/workflow.json +13 -13
  67. package/skills/engineering/ensure-coverage/SKILL.md +1 -1
  68. package/skills/engineering/golden-path/SKILL.md +1 -1
  69. package/skills/engineering/harness-runtime/SKILL.md +1 -1
  70. package/skills/engineering/resolve-issues/SKILL.md +1 -1
  71. package/skills/engineering/resolve-issues/references/review.md +27 -4
  72. package/skills/engineering/resolve-release/SKILL.md +1 -1
  73. package/skills/engineering/rush-issues/SKILL.md +1 -1
  74. package/skills/engineering/rush-release/SKILL.md +1 -1
  75. package/skills/engineering/test-quality/SKILL.md +3 -1
  76. package/skills/engineering/test-quality/scripts/persist-conventions-core.mjs +231 -21
  77. package/skills/engineering/test-quality/scripts/persist-conventions.mjs +13 -1
  78. package/skills/risk-compliance/compliance-audit/SKILL.md +1 -1
  79. package/skills/risk-compliance/contract-compare/SKILL.md +1 -1
  80. package/skills/risk-compliance/contract-review/SKILL.md +1 -1
  81. package/skills/risk-compliance/doc-authenticity/SKILL.md +1 -1
  82. package/skills/risk-compliance/fraud-detection/SKILL.md +1 -1
  83. package/skills/risk-compliance/payment-analysis/SKILL.md +1 -1
  84. package/skills/risk-compliance/portfolio-payment-analysis/SKILL.md +1 -1
  85. package/skills/risk-compliance/similar-domain/SKILL.md +1 -1
  86. package/skills/risk-compliance/tld-detection/SKILL.md +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1aboveio/skills",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "description": "Every 1aboveio skill package in one: install once, then choose which packages Pi loads with npx @1aboveio/skills select.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -28,8 +28,8 @@
28
28
  "nativeCodex": {
29
29
  "schemaVersion": 1,
30
30
  "metadataPath": ".codex-plugin/resources.json",
31
- "metadataDigest": "5a89642fb1549c82420cbba78a75eaff01509d14cbf556480130a688e7ca1efe",
32
- "releaseIdentity": "1d0affb17cf284c052ad00266f7d5ea31a7f7f9bb7f8ae6435b200835710e123"
31
+ "metadataDigest": "2bdb58dba1de073baf79efe2c5118ad75c996710344a3cde581976921c1b23ec",
32
+ "releaseIdentity": "a8975fa459ebba2a3e2661d861bdb9d43c072c1b01adaf41def9a93523782800"
33
33
  },
34
34
  "pi": {
35
35
  "skills": [
@@ -260,7 +260,7 @@
260
260
  ]
261
261
  }
262
262
  ],
263
- "digest": "ffe17fe4c3bfd5076e842358a22f58b116f060bd779f788f4ba3fd7b814f8b0e"
263
+ "digest": "6ad0dafe4a400162776b1bf6d7c9e5ab31bf37a86d18b035fcadc4c11d06f799"
264
264
  },
265
265
  "publishConfig": {
266
266
  "registry": "https://registry.npmjs.org/",
@@ -2,7 +2,7 @@
2
2
  name: airflow
3
3
  description: Airflow DAG architecture and conventions. Use when designing, writing, reviewing, testing, or debugging Airflow DAGs and tasks, including TaskGroups, data intervals, timezone-aware date parameters, CLI validation, environment-based scheduling, and pytest integrity tests.
4
4
  user-invocable: true
5
- release-version: 0.46.0
5
+ release-version: 0.47.0
6
6
  ---
7
7
  **Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
8
8
  # Airflow DAG Development Patterns
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: android-development
3
3
  description: "Prove and debug Expo / React Native apps on an owned Android emulator. Use for Android startup/rendering failures, Metro or ADB problems, UiAutomator/harness failures, APK builds, SDK/NDK/JDK workspace setup, native journey validation, and choosing Kotlin/Compose versus React Native for Android flows. Reproduce failed Android CI checkpoints off CI before fixing and redispatching. Standalone invocation offers Project or Session; init persists repo conventions. NOT for workflow YAML, CI speed or runners (github-actions), browser tests (e2e-test), iOS (ios-foundation), plain Jest tests, or signing/store release."
4
- release-version: 0.46.0
4
+ release-version: 0.47.0
5
5
  ---
6
6
  **Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
7
7
  # Android development
@@ -18,7 +18,8 @@ Project rules and required CI remain binding; this skill does not add acceptance
18
18
  leaves files unchanged. Do not offer global persistence.
19
19
  - **Project**, `/android-development init`, or an explicit request to save repo conventions:
20
20
  follow [initialization](references/init.md). Preview, then apply the authorized missing
21
- `CONTRIBUTING.md` section and `AGENTS.md` pointer. No second approval is needed unless
21
+ `CONTRIBUTING.md` section and `AGENTS.md` task-entry loader and guide pointer. Check
22
+ the skill loader separately from an existing guide link. No second approval is needed unless
22
23
  existing policy conflicts. Initialization is not a policy refresh or delivery permission.
23
24
  - **Session:** apply this workflow without writing guidance or agent settings. Retain the
24
25
  choice through reload/compaction in this session; a new session makes its own choice.
@@ -103,6 +103,11 @@ worker's "running" status does not impose a timeout or demonstrate progress. The
103
103
  whole journey. Set a positive value for unattended runs; its backward-compatible
104
104
  zero default disables that deadline. Allow time for the owner to finish cleanup.
105
105
 
106
+ Use the harness's background-task mechanism when a journey can exceed the foreground
107
+ command limit. Budget for the selected journey and owned cleanup; feedback-time targets
108
+ are not kill deadlines. Continue independent work and inspect the terminal result when
109
+ notified, rather than waiting or polling in the foreground. Do not add another watcher.
110
+
106
111
  For a hung test, identify the actual outstanding command and last completed assertion.
107
112
  If the test waits for a child to exit, check whether its input actually requires exit.
108
113
  Reduce that question to a bounded host test before launching another emulator.
@@ -30,6 +30,21 @@ Native/build-input changes invalidate that reuse; unknown compatibility calls fo
30
30
  rebuild, not an assertion that the old APK is current. Do not run `expo prebuild` routinely
31
31
  against tracked native projects.
32
32
 
33
+ ### Check journey admission before reserving devices
34
+
35
+ Before an expensive native journey, verify the exact selected case and supported arguments
36
+ against the existing runner, required installation/resource owners, effective test flags,
37
+ and device settings. Use existing help, parser tests or preflight commands when available;
38
+ do not invent a selector or build another preflight framework. Missing admission support
39
+ is a harness limitation to resolve, not a reason to allocate devices and discover it later.
40
+ Continue independent source tests while device prerequisites are checked.
41
+
42
+ Apply lifecycle-changing display size, density and other required presentation settings
43
+ before app launch when the journey relies on retaining that Activity or observation scope.
44
+ Read back the effective settings through the existing owner. A later setting change may
45
+ recreate the Activity; do not hide scope retirement with registration retries or relaxed
46
+ identity checks. Keep this check scoped to the selected case, not every possible device cell.
47
+
33
48
  ### Verify command expansion
34
49
 
35
50
  Before adopting a native fast path, trace its package script, wrapper, Gradle tasks and
@@ -14,8 +14,9 @@ node {baseDir}/scripts/init.mjs [--repo-root <dir>] [--write]
14
14
  - `--write` applies the plan. `--repo-root` selects the project; without it the nearest Git root
15
15
  from the current directory is used, falling back to the current directory when there is none.
16
16
  - `--help` prints the usage line.
17
- - An unknown argument, an unresolvable root, a malformed marker or an unsafe target exits
18
- non-zero with a message and no writes.
17
+ - An unknown argument, an unresolvable root, a malformed marker, an unsafe target or a file that
18
+ ends inside an unclosed fenced code block or HTML comment exits non-zero with a message and no
19
+ writes, in preview and with `--write` alike.
19
20
 
20
21
  ## Files and ownership
21
22
 
@@ -27,19 +28,35 @@ to a newly created Android section; report unresolved commands instead of guessi
27
28
  | File | Write |
28
29
  | --- | --- |
29
30
  | `CONTRIBUTING.md` | The `## Android development` section, wrapped in `<!-- conventions:android:start -->` / `<!-- conventions:android:end -->`, with `references/android-conventions.md` as its body. |
30
- | `AGENTS.md` | A short pointer to the selected `CONTRIBUTING.md`, added only when no correct loader link exists yet. |
31
+ | `AGENTS.md` | An `Android task entry` skill-loading block between `conventions:android-task-entry` markers, plus a pointer to the selected `CONTRIBUTING.md` when missing. Check these independently: a contributor-guide link alone is not a skill loader. |
31
32
 
32
33
  Each file is created only when it is absent. The helper never edits `CLAUDE.md`, never writes into
33
34
  a parent project, a home directory or global agent configuration, and never reaches outside the
34
35
  selected root.
35
36
 
36
37
  After applying authorized additions, verify that each existing supported agent entrypoint
37
- reaches the Android section, directly or through its instruction chain. The helper configures
38
+ reaches both the skill task-entry instruction and the Android contributor-guide section,
39
+ directly or through its instruction chain. A direct link to `CONTRIBUTING.md` does not
40
+ establish that the entrypoint loads the skill rule in `AGENTS.md`. The helper configures
38
41
  `AGENTS.md`; it does not certify an independent `CLAUDE.md` loader. Preserve existing chains
39
42
  and do not edit that entrypoint under this init permission. If one does not reach the guide,
40
43
  report the files configured and the unresolved loading path as partial setup. Obtain separate
41
44
  authorization for any additional loader edit instead of silently claiming complete setup.
42
45
 
46
+ The task-entry block requires reading and applying the installed `android-development`
47
+ skill before Android-specific commands, during issue-unit preflight, in delegated Android
48
+ workers, and again after compaction when its rules are lost. Keep commands and validation
49
+ policy in `CONTRIBUTING.md`, not this loader. An existing direct read/load-before rule or
50
+ managed block is preserved. A managed block is preserved only while it still holds an active
51
+ loader: an empty block, or one whose only loader is commented out or written as a code example,
52
+ is refused rather than counted as configured. A direct `do not load`-style rule that conflicts
53
+ with the loader is refused too, wherever it sits in the file. Fenced code, indented code, HTML
54
+ comments and inline code are documentation, so an example never counts as an active loader or as
55
+ a conflict. An unrecognized `Android task entry` section requires manual reconciliation rather
56
+ than a competing block. Inspect existing rules for conflicts before applying the helper; it
57
+ cannot interpret every natural-language policy. This missing-loader addition is part of explicit
58
+ init even in previously initialized repos, not an automatic update.
59
+
43
60
  ## Resolve the repo command map
44
61
 
45
62
  The initializer, not the deterministic writer, inspects existing scripts and guidance.
@@ -81,6 +98,11 @@ Existing guidance wins over the template:
81
98
  - Refuse a mutation of a multiply hard-linked file or of an alias to the protected
82
99
  `CLAUDE.md` entrypoint. This includes a shared AGENTS/CLAUDE target: preserve it and
83
100
  report the boundary rather than silently granting a new write permission.
101
+ - Refuse an addition to a file that ends inside an unclosed fenced code block or HTML comment.
102
+ Appended guidance would land inside that construct, be inactive, and be appended again on
103
+ every run. The helper never closes it for you: preserve the manual text, repair the fence or
104
+ comment, and rerun. A file that needs no addition is reported unchanged, so an
105
+ already-configured project behind such a construct is not blocked.
84
106
  - An existing pointer is reused only when its link resolves to the selected `CONTRIBUTING.md`,
85
107
  and a new pointer is written relative to the real location of `AGENTS.md`. A link to some other
86
108
  file, such as a nested package guide, does not count as this project's loader.
@@ -7,6 +7,14 @@ import { fileURLToPath, pathToFileURL } from 'node:url'
7
7
 
8
8
  const sectionTitle = 'Android development'
9
9
  const sectionId = 'android'
10
+ const taskEntryTitle = 'Android task entry'
11
+ const taskEntryBody = `## ${taskEntryTitle}
12
+
13
+ For Android implementation, runtime debugging, native builds, or device validation,
14
+ read and apply the installed \`android-development\` skill before choosing
15
+ Android-specific commands. In issue workflows, load it during unit preflight.
16
+ Delegated Android workers must load it too. After compaction, reload it if its
17
+ instructions are no longer in context.`
10
18
  const usage = 'node init.mjs [--repo-root <dir>] [--write]'
11
19
 
12
20
  function parseArgs(argv) {
@@ -174,7 +182,7 @@ function stripHtmlComments(line, depth = 0) {
174
182
 
175
183
  // Markdown-aware view: inactive lines are fenced code, indented code or HTML comments.
176
184
  // Inline code and HTML comments are blanked from active text so examples never count.
177
- function markdownView(current) {
185
+ function scanMarkdown(current) {
178
186
  const lines = []
179
187
  let fence = null
180
188
  let commentDepth = 0
@@ -217,10 +225,63 @@ function markdownView(current) {
217
225
  previousBlank = blank
218
226
  lines.push({ raw: line, text: active ? text : '', active, comments })
219
227
  }
220
- return lines
228
+ // An open fence or comment at the end of the file would swallow anything appended after it.
229
+ return { lines, fence, commentDepth }
230
+ }
231
+
232
+ function markdownView(current) {
233
+ return scanMarkdown(current).lines
234
+ }
235
+
236
+ // End of the paragraph starting at `start`; a span never pairs across a blank line.
237
+ function paragraphEnd(text, start) {
238
+ const blank = /\n[ \t]*\n/g
239
+ blank.lastIndex = start
240
+ const match = blank.exec(text)
241
+ return match ? match.index : text.length
242
+ }
243
+
244
+ // Marks inline code spans so a documented example is never read as a project rule.
245
+ // Runs of equal length pair up inside one paragraph; an unmatched run is literal text, so it
246
+ // never consumes a later rule. The rule text itself stays readable, only its span is marked.
247
+ function inlineCodeMask(text) {
248
+ const mask = new Uint8Array(text.length)
249
+ const runs = [...text.matchAll(/`+/g)]
250
+ let index = 0
251
+ while (index < runs.length) {
252
+ const opening = runs[index]
253
+ const limit = paragraphEnd(text, opening.index)
254
+ let closing = index + 1
255
+ while (closing < runs.length && runs[closing].index < limit
256
+ && runs[closing][0].length !== opening[0].length) closing++
257
+ if (closing === runs.length || runs[closing].index >= limit) {
258
+ index += 1
259
+ continue
260
+ }
261
+ mask.fill(1, opening.index, runs[closing].index + runs[closing][0].length)
262
+ index = closing + 1
263
+ }
264
+ return mask
221
265
  }
222
266
 
223
- function append(current, body) {
267
+ // Only a match that starts outside inline code is an instruction rather than an example.
268
+ // The rule itself keeps its text, because the skill name is normally written as code.
269
+ function matchesOutsideInlineCode(text, pattern) {
270
+ const flags = pattern.flags.includes('g') ? pattern.flags : `${pattern.flags}g`
271
+ const global = new RegExp(pattern.source, flags)
272
+ const mask = inlineCodeMask(text)
273
+ for (const match of text.matchAll(global)) {
274
+ if (!mask[match.index]) return true
275
+ }
276
+ return false
277
+ }
278
+
279
+ function append(current, body, name) {
280
+ const { fence, commentDepth } = scanMarkdown(current)
281
+ if (fence || commentDepth) {
282
+ const construct = fence ? 'an unclosed fenced code block' : 'an unclosed HTML comment'
283
+ throw new Error(`${name} ends inside ${construct}; appended Android guidance would be inactive and appended again on every run. Close it and rerun init; nothing was changed`)
284
+ }
224
285
  const separator = current.endsWith('\n\n') ? '' : current.endsWith('\n') ? '\n' : '\n\n'
225
286
  return `${current}${separator}${body.trim()}\n`
226
287
  }
@@ -258,7 +319,7 @@ function countMarkers(lines, start, end) {
258
319
  return { starts, ends }
259
320
  }
260
321
 
261
- function preserveOrAdd(current, title, id, body) {
322
+ function preserveOrAdd(current, name, title, id, body) {
262
323
  const start = `<!-- conventions:${id}:start -->`
263
324
  const end = `<!-- conventions:${id}:end -->`
264
325
  const { starts, ends } = countMarkers(markdownView(current), start, end)
@@ -266,7 +327,7 @@ function preserveOrAdd(current, title, id, body) {
266
327
  throw new Error(`malformed ${title} section markers; preserve and repair existing guidance first`)
267
328
  }
268
329
  if (starts.length || hasHeading(current, title)) return current
269
- return append(current, `${start}\n${body}\n${end}`)
330
+ return append(current, `${start}\n${body}\n${end}`, name)
270
331
  }
271
332
 
272
333
  function linkFrom(from, to) {
@@ -295,6 +356,42 @@ function hasLoader(current, from, to) {
295
356
  return false
296
357
  }
297
358
 
359
+ function addTaskEntry(current, name) {
360
+ const start = '<!-- conventions:android-task-entry:start -->'
361
+ const end = '<!-- conventions:android-task-entry:end -->'
362
+ const lines = markdownView(current)
363
+ const { starts, ends } = countMarkers(lines, start, end)
364
+ if (starts.length !== ends.length || starts.length > 1 || (starts.length && starts[0] > ends[0])) {
365
+ throw new Error('malformed Android task entry markers; preserve and repair existing guidance first')
366
+ }
367
+ // Only active prose can hold a rule: fenced code, indented code, HTML comments, inline code
368
+ // and fenced examples are documentation. A rule keeps its own inline code, so the skill name
369
+ // written as `android-development` is still matched by its position outside a code span.
370
+ const prose = lines.map(line => line.active && line.text.trim()
371
+ ? stripHtmlComments(line.raw).text : '')
372
+ const active = prose.join('\n')
373
+ // Recognize an existing direct loader, not a mere skill mention or guide link.
374
+ const loader = /^[ \t]*(?:(?:[-+*]|\d+[.)])\s+)?(?:read|load)\s+(?:and\s+apply\s+)?(?:the\s+)?(?:installed\s+)?`?android-development`?\s+skill\s+before\b/im
375
+ const negation = /\b(?:do not|don't|never|must not)\s+(?:automatically\s+)?(?:read|load|apply|use|follow)\b[^.]{0,120}\bandroid-development\b/i
376
+ if (matchesOutsideInlineCode(active, negation)) {
377
+ throw new Error('existing Android skill-loading rule conflicts with task entry; nothing was changed')
378
+ }
379
+ if (starts.length) {
380
+ const from = lines.findIndex(line => line.comments.includes(start))
381
+ const to = lines.findIndex(line => line.comments.includes(end))
382
+ const body = prose.slice(from + 1, to).join('\n')
383
+ if (!matchesOutsideInlineCode(body, loader)) {
384
+ throw new Error('preserved Android task entry has no active loader; nothing was changed')
385
+ }
386
+ return current
387
+ }
388
+ if (matchesOutsideInlineCode(active, loader)) return current
389
+ if (hasHeading(current, taskEntryTitle)) {
390
+ throw new Error('existing Android task entry needs manual reconciliation; nothing was changed')
391
+ }
392
+ return append(current, `${start}\n${taskEntryBody}\n${end}`, name)
393
+ }
394
+
298
395
  function planInitialization(root) {
299
396
  const claude = inspectClaude(root)
300
397
  const [agents, contributing] = ['AGENTS.md', 'CONTRIBUTING.md'].map(name => resolveTarget(root, name))
@@ -316,13 +413,13 @@ function planInitialization(root) {
316
413
  const agentsEntry = readGuidance(agents)
317
414
  const contributingEntry = readGuidance(contributing)
318
415
 
319
- let agentText = agentsEntry.current ?? '# Agent instructions\n'
416
+ let agentText = addTaskEntry(agentsEntry.current ?? '# Agent instructions\n', agentsEntry.name)
320
417
  if (!hasLoader(agentText, agentsEntry, contributingEntry)) {
321
418
  const heading = hasHeading(agentText, sectionTitle) ? '' : `## ${sectionTitle}\n\n`
322
- agentText = append(agentText, `${heading}Follow [CONTRIBUTING.md](${linkFrom(agentsEntry, contributingEntry)}) for this project's Android validation ladder, device proof and required gates.`)
419
+ agentText = append(agentText, `${heading}Follow [CONTRIBUTING.md](${linkFrom(agentsEntry, contributingEntry)}) for this project's Android validation ladder, device proof and required gates.`, agentsEntry.name)
323
420
  }
324
421
 
325
- const contributingText = preserveOrAdd(contributingEntry.current ?? '# Contributing\n', sectionTitle, sectionId, sectionBody())
422
+ const contributingText = preserveOrAdd(contributingEntry.current ?? '# Contributing\n', contributingEntry.name, sectionTitle, sectionId, sectionBody())
326
423
 
327
424
  const plan = [
328
425
  { ...agentsEntry, next: agentText },
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: app-debug
3
3
  description: "Diagnose runtime failures in deployed Cloud Run services — 5xx/422 errors, tracebacks, Next.js SSR/hydration or Server Action failures, DB/Secret Manager connection errors, cold-start timeouts, container OOM. NOT for build or deploy failures (cloud-debug)."
4
- release-version: 0.46.0
4
+ release-version: 0.47.0
5
5
  ---
6
6
  **Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
7
7
  # App Debug
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: better-auth
3
3
  description: "Add or debug Better Auth for Next.js App Router: login, sessions, protected routes, middleware, OAuth (including Feishu/Lark), cookies, Prisma, and Auth.js migration."
4
- release-version: 0.46.0
4
+ release-version: 0.47.0
5
5
  ---
6
6
  **Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
7
7
  # Better Auth for Next.js
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: data-catalog
3
3
  description: "Column definitions for warehouse tables, written inside the Spark/PySpark or SQL script that builds each table (CATALOG_TABLE / CATALOG_FIELDS, or a `-- @field` comment block), with a generated markdown catalog in docs/catalog/ and a CI check that fails a PR whose catalog is stale. Use when writing or changing a table script that adds, renames, removes, or changes the meaning of an output column or feature; when asked what a warehouse column or feature means; to set a repo up ('init the data catalog', 'generate the data dictionary', '字段字典', 'add catalog CI'); or to audit existing SQL or Spark scripts for undocumented columns. NOT for implementing or tuning the Spark job itself (pyspark), DAG wiring (airflow), or general workflow YAML (github-actions)."
4
- release-version: 0.46.0
4
+ release-version: 0.47.0
5
5
  ---
6
6
  **Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
7
7
  # Data catalog
@@ -12,23 +12,49 @@ and CI fails a pull request when the pages and the scripts disagree.
12
12
 
13
13
  ## First use in a repo
14
14
 
15
- In a git repo with no `data-catalog.json`, set the repo up **before** the task you
16
- were asked to do, whatever it is: an audit, a new column, or a question. Setting up
17
- puts the engine, the CI check, and the conventions in the repo itself, so agents
18
- and people without this skill follow them from then on.
15
+ No `data-catalog.json` means the repo is not set up. That is a fact about the repo,
16
+ not permission to write to it, and the `## Data catalog task entry` rule that loaded
17
+ this skill is not one either: an audit, a review, a column question or a table-script
18
+ change is the task, and it is done from the sources the repo already has.
19
+
20
+ - **Read what exists.** `docs/catalog/<table>.md` when the repo has pages, else the
21
+ script's `CATALOG_TABLE`/`CATALOG_FIELDS`, else its `-- @table`/`-- @field` block,
22
+ else the SQL or DataFrame code. A definition in the script answers the question;
23
+ never hand-write the missing page.
24
+ - **Audit read-only.** `python3 <skill-base-dir>/scripts/data_catalog.py audit
25
+ 'jobs/**/*.py' 'sql/**/*.sql'` needs no config and writes nothing; it exits 2 only
26
+ with neither a config nor globs.
27
+ - **A check you cannot run stays pending.** `generate`, `generate --check` and `drift`
28
+ exit 2 without `data-catalog.json`. Report them pending — "the catalog is not set up
29
+ here" — not "no findings", "green" or "CI passes", and do not run `init --write` to
30
+ make them runnable: running them is the task, making them runnable is setup.
31
+ - **Offer setup once.** One short line: `init --write` with the `--scripts` globs and
32
+ `--languages` you would use, plus `persist-conventions.mjs --write` for the
33
+ conventions section, the `AGENTS.md` pointer and the task-entry rule. Say nothing was
34
+ written, keep working, once per session per repo. Not an approval checkpoint.
35
+ - **Setting up is an explicit request.** "init the data catalog", "generate the data
36
+ dictionary", "字段字典", "add catalog CI", "set up the catalog here" — that
37
+ authorizes these writes in that repo only. An automatic review, the loader rule, a
38
+ handoff from another skill, or having read this section do not.
39
+
40
+ With that request, setup is:
19
41
 
20
42
  1. `python3 <skill-base-dir>/scripts/data_catalog.py audit '<globs>'` to find the
21
43
  table scripts; choose `--scripts` globs that cover them and nothing else.
22
44
  2. Pick `--languages` from the repo's existing docs (Chinese docs: `zh,en`;
23
45
  otherwise `en`). Run `init` with them and `--write` ([Init](#init)).
24
46
  3. `node <skill-base-dir>/scripts/persist-conventions.mjs --repo-root <repo> --write`
25
- writes the `## Data catalog conventions` section of `CONTRIBUTING.md` and points
26
- `AGENTS.md` at it.
47
+ writes the `## Data catalog conventions` section of `CONTRIBUTING.md`, points
48
+ `AGENTS.md` at it, and adds the `## Data catalog task entry` rule that loads this
49
+ skill for column or table-script work. It is the only writer of those files and
50
+ writes only with its own `--write`; an ordinary catalog task never runs it.
27
51
  4. Then do the task. In the reply, list what setup added, and say the Data catalog
28
52
  check runs on PRs but is not required.
29
53
 
30
- Skip setup outside a git repo, or when the user says not to change the repo.
31
- Never document tables during setup unless the task asks for it.
54
+ Outside a git repo there is nothing to set up: say so. Never document tables during
55
+ setup unless the task asks for it. Repeating setup with the same inputs leaves the
56
+ configured files unchanged; report a missing input or a conflicting rule instead of
57
+ claiming success.
32
58
 
33
59
  ## Find your task
34
60
 
@@ -36,7 +62,7 @@ Never document tables during setup unless the task asks for it.
36
62
  |---|---|
37
63
  | Writing or changing a table script | [While coding](#while-coding), then [references/field-definitions.md](references/field-definitions.md) |
38
64
  | "What does column X mean?" | Read `docs/catalog/<table>.md`; with no page, read the script's `CATALOG_FIELDS`, then its SQL |
39
- | The repo has no `data-catalog.json` | [First use in a repo](#first-use-in-a-repo) |
65
+ | The repo has no `data-catalog.json` | Do the task read-only, then offer setup once ([First use in a repo](#first-use-in-a-repo)) |
40
66
  | Find scripts with missing or weak definitions | [Audit](#audit) |
41
67
  | Document an existing table | [Backfill one table](#backfill-one-table) |
42
68
  | CI says the catalog is stale | `python3 <engine> generate`, commit the pages |
@@ -46,8 +72,8 @@ Never document tables during setup unless the task asks for it.
46
72
 
47
73
  `<engine>` is `scripts/data-catalog/data_catalog.py` in the repo, or
48
74
  `<skill-base-dir>/scripts/data_catalog.py` before the repo has a copy. When
49
- `python3 <engine> version` differs from the skill's copy, refresh with
50
- `init --write`.
75
+ `python3 <engine> version` differs from the skill's copy, the refresh is
76
+ `init --write`, which needs a setup request ([First use in a repo](#first-use-in-a-repo)).
51
77
 
52
78
  ## The files
53
79
 
@@ -61,7 +87,7 @@ Never document tables during setup unless the task asks for it.
61
87
  | `scripts/data-catalog/data_catalog.py` | engine copied from this skill | never; refresh with init |
62
88
  | `.github/workflows/data-catalog.yml` | generated CI check | never; rerun init |
63
89
  | `CONTRIBUTING.md` section between `conventions:data-catalog` markers | the conventions, for agents without this skill | never; rerun `persist-conventions.mjs --write`; the rest is yours |
64
- | `AGENTS.md` `## Contributing` pointer | points at `CONTRIBUTING.md` | written once by `persist-conventions.mjs` |
90
+ | `AGENTS.md` `## Contributing` pointer and `## Data catalog task entry` rule | reach `CONTRIBUTING.md` and this skill; the rule routes work and authorizes no write | written once by `persist-conventions.mjs`; re-run `--write` to restore a missing one |
65
91
 
66
92
  ## Rules
67
93
 
@@ -118,6 +144,11 @@ Never document tables during setup unless the task asks for it.
118
144
  PR why it still holds.
119
145
  6. Commit the script and the regenerated pages together.
120
146
 
147
+ A repo with no `data-catalog.json`: steps 4 and 5 cannot run, because both exit 2
148
+ without a config. Write the definitions the change needs, say those checks are
149
+ pending, and offer setup once ([First use in a repo](#first-use-in-a-repo)). Do not
150
+ run `init --write` to make them run.
151
+
121
152
  Example: changing `WHERE status = 'POSTED'` to `status IN ('POSTED', 'SETTLED')`
122
153
  passes CI, and `drift` reports "filters, joins or CTEs changed; no definition
123
154
  changed" until the affected sources say "posted or settled".
@@ -141,6 +172,10 @@ to `data-catalog.json` take effect on the next `init --write`. After a skill upd
141
172
  rerun both `init --write` and `persist-conventions.mjs --write` so the repo's copies
142
173
  match.
143
174
 
175
+ Without `--write`, `init` only prints its plan, so a dry run is always safe. With
176
+ `--write` it is repo setup and needs the user's setup request
177
+ ([First use in a repo](#first-use-in-a-repo)).
178
+
144
179
  The scripts import `from catalog_fields import Field, Table` at run time, so the
145
180
  module must ship with them like any sibling module (for example `--py-files` on
146
181
  `spark-submit`). Check that before merging.
@@ -188,7 +223,8 @@ script is clean when its columns were `unknown`.
188
223
  3. Add `CATALOG_TABLE` and `CATALOG_FIELDS` in contract order. Keep the literal
189
224
  contract while you write.
190
225
  4. Run `generate` until it passes, then derive the contract and run the repo's
191
- schema tests (rule 5).
226
+ schema tests (rule 5). In a repo with no `data-catalog.json` it exits 2: report it
227
+ pending and offer setup once, and do not run `init --write` for it.
192
228
  5. Rerun the audit for that script and fix its writing findings (`repeated-text`,
193
229
  `code-in-description`, `long-definition`, `thin-definition`,
194
230
  `relative-definition`), or leave one only when the text really belongs in that row.
@@ -201,8 +237,9 @@ empty text.
201
237
 
202
238
  ## Done when
203
239
 
204
- - `python3 <engine> generate --check` exits 0.
240
+ - `python3 <engine> generate --check` exits 0, or you said it is pending because the
241
+ repo has no `data-catalog.json`.
205
242
  - `python3 <engine> drift` exits 0, or you said in the PR why each listed definition
206
- still holds.
243
+ still holds, or you reported it pending for the same reason.
207
244
  - `python3 <engine> audit` has no findings for the tables you touched, or you
208
245
  reported the ones left and why.