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
|
@@ -11,15 +11,9 @@ nextStepFile: 'shared/health-check.md'
|
|
|
11
11
|
|
|
12
12
|
## STEP GOAL:
|
|
13
13
|
|
|
14
|
-
Chain to the shared workflow self-improvement health check at `{nextStepFile}`. This is the terminal step of update-skill — after the shared health check completes, the workflow is fully done.
|
|
14
|
+
Chain to the shared workflow self-improvement health check at `{nextStepFile}`. This is the terminal step of update-skill — after the shared health check completes, the workflow is fully done. This step only releases the concurrency lock and delegates: no user-facing reports, file writes, or result contracts here (those belong in step 7).
|
|
15
15
|
|
|
16
|
-
##
|
|
17
|
-
|
|
18
|
-
- No user-facing reports, file writes, or result contracts in this step — those belong in step 7
|
|
19
|
-
- Delegate directly to `{nextStepFile}` with no additional commentary
|
|
20
|
-
- Do not attempt any other action between loading this step and executing `{nextStepFile}` (other than the lock release below)
|
|
21
|
-
|
|
22
|
-
## MANDATORY SEQUENCE
|
|
16
|
+
## Steps
|
|
23
17
|
|
|
24
18
|
1. **Release the concurrency lock** acquired by init.md §1b (skip when `detect_only_mode` or `dry_run_mode` is true — those modes never acquired one):
|
|
25
19
|
|
|
@@ -27,6 +21,6 @@ Chain to the shared workflow self-improvement health check at `{nextStepFile}`.
|
|
|
27
21
|
rm -f "{forge_data_folder}/{skill_name}/.skf-update.lock"
|
|
28
22
|
```
|
|
29
23
|
|
|
30
|
-
|
|
24
|
+
Release the lock before delegating to the shared health-check: the health-check is the terminal step, so once it returns the workflow is done and any still-held lock is orphaned until the next run clears it. Releasing here keeps the lock lifecycle tight against the workflow's actual span.
|
|
31
25
|
|
|
32
26
|
2. Load `{nextStepFile}`, read it fully, then execute it.
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'detect-changes.md'
|
|
3
3
|
manualSectionRulesFile: 'references/manual-section-rules.md'
|
|
4
|
+
# Resolve `{hashContentHelper}` to the first existing path; HALT if neither
|
|
5
|
+
# candidate exists. §5 uses its `manual-inventory` subcommand to capture the
|
|
6
|
+
# exact pre-write [MANUAL] inventory (per-block byte-exact interior hashes),
|
|
7
|
+
# which write.md §1 (HALT gate) and validate.md Check B later verify against.
|
|
8
|
+
# An LLM marker-count would miss an interior truncation that leaves the marker
|
|
9
|
+
# count unchanged.
|
|
10
|
+
hashContentProbeOrder:
|
|
11
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-hash-content.py'
|
|
12
|
+
- '{project-root}/src/shared/scripts/skf-hash-content.py'
|
|
4
13
|
---
|
|
5
14
|
|
|
6
15
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -16,7 +25,7 @@ Load the existing skill and all its provenance data, detect whether this is an i
|
|
|
16
25
|
- Focus only on loading existing artifacts and establishing the baseline — read-only operations
|
|
17
26
|
- Do not begin change detection (Step 02)
|
|
18
27
|
|
|
19
|
-
##
|
|
28
|
+
## Steps
|
|
20
29
|
|
|
21
30
|
### 1. Request Skill Path
|
|
22
31
|
|
|
@@ -27,6 +36,7 @@ Provide either:
|
|
|
27
36
|
- A full path to the skill folder
|
|
28
37
|
- A skill name with `--from-test-report` to use the test report's gap findings instead of source drift detection
|
|
29
38
|
- `--allow-workspace-drift` (gap-driven mode only) to intentionally bypass the step 3 §0.a guard that halts when the local workspace HEAD does not match `metadata.source_commit`. Only use this if you know the spot-checks should read the current workspace instead of the pinned tree — step 6 will NOT automatically re-pin
|
|
39
|
+
- `--allow-degraded` (headless mode only) to pre-authorize the lossy degraded full re-extraction if §4 finds no provenance map — without it, a headless run halts `blocked` there rather than silently rebuilding
|
|
30
40
|
- `--detect-only` to run detect-changes only and exit; emits the change manifest with no further work and no writes
|
|
31
41
|
- `--dry-run` to run detect-changes + re-extract and exit before merge/write; emits what WOULD change without modifying any artifact
|
|
32
42
|
|
|
@@ -54,6 +64,8 @@ If a report is located, set `test_report_path` in context to the resolved absolu
|
|
|
54
64
|
|
|
55
65
|
**If `--allow-workspace-drift` was provided:** set `allow_workspace_drift: true` in workflow context. This flag is consumed by step 3 §0.a's pre-flight drift guard (gap-driven mode only) and has no effect in normal source-drift mode.
|
|
56
66
|
|
|
67
|
+
**If `--allow-degraded` was provided:** set `allow_degraded: true` in workflow context. This flag is consumed by §4 below when no provenance map is found under `{headless_mode}`; it has no effect interactively (the [D]/[X] prompt is shown) or when a provenance map is present.
|
|
68
|
+
|
|
57
69
|
**If `--detect-only` was provided:** set `detect_only_mode: true` in workflow context. After step 2 (detect-changes) completes, jump directly to step 7 (report) — skip re-extract, merge, validate, and write. The report emits the change manifest and a `SKF_UPDATE_RESULT_JSON` envelope with `status: "detect-only"`. **Compatibility:** `--detect-only` short-circuits before §0.a runs, so `--allow-workspace-drift` is silently ignored in detect-only mode (warn the user once at flag-parse time: "`--allow-workspace-drift` has no effect with `--detect-only` — workspace drift guard runs in step 3 §0.a, which is skipped").
|
|
58
70
|
|
|
59
71
|
**If `--dry-run` was provided:** set `dry_run_mode: true` in workflow context. After step 3 (re-extract) completes, jump directly to step 7 (report) — skip merge, validate, and write. The report emits what would change with `status: "dry-run"` in the envelope. No artifact on disk is modified — `--dry-run` is the "show me what an update would do without committing" mode.
|
|
@@ -81,8 +93,8 @@ if [ -f "$LOCK" ]; then
|
|
|
81
93
|
# (LLM emits SKF_UPDATE_RESULT_JSON status=halted-for-concurrent-run, see below)
|
|
82
94
|
exit 1
|
|
83
95
|
fi
|
|
84
|
-
#
|
|
85
|
-
echo "skf-update-skill: clearing
|
|
96
|
+
# Dead PID — lock left by a prior halted or crashed run; clear + overwrite
|
|
97
|
+
echo "skf-update-skill: clearing lock from a prior halted/crashed run (pid=$HELD_PID)"
|
|
86
98
|
fi
|
|
87
99
|
|
|
88
100
|
# Acquire: write our PID + start timestamp (one per line)
|
|
@@ -96,9 +108,9 @@ printf '%s\n%s\n' "$$" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$LOCK"
|
|
|
96
108
|
|
|
97
109
|
**Release contract:**
|
|
98
110
|
|
|
99
|
-
- The terminal health-check step (step 8) deletes the lock
|
|
100
|
-
-
|
|
101
|
-
- The lock is best-effort: a crash
|
|
111
|
+
- The terminal health-check step (step 8) deletes the lock as its final action — the normal end of every non-inspection run. The two init-stage headless halts below (§4 no-provenance-map, §6 invalid-source-path) also delete it explicitly, since they fire right after acquisition, before the terminal step runs.
|
|
112
|
+
- Mid-workflow halts (detect-changes, re-extract, merge, write) do **not** delete the lock themselves — they rely on the self-heal below. This is deliberate: several of those halt sites are also reachable under `--detect-only`/`--dry-run`, which never acquired this lock, so a blind `rm -f` there could clobber a concurrent real update's lock.
|
|
113
|
+
- The lock is best-effort and self-healing: whatever a halt or crash (process kill, host reboot) leaves behind is cleared by the next run's live-PID check above, since the stored PID is a short-lived bash PID that is already dead. No manual cleanup needed in the common case.
|
|
102
114
|
|
|
103
115
|
### 2. Validate Required Artifacts
|
|
104
116
|
|
|
@@ -113,7 +125,7 @@ printf '%s\n%s\n' "$$" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$LOCK"
|
|
|
113
125
|
|
|
114
126
|
**Detect skill type from metadata:**
|
|
115
127
|
- If `skill_type == "single"` or absent: flag as single skill
|
|
116
|
-
- If `skill_type == "stack"`: flag as stack skill
|
|
128
|
+
- If `skill_type == "stack"`: flag as stack skill — the guard below redirects it
|
|
117
129
|
|
|
118
130
|
### Stack Skill Guard
|
|
119
131
|
|
|
@@ -126,6 +138,8 @@ After loading metadata.json, check `skill_type`:
|
|
|
126
138
|
If you came here from an audit report, the drift report identifies which constituent libraries changed — use that to decide whether re-composition is needed."
|
|
127
139
|
- Exit the workflow (do not proceed to step 2)
|
|
128
140
|
|
|
141
|
+
**This guard is the single gate for stack skills** — every stack is redirected to `skf-create-stack-skill` here, before step 2, and no flag (`--detect-only`, `--dry-run`, `--from-test-report`, `--allow-workspace-drift`) bypasses it. Every later stage therefore runs against a single skill only and carries no stack-merge branch.
|
|
142
|
+
|
|
129
143
|
### 3. Load Forge Tier Configuration
|
|
130
144
|
|
|
131
145
|
**Load `{sidecar_path}/forge-tier.yaml`:**
|
|
@@ -160,18 +174,22 @@ Select: [D] Degraded / [X] Abort"
|
|
|
160
174
|
- If D: set `degraded_mode = true`, proceed with full extraction scope
|
|
161
175
|
- If X: **ABORT**
|
|
162
176
|
|
|
177
|
+
**In `{headless_mode}` without `--allow-degraded` (default):** do not auto-select [D]. Degraded mode is a full, lossy T1-low re-extraction — choosing it unattended would silently swap surgical update for a create-skill-equivalent rebuild, a policy call that belongs to an operator. Halt instead: release the lock (`rm -f "$LOCK"`), emit `SKF_UPDATE_RESULT_JSON` with `status: "blocked"`, `error: {phase: "init:load-provenance-map", path: "{forge_version}/provenance-map.json", reason: "no provenance map at versioned or flat path; degraded full re-extraction needs a human decision"}`, and exit. No `headless_decisions[]` entry — this is a hard halt, not an auto-resolved gate.
|
|
178
|
+
|
|
179
|
+
**In `{headless_mode}` with `--allow-degraded` (`allow_degraded: true`):** the operator pre-authorized the lossy rebuild for this run, so treat it as an auto-resolved [D] rather than a halt. Set `degraded_mode = true`, proceed with full extraction scope, and append to in-context `headless_decisions[]`: `{gate: "init.degraded-rebuild", default_action: "X", taken_action: "D", reason: "headless: --allow-degraded pre-authorized degraded full re-extraction", evidence: "no provenance map at {forge_version}/provenance-map.json or flat fallback"}`. Continue to step 2.
|
|
180
|
+
|
|
163
181
|
### 5. Load [MANUAL] Section Inventory
|
|
164
182
|
|
|
165
|
-
Load {manualSectionRulesFile} to understand [MANUAL] detection patterns.
|
|
183
|
+
Load {manualSectionRulesFile} to understand [MANUAL] detection patterns (the human-readable rules for markers, parent-section mapping, and orphan/nesting handling).
|
|
166
184
|
|
|
167
|
-
**
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
185
|
+
**Capture the [MANUAL] inventory deterministically.** The workflow's headline rule is "[MANUAL] sections survive regeneration with zero content loss" — the pre-write inventory captured here is the exact baseline that write.md §1 and validate.md Check B verify against, so it must be a per-block byte-exact hash, not an eyeballed marker count. Run the `manual-inventory` subcommand of `{hashContentHelper}` and persist its JSON:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
uv run {hashContentHelper} manual-inventory {resolved_skill_package}/SKILL.md \
|
|
189
|
+
> {forge_version}/.manual-inventory.json
|
|
190
|
+
```
|
|
171
191
|
|
|
172
|
-
|
|
173
|
-
- All `references/*.md` files for [MANUAL] markers
|
|
174
|
-
- All `references/integrations/*.md` files for [MANUAL] markers
|
|
192
|
+
The emitted JSON is `{"blocks":[{name, content_hash, byte_offset, parent_heading}...], "count":N}` — each `content_hash` covers the block's byte-exact interior, so a later interior truncation that leaves the marker count unchanged is still caught. Bind the persisted path as `{manual_inventory}` in context; write.md §1 and validate.md Check B pass it to `manual-verify`. Surface the block `count` in the baseline summary (§7 `{manual_count}`).
|
|
175
193
|
|
|
176
194
|
### 6. Resolve Source Code Path
|
|
177
195
|
|
|
@@ -186,6 +204,8 @@ Load {manualSectionRulesFile} to understand [MANUAL] detection patterns.
|
|
|
186
204
|
Provide the current source code path:
|
|
187
205
|
**Path:** {user provides path}"
|
|
188
206
|
|
|
207
|
+
**In `{headless_mode}`:** there is no operator to supply a path. Halt: release the lock (`rm -f "$LOCK"`), emit `SKF_UPDATE_RESULT_JSON` with `status: "blocked"`, `error: {phase: "init:resolve-source-path", path: "{source_root}", reason: "source_root from provenance map is invalid or inaccessible and no interactive path can be supplied"}`, and exit. No `headless_decisions[]` entry — this is a hard halt, not an auto-resolved gate.
|
|
208
|
+
|
|
189
209
|
### 7. Present Baseline Summary
|
|
190
210
|
|
|
191
211
|
"**Update Skill Baseline:**
|
|
@@ -193,7 +213,7 @@ Provide the current source code path:
|
|
|
193
213
|
| Property | Value |
|
|
194
214
|
|----------|-------|
|
|
195
215
|
| **Skill** | {skill_name} |
|
|
196
|
-
| **Type** |
|
|
216
|
+
| **Type** | single |
|
|
197
217
|
| **Version** | {version} |
|
|
198
218
|
| **Created** | {created date} |
|
|
199
219
|
| **Source** | {source_root} |
|
|
@@ -210,22 +230,9 @@ Provide the current source code path:
|
|
|
210
230
|
|
|
211
231
|
**Ready to detect changes and update this skill?**"
|
|
212
232
|
|
|
213
|
-
### 8.
|
|
214
|
-
|
|
215
|
-
Display: "**Select:** [C] Continue to Change Detection"
|
|
216
|
-
|
|
217
|
-
#### Menu Handling Logic:
|
|
218
|
-
|
|
219
|
-
- IF C: Load, read entire file, then execute {nextStepFile}
|
|
220
|
-
- IF Any other: help user respond, then [Redisplay Menu Options](#8-present-menu-options)
|
|
221
|
-
|
|
222
|
-
#### EXECUTION RULES:
|
|
223
|
-
|
|
224
|
-
- ALWAYS halt and wait for user input after presenting menu
|
|
225
|
-
- **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Continue, log: "headless: auto-continue past update confirmation". **Also append to in-context `headless_decisions[]`** (step 7 surfaces this list in `SKF_UPDATE_RESULT_JSON`): `{gate: "init.update-confirmation", default_action: "C", taken_action: "C", reason: "headless: no user to prompt"}`. The headless_decisions[] array is the structured audit trail for non-interactive runs — see `src/shared/scripts/schemas/skf-update-result-envelope.v1.json` for the entry shape.
|
|
226
|
-
- ONLY proceed to next step when user selects 'C'
|
|
233
|
+
### 8. Confirmation Gate
|
|
227
234
|
|
|
228
|
-
|
|
235
|
+
Present "**Select:** [C] Continue to Change Detection" and wait for the user to confirm; on [C], load, read the full file, then execute {nextStepFile}.
|
|
229
236
|
|
|
230
|
-
|
|
237
|
+
**Headless (`{headless_mode}` true):** auto-continue and append to in-context `headless_decisions[]` (step 7 surfaces it in `SKF_UPDATE_RESULT_JSON`): `{gate: "init.update-confirmation", default_action: "C", taken_action: "C", reason: "headless: no user to prompt"}`. Entry shape: `src/shared/scripts/schemas/skf-update-result-envelope.v1.json`.
|
|
231
238
|
|
|
@@ -26,8 +26,7 @@ It must be preserved during any update operation.
|
|
|
26
26
|
2. **Preserve marker positions** — if the surrounding generated content moves, the [MANUAL] block moves with its logical parent section
|
|
27
27
|
3. **Orphan detection** — if the parent section is deleted (export removed), flag as WARNING and present to user
|
|
28
28
|
4. **Multiple [MANUAL] blocks** — a single SKILL.md may have multiple [MANUAL] sections; preserve all
|
|
29
|
-
5. **
|
|
30
|
-
6. **Nested [MANUAL] forbidden** — [MANUAL] blocks cannot be nested; if detected, flag as ERROR
|
|
29
|
+
5. **Nested [MANUAL] forbidden** — [MANUAL] blocks cannot be nested; if detected, flag as ERROR
|
|
31
30
|
|
|
32
31
|
### Conflict Types
|
|
33
32
|
|
|
@@ -4,58 +4,7 @@ type: static-reference
|
|
|
4
4
|
|
|
5
5
|
# Merge Conflict Rules
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
### Category 1: Modified Exports (signature/type change)
|
|
10
|
-
|
|
11
|
-
- **Action:** Re-extract affected export with fresh AST analysis
|
|
12
|
-
- **Merge:** Replace generated content for that export; preserve adjacent [MANUAL] blocks
|
|
13
|
-
- **Confidence:** Same tier as original (T1/T1-low/T2)
|
|
14
|
-
|
|
15
|
-
### Category 2: New Exports (added since last generation)
|
|
16
|
-
|
|
17
|
-
- **Action:** Extract new export with full AST analysis
|
|
18
|
-
- **Merge:** Append to appropriate section based on export type (function, type, class, constant)
|
|
19
|
-
- **Confidence:** Label with extraction tier confidence
|
|
20
|
-
- **[MANUAL] impact:** None — new content, no existing [MANUAL] blocks
|
|
21
|
-
|
|
22
|
-
### Category 3: Deleted Exports (removed from source)
|
|
23
|
-
|
|
24
|
-
- **Action:** Remove generated content for that export
|
|
25
|
-
- **Merge:** Check for attached [MANUAL] blocks before deletion
|
|
26
|
-
- **If [MANUAL] attached:** Flag as orphan, present to user for decision
|
|
27
|
-
- **If no [MANUAL]:** Auto-remove generated content
|
|
28
|
-
|
|
29
|
-
### Category 4: Moved Exports (file relocated)
|
|
30
|
-
|
|
31
|
-
- **Action:** Update provenance map file references
|
|
32
|
-
- **Merge:** Update file:line citations in generated content
|
|
33
|
-
- **Confidence:** Retain original tier if AST structure unchanged; downgrade to T1-low if structure changed
|
|
34
|
-
- **[MANUAL] impact:** Preserve — content unchanged, only provenance metadata updates
|
|
35
|
-
|
|
36
|
-
### Category 5: Renamed Exports (identifier changed)
|
|
37
|
-
|
|
38
|
-
- **Action:** Re-extract with new identifier
|
|
39
|
-
- **Merge:** Replace old identifier references in generated content
|
|
40
|
-
- **[MANUAL] impact:** Flag if [MANUAL] blocks reference old identifier name
|
|
41
|
-
|
|
42
|
-
## Merge Priority Order
|
|
43
|
-
|
|
44
|
-
1. Process deleted exports first (remove generated content, flag [MANUAL] orphans)
|
|
45
|
-
2. Process moved exports second (update references only)
|
|
46
|
-
3. Process renamed exports third (update identifiers)
|
|
47
|
-
4. Process modified exports fourth (re-extract and replace)
|
|
48
|
-
5. Process new exports last (append to sections)
|
|
49
|
-
|
|
50
|
-
## Stack Skill Merge Rules
|
|
51
|
-
|
|
52
|
-
For stack skills with multi-file outputs:
|
|
53
|
-
|
|
54
|
-
1. **SKILL.md:** Apply standard merge rules above
|
|
55
|
-
2. **references/{library}.md:** Merge per-library, preserving [MANUAL] blocks within each
|
|
56
|
-
3. **references/integrations/{pair}.md:** Merge per-integration-pair
|
|
57
|
-
4. **metadata.json:** Regenerate completely (no [MANUAL] support in JSON)
|
|
58
|
-
5. **context-snippet.md:** Regenerate completely (no [MANUAL] support — too concise)
|
|
7
|
+
> Change-category actions and the merge priority order (deleted → moved → renamed → modified → new, plus the gap-driven priorities) are specified authoritatively in `merge.md` §3. This reference carries only the one thing §3 does not: the conflict-resolution strategy table below.
|
|
59
8
|
|
|
60
9
|
## Conflict Resolution Strategies
|
|
61
10
|
|
|
@@ -10,21 +10,21 @@ mergeConflictRulesFile: 'references/merge-conflict-rules.md'
|
|
|
10
10
|
|
|
11
11
|
## STEP GOAL:
|
|
12
12
|
|
|
13
|
-
Merge freshly extracted export data into the existing SKILL.md content while preserving all [MANUAL] sections. Detect and resolve conflicts where regenerated content overlaps developer-authored content.
|
|
13
|
+
Merge freshly extracted export data into the existing SKILL.md content while preserving all [MANUAL] sections. Detect and resolve conflicts where regenerated content overlaps developer-authored content.
|
|
14
14
|
|
|
15
15
|
## Rules
|
|
16
16
|
|
|
17
17
|
- Focus only on merging extractions into existing skill content
|
|
18
18
|
- Never delete or modify [MANUAL] section content
|
|
19
|
-
- Write merged SKILL.md
|
|
19
|
+
- Write merged SKILL.md directly to disk at section 6b — Claude Code's Edit/Write tools commit on call, so there is no held-in-memory "edit plan" primitive; subsequent steps validate and verify against the on-disk files
|
|
20
20
|
- If [MANUAL] conflicts detected: halt and present to user. If clean merge: auto-proceed
|
|
21
21
|
|
|
22
|
-
##
|
|
22
|
+
## Steps
|
|
23
23
|
|
|
24
24
|
### 1. Load Merge Rules
|
|
25
25
|
|
|
26
26
|
Load {manualSectionRulesFile} for [MANUAL] detection and preservation patterns.
|
|
27
|
-
Load {mergeConflictRulesFile} for change
|
|
27
|
+
Load {mergeConflictRulesFile} for the conflict-resolution strategy table (the change-category actions and priority order live in §3 below).
|
|
28
28
|
|
|
29
29
|
### 2. Extract [MANUAL] Blocks
|
|
30
30
|
|
|
@@ -35,7 +35,7 @@ From the [MANUAL] inventory captured in step 01:
|
|
|
35
35
|
|
|
36
36
|
### 3. Apply Merge by Priority Order
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
Apply merge in the following priority order:
|
|
39
39
|
|
|
40
40
|
**Priority 1 — Process DELETED exports:**
|
|
41
41
|
- Remove generated content for deleted exports
|
|
@@ -146,20 +146,6 @@ Select: [K] Keep / [R] Remove / [E] Edit"
|
|
|
146
146
|
|
|
147
147
|
Process each conflict with user's decision.
|
|
148
148
|
|
|
149
|
-
### 5. Stack Skill Merge (Conditional)
|
|
150
|
-
|
|
151
|
-
**ONLY if skill_type == "stack":**
|
|
152
|
-
|
|
153
|
-
Apply the same merge process to each stack output file:
|
|
154
|
-
- `references/{library}.md` — merge per-library changes, preserve [MANUAL] blocks
|
|
155
|
-
- `references/integrations/{pair}.md` — merge per-integration-pair
|
|
156
|
-
- `metadata.json` — regenerate completely (no [MANUAL] support)
|
|
157
|
-
- `context-snippet.md` — regenerate completely (no [MANUAL] support)
|
|
158
|
-
|
|
159
|
-
Report stack file merge status for each file.
|
|
160
|
-
|
|
161
|
-
**If skill_type != "stack":** Skip with notice: "Individual skill — single file merge."
|
|
162
|
-
|
|
163
149
|
### 6. Compile Merge Results
|
|
164
150
|
|
|
165
151
|
Build merge result summary:
|
|
@@ -176,30 +162,22 @@ Merge Results:
|
|
|
176
162
|
manual_conflicts_resolved: [count]
|
|
177
163
|
manual_orphans_kept: [count]
|
|
178
164
|
manual_orphans_removed: [count]
|
|
179
|
-
|
|
180
|
-
stack_files_merged: [count] (if stack skill)
|
|
181
165
|
```
|
|
182
166
|
|
|
183
167
|
### 6b. Write Merged Files to Disk
|
|
184
168
|
|
|
185
|
-
Write the merged content produced by sections 3–
|
|
169
|
+
Write the merged content produced by sections 3–4 directly to disk now. Later steps read from these files for validation and verification. The write must happen exactly once, here.
|
|
186
170
|
|
|
187
171
|
**Write SKILL.md:**
|
|
188
172
|
- Use the `Edit` or `Write` tool to write merged SKILL.md content to `{skill_package}/SKILL.md`
|
|
189
173
|
- Preserve UTF-8 encoding
|
|
190
174
|
- If the source version detected during step 3 differs from the previous metadata version, create the new `{skill_package}` directory (`{skill_group}/{new_version}/`) first and write there — the previous version's directory is preserved on disk. Update `{skill_package}` in context to point at the new path.
|
|
191
175
|
|
|
192
|
-
**Write stack reference files (if `skill_type == "stack"`):**
|
|
193
|
-
- For each affected file from section 5, use `Edit` or `Write` to write:
|
|
194
|
-
- `references/{library}.md` with merged per-library content
|
|
195
|
-
- `references/integrations/{pair}.md` with merged per-integration content
|
|
196
|
-
- Preserve [MANUAL] blocks exactly as captured in section 2.
|
|
197
|
-
|
|
198
176
|
**Do NOT write here:**
|
|
199
177
|
- `metadata.json`, `provenance-map.json`, `evidence-report.md` — derived from merge + validation output, written by step 6 sections 2–4
|
|
200
178
|
- `context-snippet.md` — regenerated from the on-disk SKILL.md + metadata.json by step 6 section 5
|
|
201
179
|
|
|
202
|
-
**Halt-on-tool-failure:** If any `Edit`/`Write` call errors (permission denied, disk full, path invalid, etc.), halt and report the failure — do not proceed to step 5 validation. The skill package may be in a partial state and will need manual recovery before re-running update-skill.
|
|
180
|
+
**Halt-on-tool-failure:** If any `Edit`/`Write` call errors (permission denied, disk full, path invalid, etc.), halt with status `halted-for-write-failure` and report the failure — do not proceed to step 5 validation. The skill package may be in a partial state and will need manual recovery before re-running update-skill. In `{headless_mode}`, emit the halt envelope per SKILL.md §Headless (`error: {phase: "merge:write-skill-md", path: "{skill_package}/SKILL.md", reason: "..."}`).
|
|
203
181
|
|
|
204
182
|
### 7. Display Merge Summary
|
|
205
183
|
|
|
@@ -213,36 +191,14 @@ Write the merged content produced by sections 3–5 directly to disk now. Later
|
|
|
213
191
|
| [MANUAL] sections preserved | {count} |
|
|
214
192
|
| Conflicts resolved | {count} |"
|
|
215
193
|
|
|
216
|
-
### 8.
|
|
217
|
-
|
|
218
|
-
**If conflicts were resolved (user interaction occurred):**
|
|
219
|
-
|
|
220
|
-
Display: "**Merge complete with conflict resolution. Select:** [C] Continue to Validation"
|
|
221
|
-
|
|
222
|
-
#### Menu Handling Logic:
|
|
223
|
-
|
|
224
|
-
- IF C: Load, read entire file, then execute {nextStepFile}
|
|
225
|
-
- IF Any other: help user respond, then [Redisplay Menu Options](#8-present-menu-options)
|
|
226
|
-
|
|
227
|
-
#### EXECUTION RULES:
|
|
228
|
-
|
|
229
|
-
- ALWAYS halt and wait for user input after conflict resolution
|
|
230
|
-
- **GATE [default: C if clean merge]** — If `{headless_mode}` and merge is clean (no [MANUAL] conflicts): auto-proceed with [C] Continue, log: "headless: clean merge, auto-continue". **Also append to in-context `headless_decisions[]`** (surfaced via `SKF_UPDATE_RESULT_JSON` by step 7): `{gate: "merge.clean-merge-gate", default_action: "C", taken_action: "C", reason: "headless: clean merge, no conflicts to resolve"}`. If conflicts exist, HALT even in headless mode — conflicts require human judgment, and the headless_decisions[] array does NOT get a continue-on-conflict entry (the workflow status becomes `halted-for-manual-mismatch` instead).
|
|
231
|
-
- ONLY proceed when user selects 'C'
|
|
232
|
-
|
|
233
|
-
**If clean merge (no conflicts):**
|
|
234
|
-
|
|
235
|
-
Display: "**Clean merge — proceeding to validation...**"
|
|
236
|
-
|
|
237
|
-
#### Clean Merge Menu Handling Logic:
|
|
238
|
-
|
|
239
|
-
- Immediately load, read entire file, then execute {nextStepFile}
|
|
194
|
+
### 8. Gate to Validation
|
|
240
195
|
|
|
241
|
-
|
|
196
|
+
**Clean merge (no conflicts):** display "**Clean merge — proceeding to validation...**", then load, read the full file, and execute {nextStepFile} (auto-proceed).
|
|
242
197
|
|
|
243
|
-
|
|
198
|
+
**Conflicts were resolved (user interaction occurred):** present "**Merge complete with conflict resolution. Select:** [C] Continue to Validation" and wait for the user to confirm before loading {nextStepFile}.
|
|
244
199
|
|
|
245
|
-
|
|
200
|
+
**Headless (`{headless_mode}` true):**
|
|
246
201
|
|
|
247
|
-
|
|
202
|
+
- Clean merge → auto-continue and append to in-context `headless_decisions[]` (surfaced via `SKF_UPDATE_RESULT_JSON` by step 7): `{gate: "merge.clean-merge-gate", default_action: "C", taken_action: "C", reason: "headless: clean merge, no conflicts to resolve"}`.
|
|
203
|
+
- Conflicts present → halt even in headless mode (conflicts require human judgment): status `halted-for-manual-mismatch`, emitting the halt envelope per SKILL.md §Headless (`error: {phase: "merge:conflict-resolution", reason: "..."}`); no `headless_decisions[]` entry is added.
|
|
248
204
|
|
|
@@ -28,7 +28,7 @@ Perform tier-aware extraction on only the changed files identified in step 02, p
|
|
|
28
28
|
- Only extract files in the change manifest — do not touch unchanged files. **Exception (gap-driven mode):** §0a's Targeted Re-Extraction Branch also scans files listed in each manifest entry's `remediation_paths[]` to resolve citation-less Critical/High gaps.
|
|
29
29
|
- For each changed file, launch a subprocess for deep AST analysis (Pattern 2); if unavailable, extract sequentially
|
|
30
30
|
|
|
31
|
-
##
|
|
31
|
+
## Steps
|
|
32
32
|
|
|
33
33
|
### 0. Check for Gap-Driven Mode
|
|
34
34
|
|
|
@@ -45,7 +45,7 @@ uv run {checkWorkspaceDriftHelper} <source-root> \
|
|
|
45
45
|
[--allow-drift]
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
Pass `--allow-drift` only when the user provided `--allow-workspace-drift` to update-skill. The helper accepts `""` and `"local"` as the "no pinned commit" sentinels; it also auto-skips when `source_root` is not a git working tree (bare checkout, tarball extract, etc.).
|
|
48
|
+
Pass `--allow-drift` only when the user provided `--allow-workspace-drift` to update-skill. The helper accepts `""` and `"local"` as the "no pinned commit" sentinels; it also auto-skips when `source_root` is not a git working tree (bare checkout, tarball extract, etc.).
|
|
49
49
|
|
|
50
50
|
The helper emits a result envelope:
|
|
51
51
|
|
|
@@ -63,7 +63,7 @@ The helper emits a result envelope:
|
|
|
63
63
|
|
|
64
64
|
- **`ok` or `skipped`** (helper exit 0): log `log_message` and continue to bullet 1.
|
|
65
65
|
- **`overridden`** (helper exit 0): log `log_message`, surface a visible warning in the final report ("**Workspace drift accepted via --allow-workspace-drift** — spot-checks read HEAD {head_short_sha}, not pinned {pinned_commit}"), and continue to bullet 1. The override does not automatically re-pin `metadata.source_commit`; re-pinning is explicit user work (run the normal-mode update-skill flow against the same HEAD, or re-create the skill).
|
|
66
|
-
- **`mismatch`** (helper exit 2): HALT immediately with
|
|
66
|
+
- **`mismatch`** (helper exit 2): HALT immediately with status `halted-for-workspace-drift`. Display the helper's `halt_message` verbatim — it already substitutes `{pinned_commit}`, `{source_ref or "unset"}`, `{source_root}`, `{head_sha}`, and the suggested `git checkout` command. Do not proceed to bullet 1. Step-04 merge has not run; no partial writes. In `{headless_mode}`, emit the halt envelope per SKILL.md §Headless (`error: {phase: "re-extract:workspace-drift", path: "{source_root}", reason: "..."}`).
|
|
67
67
|
|
|
68
68
|
1. Use the provenance map already loaded in step 1 (at `{forge_version}/provenance-map.json`) — do not re-read
|
|
69
69
|
2. **Partition by change category, then iterate the export-bearing entries.** Entries that do not name an export skip the per-export verification below — they have no symbol to resolve against source:
|
|
@@ -173,7 +173,7 @@ The helper emits a result envelope:
|
|
|
173
173
|
c) Downgrade the gap(s) to Medium/Low/Info (accepts the degraded documentation outcome).
|
|
174
174
|
```
|
|
175
175
|
|
|
176
|
-
Exit with status `halted-for-remediation-path`. Step-04 merge has not run; no partial writes.
|
|
176
|
+
Exit with status `halted-for-remediation-path`. Step-04 merge has not run; no partial writes. In `{headless_mode}`, emit the halt envelope per SKILL.md §Headless (`error: {phase: "re-extract:targeted-reextraction", reason: "..."}`).
|
|
177
177
|
|
|
178
178
|
6. **Success summary** — record `targeted_reextraction: {resolved_count, files_scanned, exports_matched, tier}` in workflow context. The evidence report (step 6 §4) surfaces this alongside the verified / moved / missing tally.
|
|
179
179
|
|
|
@@ -223,7 +223,7 @@ The helper emits a result envelope:
|
|
|
223
223
|
|
|
224
224
|
**Forge tier (AST structural extraction):**
|
|
225
225
|
|
|
226
|
-
|
|
226
|
+
Load and follow the **AST Extraction Protocol** from `{extractionPatternsData}`. Use the decision tree based on the number of changed files: prefer MCP `find_code()` for small sets, `find_code_by_rule()` with scoped YAML rules for medium sets, and CLI `--json=stream` with line-by-line streaming for large sets. Never use `ast-grep --json` (without `=stream`) — it loads the entire result set into memory and will fail on large codebases.
|
|
227
227
|
|
|
228
228
|
- Extract: function signatures, type definitions, class members, exported constants
|
|
229
229
|
- Extract: parameter types, return types, JSDoc/docstring comments
|
|
@@ -243,17 +243,11 @@ The helper emits a result envelope:
|
|
|
243
243
|
|
|
244
244
|
**Skip authoritative doc paths.** Before iterating the change manifest, build a skip set from `promoted_docs_new[]` (populated by step 2 §1b) and any existing `file_entries[]` entries with `file_type: "doc"` from the provenance map. These are documentation files tracked for drift detection only — they must not reach AST extraction, which would produce ghost entries on non-code content. If a change manifest entry matches the skip set, skip it silently and continue; doc-type drift is handled by step 2 Category D and step 4 Priority 6/7.
|
|
245
245
|
|
|
246
|
-
|
|
246
|
+
For each remaining file in the change manifest with status MODIFIED, ADDED, or RENAMED, launch a subprocess that:
|
|
247
247
|
|
|
248
248
|
1. Loads the source file
|
|
249
249
|
2. Performs tier-appropriate extraction (Quick/Forge/Forge+/Deep)
|
|
250
|
-
3.
|
|
251
|
-
- Record: export name, type (function/class/type/constant), signature
|
|
252
|
-
- Record: file path, start line, end line
|
|
253
|
-
- Record: parameters with types (if function/method)
|
|
254
|
-
- Record: return type (if function/method)
|
|
255
|
-
- Record: JSDoc/docstring summary (if present)
|
|
256
|
-
- Label: confidence tier (T1/T1-low/T2)
|
|
250
|
+
3. Extract each export into the per-file return contract shown in bullet 4.
|
|
257
251
|
4. **Return contract.** Each extraction worker returns ONLY this per-file block — no prose, no commentary, no markdown fences (the parent strips wrapping fences before parsing). The shape is exactly the per-file record §4 aggregates (the `Per-file extractions` block, lines below), so the parent appends it verbatim rather than re-parsing free text:
|
|
258
252
|
|
|
259
253
|
```json
|
|
@@ -291,7 +285,7 @@ This helps the merge step (section 4) prioritize which changes are most likely t
|
|
|
291
285
|
|
|
292
286
|
CCC failures: skip ranking silently, all changes treated equally.
|
|
293
287
|
|
|
294
|
-
**Note on remote sources:** If `source_root` is a workspace clone, the CCC index may already exist from a prior forge and can be reused via `ccc search --refresh`. If the source is an ephemeral fallback clone, the clone path is not indexed by CCC — the search
|
|
288
|
+
**Note on remote sources:** If `source_root` is a workspace clone, the CCC index may already exist from a prior forge and can be reused via `ccc search --refresh`. If the source is an ephemeral fallback clone, the clone path is not indexed by CCC — the search returns empty results, so semantic ranking is skipped and all changes are treated equally.
|
|
295
289
|
|
|
296
290
|
**IF `tools.ccc` is false:** Skip this section silently.
|
|
297
291
|
|
|
@@ -356,16 +350,10 @@ Extraction Results:
|
|
|
356
350
|
|
|
357
351
|
**Proceeding to merge with existing skill...**"
|
|
358
352
|
|
|
359
|
-
### 6.
|
|
353
|
+
### 6. Route to Next Step
|
|
360
354
|
|
|
361
|
-
|
|
362
|
-
- Else, display "**Proceeding to merge...**" and after extraction results are compiled, immediately load, read entire file, then execute `{nextStepFile}`.
|
|
363
|
-
- This is an auto-proceed step with no user choices.
|
|
355
|
+
This step auto-proceeds — no user choices. Once all changed files are extracted and results compiled, load and fully read the next file, then execute it, per the branch that applies:
|
|
364
356
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
ONLY WHEN all changed files have been extracted and results compiled will you load the next file:
|
|
368
|
-
|
|
369
|
-
- `dry_run_mode == true` → load `report.md`. Report emits status `dry-run`. No artifact is modified on disk by this run.
|
|
370
|
-
- Otherwise → load `{nextStepFile}` (merge.md) to begin the merge operation.
|
|
357
|
+
- **`dry_run_mode == true`** → display "**Dry-run mode — skipping merge/validate/write.** Loading report..." and load `report.md` (NOT `{nextStepFile}`); it emits status `dry-run` describing what merge+write would have done. No artifact is modified on disk by this run.
|
|
358
|
+
- **Otherwise** → display "**Proceeding to merge...**" and load `{nextStepFile}` (merge.md) to begin the merge operation.
|
|
371
359
|
|
|
@@ -16,7 +16,7 @@ Present a comprehensive change summary showing what was updated, [MANUAL] sectio
|
|
|
16
16
|
- Present clear, actionable summary with next step recommendations
|
|
17
17
|
- Chains to the local health-check step via `{nextStepFile}` after completion — the user-facing summary is NOT the terminal step
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## Steps
|
|
20
20
|
|
|
21
21
|
### 1. Handle No-Change Shortcut
|
|
22
22
|
|
|
@@ -89,7 +89,7 @@ The headless envelope carries `status: "dry-run"`, `files_written: []`, the `hea
|
|
|
89
89
|
|
|
90
90
|
| Metric | Value |
|
|
91
91
|
|--------|-------|
|
|
92
|
-
| **Skill** | {skill_name}
|
|
92
|
+
| **Skill** | {skill_name} |
|
|
93
93
|
| **Forge Tier** | {tier} |
|
|
94
94
|
| **Mode** | {update_mode}{mode_fallback_note} |
|
|
95
95
|
| **Duration** | {step count} steps |
|
|
@@ -169,7 +169,6 @@ These signals also appear in `warnings[]` on the headless envelope; the Mode row
|
|
|
169
169
|
| `{resolved_skill_package}/metadata.json` | Updated |
|
|
170
170
|
| `{forge_version}/provenance-map.json` | Updated |
|
|
171
171
|
| `{forge_version}/evidence-report.md` | Appended |
|
|
172
|
-
| {stack reference files if applicable} | Updated |
|
|
173
172
|
|
|
174
173
|
Where `{resolved_skill_package}` = `{skills_output_folder}/{skill_name}/{version}/{skill_name}/` and `{forge_version}` = `{forge_data_folder}/{skill_name}/{version}/` — see `knowledge/version-paths.md`."
|
|
175
174
|
|
|
@@ -199,16 +198,24 @@ Write the result contract per `shared/references/output-contract-schema.md`: the
|
|
|
199
198
|
**Headless envelope (`SKF_UPDATE_RESULT_JSON`):** when `{headless_mode}` is true, ALSO emit a single-line JSON envelope to stdout prefixed with the literal `SKF_UPDATE_RESULT_JSON: `. Schema: `src/shared/scripts/schemas/skf-update-result-envelope.v1.json`. Construct the envelope from in-context state:
|
|
200
199
|
|
|
201
200
|
```json
|
|
202
|
-
SKF_UPDATE_RESULT_JSON: {"skf_update":{"status":"success|no-changes|halted-for-*|blocked","skill_name":"<name>","version":"<v>","previous_version":"<v>","update_mode":"normal|gap-driven|degraded","files_written":[...],"headless_decisions":[...],"warnings":[...],"error":null|{...}}}
|
|
201
|
+
SKF_UPDATE_RESULT_JSON: {"skf_update":{"status":"success|no-changes|detect-only|dry-run|halted-for-*|blocked","skill_name":"<name>","version":"<v>","previous_version":"<v>","update_mode":"normal|gap-driven|degraded","files_written":[...],"headless_decisions":[...],"warnings":[...],"error":null|{...}}}
|
|
203
202
|
```
|
|
204
203
|
|
|
205
|
-
- `headless_decisions[]` — verbatim from the in-context array populated by gates (init.md §confirmation, detect-changes.md §1b/§1c/§2.2, merge.md §gate). Each entry `{gate, default_action, taken_action, reason, evidence?}`. Empty when no gates auto-resolved (e.g. no-changes path skipped detect-changes' gates).
|
|
206
|
-
- `status` — single-field outcome for pipeline branching. `"success"` when the run wrote artifacts and produced no halts; `"no-changes"` when §1 short-circuited; one of the documented `halted-for-*` codes when a halt fired; `"blocked"` as the catch-all.
|
|
204
|
+
- `headless_decisions[]` — verbatim from the in-context array populated by gates (init.md §confirmation and §4 degraded-rebuild, detect-changes.md §1b/§1c/§2.2, merge.md §gate). Each entry `{gate, default_action, taken_action, reason, evidence?}`. Empty when no gates auto-resolved (e.g. no-changes path skipped detect-changes' gates).
|
|
205
|
+
- `status` — single-field outcome for pipeline branching. `"success"` when the run wrote artifacts and produced no halts; `"no-changes"` when §1 short-circuited; `"detect-only"` / `"dry-run"` for the §1a/§1b read-only exits; one of the documented `halted-for-*` codes when a halt fired; `"blocked"` as the catch-all. The full enum lives in the schema (this step emits the value already resolved in context).
|
|
207
206
|
- `error` — null on success or no-changes. Object `{phase, path?, reason}` describing the failure when a halt or write error fired. Pipelines branch on `error !== null` for non-zero exit semantics.
|
|
208
207
|
|
|
209
208
|
The headless envelope is the structured channel; the per-run JSON written above is the audit trail. Both coexist — the envelope is one line on stdout for grep-friendly consumption, the per-run JSON is the full record on disk.
|
|
210
209
|
|
|
210
|
+
**Post-finalization hook.** If `{onCompleteCommand}` (resolved in SKILL.md On Activation §3 from `workflow.on_complete`) is non-empty, invoke it after both result-JSON writes complete:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
{onCompleteCommand} --result-path={forge_version}/update-skill-result-latest.json
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Run it with a bounded timeout (default 60s). On success, log an Info note and continue; on non-zero exit, timeout, or any failure, append the reason to `warnings[]` (surfaced on the headless envelope) and continue. The hook must never fail the workflow — it is integration glue (notify a CI router, chain audit/export/test) orthogonal to the update outcome. Empty `{onCompleteCommand}` = no-op, no log entry.
|
|
217
|
+
|
|
211
218
|
### 6. Chain to Health Check
|
|
212
219
|
|
|
213
|
-
|
|
220
|
+
Once the change summary has been presented, the files-written list displayed, and the result contract saved, load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step — do not stop at the report even though it reads as final.
|
|
214
221
|
|