bmad-module-skill-forge 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.nvmrc +1 -1
- package/docs/_data/pinned.yaml +1 -1
- package/package.json +2 -2
- package/src/knowledge/skill-lifecycle.md +1 -1
- package/src/module-help.csv +2 -2
- package/src/shared/scripts/skf-comention-pairs.py +350 -0
- package/src/shared/scripts/skf-count-tokens.py +222 -0
- package/src/shared/scripts/skf-detect-docs.py +232 -1
- package/src/shared/scripts/skf-detect-language.py +77 -0
- package/src/shared/scripts/skf-detect-tools.py +105 -2
- package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
- package/src/shared/scripts/skf-find-cycles.py +246 -0
- package/src/shared/scripts/skf-hash-content.py +487 -2
- package/src/shared/scripts/skf-manifest-ops.py +67 -1
- package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
- package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
- package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
- package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
- package/src/shared/scripts/skf-shard-body.py +461 -0
- package/src/shared/scripts/skf-skill-inventory.py +139 -3
- package/src/shared/scripts/skf-structural-diff.py +307 -67
- package/src/shared/scripts/skf-validate-brief-schema.py +39 -1
- package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
- package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
- package/src/shared/scripts/skf-validate-output.py +443 -10
- package/src/shared/scripts/skf-validate-pins.py +1 -1
- package/src/shared/scripts/skf-verify-no-trace.py +214 -0
- package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
- package/src/skf-analyze-source/SKILL.md +17 -32
- package/src/skf-analyze-source/customize.toml +2 -0
- package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
- package/src/skf-analyze-source/references/continue.md +8 -13
- package/src/skf-analyze-source/references/generate-briefs.md +28 -12
- package/src/skf-analyze-source/references/headless-contract.md +33 -0
- package/src/skf-analyze-source/references/health-check.md +1 -2
- package/src/skf-analyze-source/references/identify-units.md +25 -36
- package/src/skf-analyze-source/references/init.md +12 -25
- package/src/skf-analyze-source/references/map-and-detect.md +8 -20
- package/src/skf-analyze-source/references/recommend.md +4 -14
- package/src/skf-analyze-source/references/scan-project.md +3 -11
- package/src/skf-analyze-source/references/step-auto-scope.md +42 -180
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
- package/src/skf-audit-skill/SKILL.md +9 -6
- package/src/skf-audit-skill/customize.toml +2 -0
- package/src/skf-audit-skill/references/init.md +58 -32
- package/src/skf-audit-skill/references/re-index.md +15 -34
- package/src/skf-audit-skill/references/report.md +11 -58
- package/src/skf-audit-skill/references/semantic-diff.md +4 -22
- package/src/skf-audit-skill/references/severity-classify.md +53 -87
- package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
- package/src/skf-audit-skill/references/structural-diff.md +43 -68
- package/src/skf-brief-skill/SKILL.md +7 -36
- package/src/skf-brief-skill/assets/scope-templates.md +1 -1
- package/src/skf-brief-skill/customize.toml +14 -0
- package/src/skf-brief-skill/references/analyze-target.md +6 -14
- package/src/skf-brief-skill/references/confirm-brief.md +2 -14
- package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
- package/src/skf-brief-skill/references/gather-intent.md +19 -22
- package/src/skf-brief-skill/references/headless-args.md +1 -1
- package/src/skf-brief-skill/references/health-check.md +1 -22
- package/src/skf-brief-skill/references/invocation-contract.md +37 -0
- package/src/skf-brief-skill/references/scope-definition.md +4 -14
- package/src/skf-brief-skill/references/step-auto-brief.md +1 -5
- package/src/skf-brief-skill/references/step-auto-validate.md +1 -5
- package/src/skf-brief-skill/references/version-resolution.md +1 -1
- package/src/skf-brief-skill/references/write-brief.md +17 -10
- package/src/skf-campaign/SKILL.md +15 -84
- package/src/skf-campaign/customize.toml +2 -0
- package/src/skf-campaign/manifest.yaml +4 -0
- package/src/skf-campaign/references/campaign-contracts.md +67 -0
- package/src/skf-campaign/references/campaign-directive-spec.md +14 -103
- package/src/skf-campaign/references/step-01-setup.md +4 -5
- package/src/skf-campaign/references/step-02-strategy.md +8 -3
- package/src/skf-campaign/references/step-03-pins.md +1 -1
- package/src/skf-campaign/references/step-04-provenance.md +1 -1
- package/src/skf-campaign/references/step-05-skill-loop.md +1 -1
- package/src/skf-campaign/references/step-06-batch.md +7 -6
- package/src/skf-campaign/references/step-11-maintenance.md +2 -2
- package/src/skf-campaign/references/step-resume.md +9 -8
- package/src/skf-campaign/scripts/campaign-deps.py +10 -1
- package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
- package/src/skf-campaign/scripts/campaign-status.py +162 -0
- package/src/skf-campaign/templates/campaign-brief-template.yaml +1 -1
- package/src/skf-create-skill/SKILL.md +14 -3
- package/src/skf-create-skill/assets/compile-assembly-rules.md +17 -38
- package/src/skf-create-skill/assets/skill-sections.md +9 -100
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
- package/src/skf-create-skill/customize.toml +13 -0
- package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
- package/src/skf-create-skill/references/compile.md +34 -47
- package/src/skf-create-skill/references/component-extraction.md +8 -35
- package/src/skf-create-skill/references/ecosystem-check.md +9 -25
- package/src/skf-create-skill/references/enrich.md +4 -17
- package/src/skf-create-skill/references/extract.md +14 -29
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
- package/src/skf-create-skill/references/extraction-patterns.md +7 -7
- package/src/skf-create-skill/references/generate-artifacts.md +9 -23
- package/src/skf-create-skill/references/health-check.md +1 -1
- package/src/skf-create-skill/references/load-brief.md +16 -18
- package/src/skf-create-skill/references/report.md +12 -15
- package/src/skf-create-skill/references/source-resolution-protocols.md +3 -3
- package/src/skf-create-skill/references/step-auto-shard.md +52 -25
- package/src/skf-create-skill/references/step-doc-rot.md +30 -12
- package/src/skf-create-skill/references/step-doc-sources.md +2 -2
- package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
- package/src/skf-create-skill/references/sub/fetch-docs.md +8 -50
- package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
- package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
- package/src/skf-create-skill/references/validate.md +59 -28
- package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
- package/src/skf-create-stack-skill/SKILL.md +15 -9
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
- package/src/skf-create-stack-skill/customize.toml +10 -0
- package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
- package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
- package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
- package/src/skf-create-stack-skill/references/generate-output.md +24 -75
- package/src/skf-create-stack-skill/references/init.md +9 -81
- package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
- package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
- package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
- package/src/skf-create-stack-skill/references/report.md +27 -62
- package/src/skf-create-stack-skill/references/validate.md +35 -31
- package/src/skf-drop-skill/SKILL.md +20 -23
- package/src/skf-drop-skill/customize.toml +10 -0
- package/src/skf-drop-skill/references/execute.md +51 -31
- package/src/skf-drop-skill/references/headless-contract.md +18 -0
- package/src/skf-drop-skill/references/health-check.md +1 -13
- package/src/skf-drop-skill/references/report.md +42 -10
- package/src/skf-drop-skill/references/select.md +88 -48
- package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
- package/src/skf-export-skill/SKILL.md +17 -14
- package/src/skf-export-skill/assets/managed-section-format.md +2 -5
- package/src/skf-export-skill/customize.toml +10 -6
- package/src/skf-export-skill/references/generate-snippet.md +21 -35
- package/src/skf-export-skill/references/load-skill.md +44 -42
- package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
- package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
- package/src/skf-export-skill/references/package.md +27 -33
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
- package/src/skf-export-skill/references/result-envelope.md +28 -0
- package/src/skf-export-skill/references/summary.md +11 -5
- package/src/skf-export-skill/references/token-report.md +42 -24
- package/src/skf-export-skill/references/update-context.md +32 -33
- package/src/skf-forger/SKILL.md +27 -39
- package/src/skf-forger/references/pipeline-mode.md +34 -0
- package/src/skf-forger/scripts/parse-pipeline.py +270 -0
- package/src/skf-quick-skill/SKILL.md +10 -60
- package/src/skf-quick-skill/customize.toml +9 -0
- package/src/skf-quick-skill/references/batch-mode.md +6 -4
- package/src/skf-quick-skill/references/compile.md +15 -52
- package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
- package/src/skf-quick-skill/references/finalize.md +12 -6
- package/src/skf-quick-skill/references/halt-contract.md +54 -0
- package/src/skf-quick-skill/references/health-check.md +3 -4
- package/src/skf-quick-skill/references/quick-extract.md +7 -18
- package/src/skf-quick-skill/references/registry-resolution.md +1 -23
- package/src/skf-quick-skill/references/resolve-target.md +27 -34
- package/src/skf-quick-skill/references/write-and-validate.md +10 -25
- package/src/skf-refine-architecture/SKILL.md +14 -7
- package/src/skf-refine-architecture/customize.toml +9 -0
- package/src/skf-refine-architecture/references/compile.md +9 -7
- package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
- package/src/skf-refine-architecture/references/health-check.md +1 -1
- package/src/skf-refine-architecture/references/improvements.md +9 -25
- package/src/skf-refine-architecture/references/init.md +9 -16
- package/src/skf-refine-architecture/references/issue-detection.md +10 -25
- package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
- package/src/skf-refine-architecture/references/report.md +13 -10
- package/src/skf-rename-skill/SKILL.md +11 -21
- package/src/skf-rename-skill/customize.toml +10 -0
- package/src/skf-rename-skill/references/execute.md +107 -78
- package/src/skf-rename-skill/references/exit-codes.md +12 -0
- package/src/skf-rename-skill/references/report.md +16 -8
- package/src/skf-rename-skill/references/select.md +69 -42
- package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
- package/src/skf-setup/SKILL.md +20 -12
- package/src/skf-setup/customize.toml +10 -0
- package/src/skf-setup/references/auto-index.md +9 -10
- package/src/skf-setup/references/ccc-index.md +14 -15
- package/src/skf-setup/references/detect-and-tier.md +6 -8
- package/src/skf-setup/references/report.md +22 -31
- package/src/skf-setup/references/tier-rules.md +2 -32
- package/src/skf-setup/references/write-config.md +9 -10
- package/src/skf-test-skill/SKILL.md +10 -8
- package/src/skf-test-skill/customize.toml +2 -0
- package/src/skf-test-skill/references/coherence-check.md +19 -31
- package/src/skf-test-skill/references/coverage-check.md +109 -75
- package/src/skf-test-skill/references/detect-mode.md +10 -41
- package/src/skf-test-skill/references/external-validators.md +11 -19
- package/src/skf-test-skill/references/init.md +38 -20
- package/src/skf-test-skill/references/migration-section-rules.md +4 -4
- package/src/skf-test-skill/references/report.md +60 -40
- package/src/skf-test-skill/references/score.md +32 -64
- package/src/skf-test-skill/references/scoring-rules.md +6 -62
- package/src/skf-test-skill/references/source-access-protocol.md +6 -6
- package/src/skf-test-skill/references/step-hard-gate.md +1 -3
- package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
- package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
- package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
- package/src/skf-test-skill/scripts/compute-score.py +131 -1
- package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
- package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
- package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
- package/src/skf-update-skill/SKILL.md +17 -5
- package/src/skf-update-skill/customize.toml +14 -0
- package/src/skf-update-skill/references/detect-changes.md +19 -37
- package/src/skf-update-skill/references/health-check.md +3 -9
- package/src/skf-update-skill/references/init.md +39 -32
- package/src/skf-update-skill/references/manual-section-rules.md +1 -2
- package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
- package/src/skf-update-skill/references/merge.md +13 -57
- package/src/skf-update-skill/references/re-extract.md +12 -24
- package/src/skf-update-skill/references/report.md +14 -7
- package/src/skf-update-skill/references/validate.md +32 -30
- package/src/skf-update-skill/references/write.md +86 -51
- package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
- package/src/skf-verify-stack/SKILL.md +11 -21
- package/src/skf-verify-stack/customize.toml +12 -3
- package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
- package/src/skf-verify-stack/references/coverage.md +21 -10
- package/src/skf-verify-stack/references/exit-codes.md +14 -0
- package/src/skf-verify-stack/references/health-check.md +1 -1
- package/src/skf-verify-stack/references/init.md +20 -25
- package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
- package/src/skf-verify-stack/references/integrations.md +44 -49
- package/src/skf-verify-stack/references/report.md +28 -34
- package/src/skf-verify-stack/references/requirements.md +3 -3
- package/src/skf-verify-stack/references/synthesize.md +36 -39
- package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
- package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
- package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
- package/src/skf-rename-skill/references/rebuild-context.md +0 -110
|
@@ -16,10 +16,23 @@ Actions:
|
|
|
16
16
|
clear — Remove managed section entirely (markers + content)
|
|
17
17
|
insert — Insert managed section if not present (at end of file)
|
|
18
18
|
check — Check if managed section exists, report status
|
|
19
|
+
|
|
20
|
+
Query actions (read-only, take positional file lists instead of <file> <action>):
|
|
21
|
+
orphan-detect <context-file>... --exported-skills a,b
|
|
22
|
+
— Parse `[skill-name v...]` rows across one or more context
|
|
23
|
+
files, drop rows whose skill_name is in the exported set,
|
|
24
|
+
and report the survivors (deduped by (skill_name, version),
|
|
25
|
+
with verbatim snippet_text and sorted source_files provenance)
|
|
26
|
+
as `orphan_managed_rows`.
|
|
27
|
+
root-probe <snippet-file>... --reference-root .claude/skills/
|
|
28
|
+
— Read each snippet's first line, parse its `root:` prefix
|
|
29
|
+
(trailing `{skill-name}/` stripped), collect the unique
|
|
30
|
+
`observed_prefixes`, and flag `mismatch` against the reference.
|
|
19
31
|
"""
|
|
20
32
|
|
|
21
33
|
from __future__ import annotations
|
|
22
34
|
|
|
35
|
+
import argparse
|
|
23
36
|
import json
|
|
24
37
|
import os
|
|
25
38
|
import re
|
|
@@ -34,6 +47,16 @@ MARKER_PATTERN = re.compile(
|
|
|
34
47
|
re.DOTALL,
|
|
35
48
|
)
|
|
36
49
|
|
|
50
|
+
# A managed-section skill row header: `[skill-name v1.2.3]…`, optionally
|
|
51
|
+
# prefixed by the format's leading `|`. Requires a ` v<version>` inside the
|
|
52
|
+
# brackets so the section header `[SKF Skills]|{n} skills|{m} stack` (no ` v`)
|
|
53
|
+
# is never mistaken for a skill row.
|
|
54
|
+
ROW_HEADER_PATTERN = re.compile(
|
|
55
|
+
r"^\|?\[(?P<name>[^\]]+?) v(?P<version>[^\]\s]+)\]"
|
|
56
|
+
)
|
|
57
|
+
# The `root:` field of a snippet's first line: `…|root: {prefix}{skill-name}/`.
|
|
58
|
+
SNIPPET_ROOT_PATTERN = re.compile(r"root:\s*(?P<root>\S.*?)\s*$")
|
|
59
|
+
|
|
37
60
|
|
|
38
61
|
def read_context_file(file_path):
|
|
39
62
|
"""Read a context file. Returns (content, None) or (None, error)."""
|
|
@@ -222,7 +245,164 @@ def cmd_insert(file_path, new_content):
|
|
|
222
245
|
return {"status": "ok", "action": "inserted", "bytes_written": len(updated)}
|
|
223
246
|
|
|
224
247
|
|
|
248
|
+
def _is_row_separator(line):
|
|
249
|
+
"""A blank/separator line between snippets: bare `|` or empty."""
|
|
250
|
+
return line.strip() in ("", "|")
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def parse_managed_rows(body):
|
|
254
|
+
"""Split the between-marker `body` into skill rows.
|
|
255
|
+
|
|
256
|
+
Returns a list of {skill_name, version, snippet_text} dicts, one per
|
|
257
|
+
`[skill-name v...]` header found. `snippet_text` is the header line plus its
|
|
258
|
+
continuation lines, captured verbatim (byte-preserved) up to — but not
|
|
259
|
+
including — the next bare-`|` separator, the next row header, or end of body.
|
|
260
|
+
Non-row lines (the `[SKF Skills]` header, the IMPORTANT preamble) are skipped.
|
|
261
|
+
"""
|
|
262
|
+
lines = body.split("\n")
|
|
263
|
+
rows = []
|
|
264
|
+
i = 0
|
|
265
|
+
n = len(lines)
|
|
266
|
+
while i < n:
|
|
267
|
+
m = ROW_HEADER_PATTERN.match(lines[i])
|
|
268
|
+
if not m:
|
|
269
|
+
i += 1
|
|
270
|
+
continue
|
|
271
|
+
start = i
|
|
272
|
+
i += 1
|
|
273
|
+
while i < n and not ROW_HEADER_PATTERN.match(lines[i]) and not _is_row_separator(lines[i]):
|
|
274
|
+
i += 1
|
|
275
|
+
rows.append(
|
|
276
|
+
{
|
|
277
|
+
"skill_name": m.group("name"),
|
|
278
|
+
"version": m.group("version"),
|
|
279
|
+
"snippet_text": "\n".join(lines[start:i]),
|
|
280
|
+
}
|
|
281
|
+
)
|
|
282
|
+
return rows
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def cmd_orphan_detect(context_files, exported_skills):
|
|
286
|
+
"""Detect managed-section rows absent from the exported skill set.
|
|
287
|
+
|
|
288
|
+
Scans every context file that exists and has a managed section, parses its
|
|
289
|
+
skill rows, drops those whose skill_name is in `exported_skills`, and
|
|
290
|
+
accumulates the survivors keyed by (skill_name, version). The first-seen
|
|
291
|
+
snippet_text wins; each file the row appears in is added to source_files.
|
|
292
|
+
Deterministic: rows sorted by (skill_name, version), source_files sorted.
|
|
293
|
+
"""
|
|
294
|
+
exported = {s.strip() for s in exported_skills.split(",") if s.strip()}
|
|
295
|
+
orphans = {} # (name, version) -> {skill_name, version, snippet_text, source_files:set}
|
|
296
|
+
for cf in context_files:
|
|
297
|
+
content, err = read_context_file(cf)
|
|
298
|
+
if err:
|
|
299
|
+
continue # missing file — no orphans by definition
|
|
300
|
+
match = find_managed_section(content)
|
|
301
|
+
if not match:
|
|
302
|
+
continue # no managed section — no orphans
|
|
303
|
+
for row in parse_managed_rows(match.group(2)):
|
|
304
|
+
if row["skill_name"] in exported:
|
|
305
|
+
continue # not an orphan — it is being (re)exported
|
|
306
|
+
key = (row["skill_name"], row["version"])
|
|
307
|
+
if key in orphans:
|
|
308
|
+
orphans[key]["source_files"].add(cf) # keep first-seen snippet_text
|
|
309
|
+
else:
|
|
310
|
+
orphans[key] = {
|
|
311
|
+
"skill_name": row["skill_name"],
|
|
312
|
+
"version": row["version"],
|
|
313
|
+
"snippet_text": row["snippet_text"],
|
|
314
|
+
"source_files": {cf},
|
|
315
|
+
}
|
|
316
|
+
orphan_rows = [
|
|
317
|
+
{
|
|
318
|
+
"skill_name": v["skill_name"],
|
|
319
|
+
"version": v["version"],
|
|
320
|
+
"snippet_text": v["snippet_text"],
|
|
321
|
+
"source_files": sorted(v["source_files"]),
|
|
322
|
+
}
|
|
323
|
+
for _, v in sorted(orphans.items())
|
|
324
|
+
]
|
|
325
|
+
return {"status": "ok", "orphan_managed_rows": orphan_rows}
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def cmd_root_probe(snippet_files, reference_root):
|
|
329
|
+
"""Observe snippet root prefixes and flag mismatch against a reference.
|
|
330
|
+
|
|
331
|
+
Reads the first line of each snippet that exists, parses its `root:` value,
|
|
332
|
+
strips the trailing `{skill-name}/` to recover the prefix, and collects the
|
|
333
|
+
unique prefixes. `mismatch` is True when any observed prefix differs from
|
|
334
|
+
`reference_root`. Deterministic: observed_prefixes sorted.
|
|
335
|
+
"""
|
|
336
|
+
observed = set()
|
|
337
|
+
for sf in snippet_files:
|
|
338
|
+
content, err = read_context_file(sf)
|
|
339
|
+
if err:
|
|
340
|
+
continue # missing snippet — skip
|
|
341
|
+
first_line = content.split("\n", 1)[0]
|
|
342
|
+
header = ROW_HEADER_PATTERN.match(first_line)
|
|
343
|
+
root_match = SNIPPET_ROOT_PATTERN.search(first_line)
|
|
344
|
+
if not root_match:
|
|
345
|
+
continue # no root: field — skip
|
|
346
|
+
root_value = root_match.group("root")
|
|
347
|
+
prefix = root_value
|
|
348
|
+
if header:
|
|
349
|
+
suffix = header.group("name") + "/"
|
|
350
|
+
if root_value.endswith(suffix):
|
|
351
|
+
prefix = root_value[: -len(suffix)]
|
|
352
|
+
observed.add(prefix)
|
|
353
|
+
observed_prefixes = sorted(observed)
|
|
354
|
+
return {
|
|
355
|
+
"status": "ok",
|
|
356
|
+
"reference_root": reference_root,
|
|
357
|
+
"observed_prefixes": observed_prefixes,
|
|
358
|
+
"mismatch": any(p != reference_root for p in observed_prefixes),
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
|
|
362
|
+
def _run_query_action(argv):
|
|
363
|
+
"""Dispatch the read-only query actions (orphan-detect / root-probe).
|
|
364
|
+
|
|
365
|
+
These take a positional file list rather than the legacy `<file> <action>`
|
|
366
|
+
shape, so they are parsed with argparse and routed here before the legacy
|
|
367
|
+
path. Returns (result_dict, exit_code).
|
|
368
|
+
"""
|
|
369
|
+
action = argv[0]
|
|
370
|
+
if action == "orphan-detect":
|
|
371
|
+
parser = argparse.ArgumentParser(
|
|
372
|
+
prog="skf-rebuild-managed-sections.py orphan-detect",
|
|
373
|
+
description="Detect managed-section rows absent from the exported skill set.",
|
|
374
|
+
)
|
|
375
|
+
parser.add_argument("context_files", nargs="+", help="Context file paths to scan")
|
|
376
|
+
parser.add_argument(
|
|
377
|
+
"--exported-skills",
|
|
378
|
+
default="",
|
|
379
|
+
help="Comma-separated skill names being exported (excluded from orphans)",
|
|
380
|
+
)
|
|
381
|
+
args = parser.parse_args(argv[1:])
|
|
382
|
+
return cmd_orphan_detect(args.context_files, args.exported_skills), 0
|
|
383
|
+
# action == "root-probe"
|
|
384
|
+
parser = argparse.ArgumentParser(
|
|
385
|
+
prog="skf-rebuild-managed-sections.py root-probe",
|
|
386
|
+
description="Observe snippet root prefixes and flag mismatch against a reference.",
|
|
387
|
+
)
|
|
388
|
+
parser.add_argument("snippet_files", nargs="+", help="Snippet file paths to probe")
|
|
389
|
+
parser.add_argument(
|
|
390
|
+
"--reference-root",
|
|
391
|
+
required=True,
|
|
392
|
+
help="Reference skill root prefix to compare observed prefixes against",
|
|
393
|
+
)
|
|
394
|
+
args = parser.parse_args(argv[1:])
|
|
395
|
+
return cmd_root_probe(args.snippet_files, args.reference_root), 0
|
|
396
|
+
|
|
397
|
+
|
|
225
398
|
def main():
|
|
399
|
+
# Query actions take a positional file list, so they are action-first
|
|
400
|
+
# (`orphan-detect <file>...`) rather than the legacy `<file> <action>` shape.
|
|
401
|
+
if len(sys.argv) >= 2 and sys.argv[1] in ("orphan-detect", "root-probe"):
|
|
402
|
+
result, code = _run_query_action(sys.argv[1:])
|
|
403
|
+
print(json.dumps(result, indent=2))
|
|
404
|
+
sys.exit(code)
|
|
405
|
+
|
|
226
406
|
if len(sys.argv) < 3:
|
|
227
407
|
print("Usage: python3 skf-rebuild-managed-sections.py <context-file> <action> [--content <text>]", file=sys.stderr)
|
|
228
408
|
print("Actions: read, replace, clear, insert, check", file=sys.stderr)
|
|
@@ -15,7 +15,7 @@ The five-rule ladder (apply in order, first match wins):
|
|
|
15
15
|
entries or `Component[]` annotation when contents available;
|
|
16
16
|
presence-only when contents not available)
|
|
17
17
|
2. reference-app — intent text mentions wiring / integration / starter
|
|
18
|
-
/
|
|
18
|
+
/ build-config keywords, OR analysis flagged as demo/example
|
|
19
19
|
3. specific-modules — intent names a specific subset ("just the X",
|
|
20
20
|
"only the Y") OR module_count >= 6
|
|
21
21
|
4. public-api — export_count <= 8 AND intent mentions "the API",
|
|
@@ -71,7 +71,6 @@ REFERENCE_APP_KEYWORDS = (
|
|
|
71
71
|
"integration example",
|
|
72
72
|
"integration sample",
|
|
73
73
|
"starter",
|
|
74
|
-
"lifecycle",
|
|
75
74
|
"build config",
|
|
76
75
|
"build-config",
|
|
77
76
|
"demo app",
|