release-skill 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codebuddy-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +2 -2
- package/.kimi-plugin/plugin.json +1 -1
- package/CHANGELOG.md +31 -0
- package/INSTALL.md +2 -2
- package/INSTALL.zh-CN.md +2 -2
- package/README.md +13 -21
- package/README.zh-CN.md +14 -22
- package/adapters/claude/.claude-plugin/marketplace.json +1 -1
- package/adapters/claude/.claude-plugin/plugin.json +1 -1
- package/adapters/claude/bin/error-codes.json +1 -1
- package/adapters/claude/bin/kernel-protocol.json +1 -1
- package/adapters/claude/bin/registry.json +15 -1
- package/adapters/claude/bin/release-skill.bundle.mjs +38147 -23284
- package/adapters/claude/bin/rules.json +1 -1
- package/adapters/claude/schemas/.render-manifest.json +6 -6
- package/adapters/claude/schemas/release-plan.schema.json +401 -2
- package/adapters/claude/schemas/release-project.schema.json +291 -0
- package/adapters/claude/schemas/release-run.schema.json +59 -6
- package/adapters/claude/skills/release-config/SKILL.md +140 -0
- package/adapters/claude/skills/release-docs/SKILL.md +106 -0
- package/adapters/claude/skills/release-help/SKILL.md +39 -0
- package/adapters/claude/skills/release-marketplace/SKILL.md +147 -0
- package/adapters/claude/skills/release-publish/SKILL.md +25 -6
- package/adapters/claude/skills/release-verify/SKILL.md +10 -0
- package/adapters/codex/.codex-plugin/plugin.json +2 -2
- package/adapters/codex/bin/error-codes.json +1 -1
- package/adapters/codex/bin/kernel-protocol.json +1 -1
- package/adapters/codex/bin/registry.json +15 -1
- package/adapters/codex/bin/release-skill.bundle.mjs +38147 -23284
- package/adapters/codex/bin/rules.json +1 -1
- package/adapters/codex/schemas/.render-manifest.json +6 -6
- package/adapters/codex/schemas/release-plan.schema.json +401 -2
- package/adapters/codex/schemas/release-project.schema.json +291 -0
- package/adapters/codex/schemas/release-run.schema.json +59 -6
- package/adapters/codex/skills/release-config/SKILL.md +147 -0
- package/adapters/codex/skills/release-docs/SKILL.md +113 -0
- package/adapters/codex/skills/release-help/SKILL.md +39 -0
- package/adapters/codex/skills/release-marketplace/SKILL.md +154 -0
- package/adapters/codex/skills/release-publish/SKILL.md +25 -6
- package/adapters/codex/skills/release-verify/SKILL.md +10 -0
- package/adapters/kimi/.kimi-plugin/plugin.json +1 -1
- package/adapters/kimi/bin/error-codes.json +1 -1
- package/adapters/kimi/bin/kernel-protocol.json +1 -1
- package/adapters/kimi/bin/registry.json +15 -1
- package/adapters/kimi/bin/release-skill.bundle.mjs +38147 -23284
- package/adapters/kimi/bin/rules.json +1 -1
- package/adapters/kimi/schemas/.render-manifest.json +6 -6
- package/adapters/kimi/schemas/release-plan.schema.json +401 -2
- package/adapters/kimi/schemas/release-project.schema.json +291 -0
- package/adapters/kimi/schemas/release-run.schema.json +59 -6
- package/adapters/kimi/skills/release-config/SKILL.md +147 -0
- package/adapters/kimi/skills/release-docs/SKILL.md +113 -0
- package/adapters/kimi/skills/release-help/SKILL.md +39 -0
- package/adapters/kimi/skills/release-marketplace/SKILL.md +154 -0
- package/adapters/kimi/skills/release-publish/SKILL.md +25 -6
- package/adapters/kimi/skills/release-verify/SKILL.md +10 -0
- package/adapters/workbuddy/.codebuddy-plugin/plugin.json +1 -1
- package/adapters/workbuddy/bin/error-codes.json +1 -1
- package/adapters/workbuddy/bin/kernel-protocol.json +1 -1
- package/adapters/workbuddy/bin/registry.json +15 -1
- package/adapters/workbuddy/bin/release-skill.bundle.mjs +38147 -23284
- package/adapters/workbuddy/bin/rules.json +1 -1
- package/adapters/workbuddy/schemas/.render-manifest.json +6 -6
- package/adapters/workbuddy/schemas/release-plan.schema.json +401 -2
- package/adapters/workbuddy/schemas/release-project.schema.json +291 -0
- package/adapters/workbuddy/schemas/release-run.schema.json +59 -6
- package/adapters/workbuddy/skills/release-config/SKILL.md +140 -0
- package/adapters/workbuddy/skills/release-docs/SKILL.md +106 -0
- package/adapters/workbuddy/skills/release-help/SKILL.md +39 -0
- package/adapters/workbuddy/skills/release-marketplace/SKILL.md +147 -0
- package/adapters/workbuddy/skills/release-publish/SKILL.md +25 -6
- package/adapters/workbuddy/skills/release-verify/SKILL.md +10 -0
- package/bin/error-codes.json +1 -1
- package/bin/kernel-protocol.json +1 -1
- package/bin/registry.json +15 -1
- package/bin/release-skill-cli.mjs +235 -7
- package/bin/release-skill.bundle.mjs +38147 -23284
- package/bin/rules.json +1 -1
- package/package.json +5 -4
- package/platform-manifest.json +359 -0
- package/references/.render-manifest.json +9 -9
- package/references/02-project-config.md +35 -0
- package/references/05-evidence-and-errors.md +44 -0
- package/references/06-adapter-contract.md +13 -0
- package/schemas/.render-manifest.json +6 -6
- package/schemas/release-plan.schema.json +401 -2
- package/schemas/release-project.schema.json +291 -0
- package/schemas/release-run.schema.json +59 -6
- package/skills/release-config/SKILL.md +140 -0
- package/skills/release-docs/SKILL.md +106 -0
- package/skills/release-help/SKILL.md +39 -0
- package/skills/release-marketplace/SKILL.md +147 -0
- package/skills/release-publish/SKILL.md +25 -6
- package/skills/release-verify/SKILL.md +10 -0
- package/skills-src/release-config/SKILL.md +140 -0
- package/skills-src/release-docs/SKILL.md +106 -0
- package/skills-src/release-help/SKILL.md +39 -0
- package/skills-src/release-marketplace/SKILL.md +147 -0
- package/skills-src/release-publish/SKILL.md +25 -6
- package/skills-src/release-verify/SKILL.md +10 -0
- package/src/adapters/contract.mjs +5 -0
- package/src/adapters/distribute-git.mjs +625 -0
- package/src/adapters/plugin-marketplace.mjs +48 -4
- package/src/adapters/push-snapshot.mjs +12 -4
- package/src/commands/assess.mjs +171 -0
- package/src/commands/distribute.mjs +1078 -0
- package/src/commands/hooks.mjs +6 -1
- package/src/commands/lineage.mjs +616 -0
- package/src/commands/prepare.mjs +413 -72
- package/src/commands/route.mjs +686 -0
- package/src/commands/ship.mjs +45 -1
- package/src/commands/verify.mjs +176 -0
- package/src/core/baseline-advance.mjs +185 -0
- package/src/core/baseline.mjs +11 -1
- package/src/core/checkpoints.mjs +25 -0
- package/src/core/foundation-inflight.mjs +7 -0
- package/src/core/plan.mjs +12 -2
- package/src/core/postpublish.mjs +315 -0
|
@@ -2179,10 +2179,34 @@ export function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
2179
2179
|
// pluginRootForEntrySkill 在非 external 结构化 CLI 路径中已确定;
|
|
2180
2180
|
// external 路径或 human-attestation(null)时回退到 snapshotDirReal。
|
|
2181
2181
|
const pluginRootForSkill = pluginRootForEntrySkill || snapshotDirReal;
|
|
2182
|
-
|
|
2182
|
+
// Prefixed skill-directory fallback (0.5.1 entry-skill-prefix fix,
|
|
2183
|
+
// D-ACA-30 platform_physical_name): some candidate builds name
|
|
2184
|
+
// skill directories `skills/<plugin>-<entrySkill>/` instead of
|
|
2185
|
+
// the unprefixed `skills/<entrySkill>/`. Resolve the unprefixed
|
|
2186
|
+
// layout first; when it misses, retry with the plugin prefix.
|
|
2187
|
+
let entrySkillFile = resolve(pluginRootForSkill, 'skills', action.entrySkill, 'SKILL.md');
|
|
2188
|
+
let entrySkillExists = false;
|
|
2183
2189
|
try {
|
|
2184
2190
|
await stat(entrySkillFile);
|
|
2191
|
+
entrySkillExists = true;
|
|
2185
2192
|
} catch {
|
|
2193
|
+
if (action.plugin) {
|
|
2194
|
+
const prefixed = resolve(
|
|
2195
|
+
pluginRootForSkill,
|
|
2196
|
+
'skills',
|
|
2197
|
+
`${action.plugin}-${action.entrySkill}`,
|
|
2198
|
+
'SKILL.md',
|
|
2199
|
+
);
|
|
2200
|
+
try {
|
|
2201
|
+
await stat(prefixed);
|
|
2202
|
+
entrySkillFile = prefixed;
|
|
2203
|
+
entrySkillExists = true;
|
|
2204
|
+
} catch {
|
|
2205
|
+
// both layouts miss; report below
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
if (!entrySkillExists) {
|
|
2186
2210
|
const skillRel = relative(snapshotDirReal, entrySkillFile) || `skills/${action.entrySkill}/SKILL.md`;
|
|
2187
2211
|
return createResult({
|
|
2188
2212
|
actionType,
|
|
@@ -3476,8 +3500,11 @@ export function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
3476
3500
|
});
|
|
3477
3501
|
}
|
|
3478
3502
|
|
|
3479
|
-
// Verify entry skill exists as a regular file in install dir
|
|
3480
|
-
|
|
3503
|
+
// Verify entry skill exists as a regular file in install dir.
|
|
3504
|
+
// Prefixed skill-directory fallback (0.5.1 entry-skill-prefix fix):
|
|
3505
|
+
// mirror the preflight resolution — `skills/<entrySkill>` first,
|
|
3506
|
+
// then `skills/<plugin>-<entrySkill>` when the plugin is known.
|
|
3507
|
+
let entrySkillPath = resolve(installPath, 'skills', action.entrySkill, 'SKILL.md');
|
|
3481
3508
|
let entrySkillFound = false;
|
|
3482
3509
|
try {
|
|
3483
3510
|
const skillStat = await lstat(entrySkillPath);
|
|
@@ -3485,7 +3512,24 @@ export function createPluginMarketplaceAdapter(deps = {}) {
|
|
|
3485
3512
|
entrySkillFound = true;
|
|
3486
3513
|
}
|
|
3487
3514
|
} catch {
|
|
3488
|
-
// entry skill not found
|
|
3515
|
+
// entry skill not found in unprefixed layout
|
|
3516
|
+
}
|
|
3517
|
+
if (!entrySkillFound && action.plugin) {
|
|
3518
|
+
const prefixedPath = resolve(
|
|
3519
|
+
installPath,
|
|
3520
|
+
'skills',
|
|
3521
|
+
`${action.plugin}-${action.entrySkill}`,
|
|
3522
|
+
'SKILL.md',
|
|
3523
|
+
);
|
|
3524
|
+
try {
|
|
3525
|
+
const skillStat = await lstat(prefixedPath);
|
|
3526
|
+
if (skillStat.isFile() && !skillStat.isSymbolicLink()) {
|
|
3527
|
+
entrySkillPath = prefixedPath;
|
|
3528
|
+
entrySkillFound = true;
|
|
3529
|
+
}
|
|
3530
|
+
} catch {
|
|
3531
|
+
// both layouts miss; report below
|
|
3532
|
+
}
|
|
3489
3533
|
}
|
|
3490
3534
|
|
|
3491
3535
|
if (!entrySkillFound) {
|
|
@@ -58,10 +58,16 @@ function validateAction(action) {
|
|
|
58
58
|
githubRepositoryUrl(action.repo, action.githubHost);
|
|
59
59
|
|
|
60
60
|
const validStrategies = ['create-release-branch', 'advance-existing-branch', 'initialize-default-branch'];
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
// Explicit strategy is required (0.5.1 chain hardening): the historical
|
|
62
|
+
// `?? 'create-release-branch'` default silently produced orphan root
|
|
63
|
+
// commits whenever a plan omitted the strategy — the root cause of the
|
|
64
|
+
// synthetic-date root commits in the public repositories. The plan layer
|
|
65
|
+
// now guarantees the value; a missing value here fails closed instead of
|
|
66
|
+
// degrading to the orphan-root channel.
|
|
67
|
+
if (typeof action.branchStrategy !== 'string' || !validStrategies.includes(action.branchStrategy)) {
|
|
63
68
|
throw new Error(`branchStrategy must be one of: ${validStrategies.join(', ')}`);
|
|
64
69
|
}
|
|
70
|
+
const strategy = action.branchStrategy;
|
|
65
71
|
if (strategy === 'advance-existing-branch' || strategy === 'initialize-default-branch') {
|
|
66
72
|
if (!action.parentCommit || typeof action.parentCommit !== 'string') {
|
|
67
73
|
throw new Error(`${strategy} requires parentCommit`);
|
|
@@ -126,7 +132,8 @@ export function createPushSnapshotAdapter(deps = {}) {
|
|
|
126
132
|
{ shell: false },
|
|
127
133
|
);
|
|
128
134
|
const remoteTip = stdout.trim().split(/\s+/)[0] ?? '';
|
|
129
|
-
|
|
135
|
+
// Guaranteed by validateAction above (branchStrategy is required).
|
|
136
|
+
const strategy = action.branchStrategy;
|
|
130
137
|
|
|
131
138
|
if (strategy === 'advance-existing-branch') {
|
|
132
139
|
if (!remoteTip) {
|
|
@@ -173,7 +180,8 @@ export function createPushSnapshotAdapter(deps = {}) {
|
|
|
173
180
|
});
|
|
174
181
|
const gitDir = await inspectLocalObjects(action, context, exec);
|
|
175
182
|
const remoteUrl = githubRepositoryUrl(action.repo, action.githubHost);
|
|
176
|
-
|
|
183
|
+
// Guaranteed by validateAction above (branchStrategy is required).
|
|
184
|
+
const strategy = action.branchStrategy;
|
|
177
185
|
|
|
178
186
|
if (strategy === 'advance-existing-branch') {
|
|
179
187
|
await exec(
|
package/src/commands/assess.mjs
CHANGED
|
@@ -709,6 +709,171 @@ async function checkRemotePrerequisites(root, config, offline) {
|
|
|
709
709
|
return gaps;
|
|
710
710
|
}
|
|
711
711
|
|
|
712
|
+
/**
|
|
713
|
+
* Parse a semver-ish version string into comparable components.
|
|
714
|
+
*
|
|
715
|
+
* Accepts `major.minor.patch` with an optional `-prerelease` suffix (which
|
|
716
|
+
* sorts strictly below the same release triple). Returns null for anything
|
|
717
|
+
* that is not a version-shaped tag (candidate names like `0.1.27-candidate.2`
|
|
718
|
+
* parse fine; non-version tags are skipped).
|
|
719
|
+
*
|
|
720
|
+
* @param {string} version
|
|
721
|
+
* @returns {{ major: number, minor: number, patch: number, prerelease: string|null } | null}
|
|
722
|
+
*/
|
|
723
|
+
export function parseSemverVersion(version) {
|
|
724
|
+
const match = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?$/.exec(version);
|
|
725
|
+
if (!match) return null;
|
|
726
|
+
return {
|
|
727
|
+
major: Number(match[1]),
|
|
728
|
+
minor: Number(match[2]),
|
|
729
|
+
patch: Number(match[3]),
|
|
730
|
+
prerelease: match[4] ?? null,
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Compare two parsed semver values. Returns a negative/zero/positive number.
|
|
736
|
+
*
|
|
737
|
+
* @param {{ major: number, minor: number, patch: number, prerelease: string|null }} a
|
|
738
|
+
* @param {{ major: number, minor: number, patch: number, prerelease: string|null }} b
|
|
739
|
+
* @returns {number}
|
|
740
|
+
*/
|
|
741
|
+
export function compareSemverVersions(a, b) {
|
|
742
|
+
if (a.major !== b.major) return a.major - b.major;
|
|
743
|
+
if (a.minor !== b.minor) return a.minor - b.minor;
|
|
744
|
+
if (a.patch !== b.patch) return a.patch - b.patch;
|
|
745
|
+
if (a.prerelease && !b.prerelease) return -1;
|
|
746
|
+
if (!a.prerelease && b.prerelease) return 1;
|
|
747
|
+
return 0;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Describe a version-sequence gap between an immediate predecessor and the
|
|
752
|
+
* target version, or null when the step is contiguous.
|
|
753
|
+
*
|
|
754
|
+
* A gap means some version between the two was never released (e.g. the
|
|
755
|
+
* historical 0.1.1 -> 0.1.3 jump with no v0.1.2 tag). Pre-release steps
|
|
756
|
+
* never count as gaps by themselves.
|
|
757
|
+
*
|
|
758
|
+
* @param {{ major: number, minor: number, patch: number, prerelease: string|null }} prev
|
|
759
|
+
* @param {{ major: number, minor: number, patch: number, prerelease: string|null }} target
|
|
760
|
+
* @returns {string|null}
|
|
761
|
+
*/
|
|
762
|
+
export function describeVersionSequenceGap(prev, target) {
|
|
763
|
+
if (prev.major !== target.major) {
|
|
764
|
+
return prev.major + 1 < target.major
|
|
765
|
+
? `major ${prev.major}.x.x -> ${target.major}.x.x`
|
|
766
|
+
: null;
|
|
767
|
+
}
|
|
768
|
+
if (prev.minor !== target.minor) {
|
|
769
|
+
return prev.minor + 1 < target.minor
|
|
770
|
+
? `minor ${prev.major}.${prev.minor}.x -> ${target.major}.${target.minor}.x`
|
|
771
|
+
: null;
|
|
772
|
+
}
|
|
773
|
+
if (prev.patch !== target.patch) {
|
|
774
|
+
return prev.patch + 1 < target.patch
|
|
775
|
+
? `patch ${prev.major}.${prev.minor}.${prev.patch} -> ${target.major}.${target.minor}.${target.patch}`
|
|
776
|
+
: null;
|
|
777
|
+
}
|
|
778
|
+
return null;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/**
|
|
782
|
+
* Build a regex that extracts the version from a tag name following the
|
|
783
|
+
* unit's tagTemplate (`{version}` placeholder, regex-special characters
|
|
784
|
+
* escaped).
|
|
785
|
+
*
|
|
786
|
+
* @param {string} tagTemplate
|
|
787
|
+
* @returns {RegExp}
|
|
788
|
+
*/
|
|
789
|
+
export function buildTagVersionRegex(tagTemplate) {
|
|
790
|
+
const escaped = tagTemplate
|
|
791
|
+
.split('{version}')
|
|
792
|
+
.map((part) => part.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'))
|
|
793
|
+
.join('(.+)');
|
|
794
|
+
return new RegExp(`^${escaped}$`);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/**
|
|
798
|
+
* Check the public repository's release tag sequence for version jumps
|
|
799
|
+
* (0.5.1 chain hardening): when the immediate predecessor release is more
|
|
800
|
+
* than one version step below the current target version, register a
|
|
801
|
+
* warning-level gap `VERSION_SEQUENCE_GAP` (e.g. 0.1.1 -> 0.1.3 with no
|
|
802
|
+
* v0.1.2 tag). This never blocks: it records the observation for the human
|
|
803
|
+
* release planner.
|
|
804
|
+
*
|
|
805
|
+
* @param {string} root - Project root.
|
|
806
|
+
* @param {Object} config - The loaded project config.
|
|
807
|
+
* @returns {Promise<Object[]>} Array of warning gap entries.
|
|
808
|
+
*/
|
|
809
|
+
async function checkReleaseTagSequence(root, config) {
|
|
810
|
+
const gaps = [];
|
|
811
|
+
for (const unit of config.releaseUnits ?? []) {
|
|
812
|
+
const tagTemplate = unit.version?.tagTemplate;
|
|
813
|
+
if (!tagTemplate || !unit.publicRepo) continue;
|
|
814
|
+
|
|
815
|
+
const versionRegex = buildTagVersionRegex(tagTemplate);
|
|
816
|
+
const tagPattern = tagTemplate.replace('{version}', '*');
|
|
817
|
+
|
|
818
|
+
let stdout;
|
|
819
|
+
try {
|
|
820
|
+
({ stdout } = await execFile(
|
|
821
|
+
'git',
|
|
822
|
+
['ls-remote', `https://github.com/${unit.publicRepo}.git`, `refs/tags/${tagPattern}`],
|
|
823
|
+
{ cwd: root, shell: false, encoding: 'utf8', timeout: 15_000 },
|
|
824
|
+
));
|
|
825
|
+
} catch {
|
|
826
|
+
// Tag enumeration failure (network/auth/repo absent) is not a version
|
|
827
|
+
// gap and must not block; the remote-prerequisites npm check already
|
|
828
|
+
// reports unreachable registries where relevant.
|
|
829
|
+
continue;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
let targetVersion;
|
|
833
|
+
try {
|
|
834
|
+
const pkg = JSON.parse(await readFile(resolve(root, unit.source, 'package.json'), 'utf8'));
|
|
835
|
+
targetVersion = pkg.version;
|
|
836
|
+
} catch {
|
|
837
|
+
continue; // package metadata issues are reported elsewhere
|
|
838
|
+
}
|
|
839
|
+
const targetParsed = parseSemverVersion(targetVersion);
|
|
840
|
+
if (!targetParsed) continue;
|
|
841
|
+
|
|
842
|
+
let previousParsed = null;
|
|
843
|
+
let previousTag = null;
|
|
844
|
+
for (const line of stdout.trim().split('\n')) {
|
|
845
|
+
if (!line) continue;
|
|
846
|
+
const tagName = line.split('\t')[1]?.replace(/^refs\/tags\//, '');
|
|
847
|
+
if (!tagName) continue;
|
|
848
|
+
const versionMatch = versionRegex.exec(tagName);
|
|
849
|
+
if (!versionMatch) continue;
|
|
850
|
+
const parsed = parseSemverVersion(versionMatch[1]);
|
|
851
|
+
if (!parsed) continue;
|
|
852
|
+
// Prereleases never qualify as the "previous release" predecessor.
|
|
853
|
+
if (parsed.prerelease) continue;
|
|
854
|
+
if (compareSemverVersions(parsed, targetParsed) >= 0) continue;
|
|
855
|
+
if (previousParsed === null || compareSemverVersions(parsed, previousParsed) > 0) {
|
|
856
|
+
previousParsed = parsed;
|
|
857
|
+
previousTag = tagName;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
if (!previousParsed) continue;
|
|
862
|
+
const gap = describeVersionSequenceGap(previousParsed, targetParsed);
|
|
863
|
+
if (gap) {
|
|
864
|
+
gaps.push(createGap({
|
|
865
|
+
scope: GapScope.PROJECT,
|
|
866
|
+
category: GapCategory.REMOTE,
|
|
867
|
+
severity: Severity.WARNING,
|
|
868
|
+
code: 'VERSION_SEQUENCE_GAP',
|
|
869
|
+
message: `发布单元 "${unit.id}" 的版本序列存在跳号(${gap},上一发布标签 ${previousTag},目标版本 ${targetVersion}):请确认中间版本未发布是否是有意为之;发布链仍会以链式历史推进,但跳过的版本不会补造标签`,
|
|
870
|
+
file: '.release-skill/project.yaml',
|
|
871
|
+
}));
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
return gaps;
|
|
875
|
+
}
|
|
876
|
+
|
|
712
877
|
/**
|
|
713
878
|
* Perform a basic README structural check.
|
|
714
879
|
*
|
|
@@ -967,6 +1132,12 @@ export async function assessProject(options) {
|
|
|
967
1132
|
const remoteGaps = await checkRemotePrerequisites(root, config, offline);
|
|
968
1133
|
allGaps.push(...remoteGaps);
|
|
969
1134
|
|
|
1135
|
+
// --- 7b. Release tag sequence (online only; warning, never blocking) ---
|
|
1136
|
+
if (!offline) {
|
|
1137
|
+
const tagSequenceGaps = await checkReleaseTagSequence(root, config);
|
|
1138
|
+
allGaps.push(...tagSequenceGaps);
|
|
1139
|
+
}
|
|
1140
|
+
|
|
970
1141
|
// --- 8. README structure check ---
|
|
971
1142
|
const readmeGaps = await checkReadmeStructure(root, config);
|
|
972
1143
|
allGaps.push(...readmeGaps);
|