@event4u/agent-config 9.11.0 → 9.13.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/CHANGELOG.md +80 -204
- package/README.md +8 -1
- package/dist/agent-src/commands/fix/ci.md +29 -0
- package/dist/agent-src/commands/pr/create.md +60 -0
- package/dist/agent-src/contexts/authority/kernel-rule-edits.md +18 -2
- package/dist/agent-src/rules/active-remediation.md +0 -2
- package/dist/agent-src/rules/architecture.md +0 -1
- package/dist/agent-src/rules/artifact-drafting-protocol.md +0 -4
- package/dist/agent-src/rules/autonomous-execution.md +1 -2
- package/dist/agent-src/rules/broken-access-control.md +0 -2
- package/dist/agent-src/rules/code-comment-discipline.md +0 -3
- package/dist/agent-src/rules/code-provenance.md +0 -3
- package/dist/agent-src/rules/communication-through-line.md +2 -3
- package/dist/agent-src/rules/content-quoting-floor.md +0 -2
- package/dist/agent-src/rules/context-hygiene.md +1 -3
- package/dist/agent-src/rules/decision-revisit-gate.md +0 -2
- package/dist/agent-src/rules/design-fidelity.md +30 -1
- package/dist/agent-src/rules/domain-adoption-policy.md +0 -3
- package/dist/agent-src/rules/downstream-changes.md +10 -1
- package/dist/agent-src/rules/external-reference-deep-dive.md +0 -7
- package/dist/agent-src/rules/fast-path-marker-visibility.md +0 -1
- package/dist/agent-src/rules/git-history-discipline.md +0 -7
- package/dist/agent-src/rules/guidelines.md +0 -2
- package/dist/agent-src/rules/improve-before-implement.md +4 -2
- package/dist/agent-src/rules/invite-challenge.md +0 -4
- package/dist/agent-src/rules/linked-projects-onboarding-gate.md +0 -2
- package/dist/agent-src/rules/markdown-safe-codeblocks.md +0 -1
- package/dist/agent-src/rules/minimal-safe-diff.md +2 -2
- package/dist/agent-src/rules/missing-tool-handling.md +0 -1
- package/dist/agent-src/rules/no-attribution-footers.md +0 -3
- package/dist/agent-src/rules/no-decorative-emojis-in-git-surfaces.md +8 -5
- package/dist/agent-src/rules/no-pr-progress-comments.md +1 -3
- package/dist/agent-src/rules/no-roadmap-references.md +0 -2
- package/dist/agent-src/rules/output-discipline.md +0 -1
- package/dist/agent-src/rules/prefer-enums-over-literals.md +0 -2
- package/dist/agent-src/rules/preservation-guard.md +0 -3
- package/dist/agent-src/rules/role-mode-adherence.md +0 -1
- package/dist/agent-src/rules/secret-vcs-guard.md +0 -2
- package/dist/agent-src/rules/senior-engineering-discipline.md +0 -2
- package/dist/agent-src/rules/session-canary.md +0 -2
- package/dist/agent-src/rules/size-enforcement.md +0 -5
- package/dist/agent-src/rules/source-confidentiality.md +0 -3
- package/dist/agent-src/rules/source-discovery-gate.md +0 -2
- package/dist/agent-src/rules/think-before-action.md +3 -3
- package/dist/agent-src/rules/token-budget-discipline.md +0 -1
- package/dist/agent-src/rules/token-efficiency.md +1 -2
- package/dist/agent-src/rules/tool-safety.md +0 -1
- package/dist/agent-src/rules/user-interaction.md +0 -3
- package/dist/agent-src/rules/user-interrupt-priority.md +0 -1
- package/dist/agent-src/skills/agent-docs-writing/SKILL.md +8 -0
- package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +1 -0
- package/dist/agent-src/skills/analysis-skill-router/SKILL.md +55 -86
- package/dist/agent-src/skills/character-consistency/SKILL.md +7 -4
- package/dist/agent-src/skills/decision-record/SKILL.md +8 -0
- package/dist/agent-src/skills/design-intelligence/SKILL.md +27 -1
- package/dist/agent-src/skills/design-intelligence/data/font-pairings-reference.csv +74 -74
- package/dist/agent-src/skills/design-intelligence/data/manifest.json +2 -0
- package/dist/agent-src/skills/design-review/SKILL.md +11 -0
- package/dist/agent-src/skills/design-system-capture/reference/design-system-json.md +8 -0
- package/dist/agent-src/skills/design-tokens/scripts/tokens.ts +0 -7
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +34 -3
- package/dist/agent-src/skills/fe-design/SKILL.md +10 -0
- package/dist/agent-src/skills/motion-choreographer/SKILL.md +7 -4
- package/dist/agent-src/skills/overbuild-review-lens/SKILL.md +201 -0
- package/dist/agent-src/skills/performance/SKILL.md +14 -0
- package/dist/agent-src/skills/pixar-storyteller/SKILL.md +8 -5
- package/dist/agent-src/skills/scene-expander/SKILL.md +9 -6
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +10 -0
- package/dist/agent-src/skills/typography-system/SKILL.md +55 -11
- package/dist/agent-src/skills/ui-apply-generic/SKILL.md +180 -0
- package/dist/agent-src/skills/universal-project-analysis/SKILL.md +14 -37
- package/dist/agent-src/skills/video-director/SKILL.md +9 -6
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +162 -17
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +118 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +49 -6
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +9 -5
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +182 -29
- package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +311 -24
- package/dist/agent-src/templates/scripts/work_engine/state.ts +55 -0
- package/dist/cli-delegate/chunk-523HCFYO.js +90 -0
- package/dist/cli-delegate/{chunk-IR7P7JWA.js → chunk-A3HJ6NTI.js} +271 -59
- package/dist/cli-delegate/chunk-EJYIGZ3T.js +125 -0
- package/dist/cli-delegate/{chunk-RDGRHAAB.js → chunk-HYWSRNUX.js} +6 -86
- package/dist/cli-delegate/{chunk-YMFO6FDN.js → chunk-QFKQLQ7X.js} +313 -81
- package/dist/cli-delegate/{chunk-4SV3XGFA.js → chunk-TEGJU2JX.js} +7 -9
- package/dist/cli-delegate/chunk-TJIAM5FW.js +133 -0
- package/dist/cli-delegate/cmd_conformance.js +4 -7
- package/dist/cli-delegate/cmd_doctor.js +3 -5
- package/dist/cli-delegate/cmd_explain.js +153 -85
- package/dist/cli-delegate/cmd_export.js +5 -3
- package/dist/cli-delegate/cmd_fleet.js +2 -1
- package/dist/cli-delegate/cmd_preflight.js +6 -123
- package/dist/cli-delegate/cmd_prune.js +5 -3
- package/dist/cli-delegate/cmd_settings_migrate.js +5 -3
- package/dist/cli-delegate/cmd_sync.js +5 -3
- package/dist/cli-delegate/cmd_uninstall.js +6 -5
- package/dist/cli-delegate/cmd_validate.js +5 -3
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +116 -72
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +3 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +7 -5
- package/dist/discovery/trust-report.md +2 -2
- package/dist/discovery/workspaces.json +6 -4
- package/dist/hooks/dispatch.js +174 -13
- package/dist/install/install.mjs +605 -412
- package/dist/install/ruleInScope.js +123 -0
- package/dist/install/ruleInScope.js.map +1 -0
- package/dist/install/rule_scope.js +2 -2
- package/dist/install/rule_scope.js.map +1 -1
- package/dist/install/wizard-plan.js +10 -1
- package/dist/install/wizard-plan.js.map +1 -1
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +710 -2491
- package/dist/router.json +1 -1
- package/dist/scripts/condense.js +8 -24
- package/dist/scripts/condense.js.map +1 -1
- package/docs/MIGRATION.md +1 -1
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +71 -0
- package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +24 -1
- package/docs/guidelines/code-clarity.md +9 -2
- package/docs/guidelines/design-fidelity-mechanics.md +58 -0
- package/llms.txt +63 -27
- package/package.json +4 -4
- package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +162 -17
- package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +118 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +49 -6
- package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +9 -5
- package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +182 -29
- package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +311 -24
- package/src/agent-src/templates/scripts/work_engine/state.ts +55 -0
- package/src/config/agent-settings.template.yml +8 -0
- package/src/install/ruleInScope.ts +133 -0
- package/src/install/rule_scope.ts +2 -2
- package/src/install/wizard-plan.ts +11 -1
- package/src/scripts/_lib/counted_probe.ts +142 -0
- package/src/scripts/_lib/global_deploy_inventory.ts +38 -2
- package/src/scripts/_lib/overbuild_lens_contract.ts +196 -0
- package/src/scripts/_lib/release_scope.ts +207 -0
- package/src/scripts/ai_council/stance_tally.ts +37 -2
- package/src/scripts/audit_auto_rules.ts +9 -9
- package/src/scripts/audit_likelihood.ts +3 -3
- package/src/scripts/audit_overlap.ts +2 -2
- package/src/scripts/audit_skill_overlap.ts +233 -95
- package/src/scripts/audit_skill_overlap_allowlist.json +4 -0
- package/src/scripts/build_proof.ts +15 -1
- package/src/scripts/check_dependency_floors.ts +16 -6
- package/src/scripts/check_gate_coverage.ts +6 -6
- package/src/scripts/check_installer_import_purity.ts +295 -0
- package/src/scripts/check_kernel_rule_bundle.ts +5 -4
- package/src/scripts/check_token_quality_golden.ts +0 -18
- package/src/scripts/code_graph/loader.ts +35 -6
- package/src/scripts/compile_router.ts +3 -8
- package/src/scripts/condense.ts +9 -30
- package/src/scripts/explain_run.ts +0 -1
- package/src/scripts/generate_pack_manifests.ts +3 -20
- package/src/scripts/hooks/block_kernel_rule_writes.ts +145 -10
- package/src/scripts/hooks/block_no_verify.ts +101 -0
- package/src/scripts/install-hooks.sh +36 -4
- package/src/scripts/install.ts +210 -5
- package/src/scripts/lint_agent_security.ts +5 -4
- package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
- package/src/scripts/lint_regression.ts +92 -1
- package/src/scripts/lint_skill_descriptions.ts +93 -5
- package/src/scripts/lint_ui_stack_bundles.ts +31 -0
- package/src/scripts/project_thin_rules.ts +2 -2
- package/src/scripts/release.ts +107 -3
- package/src/scripts/resolve_lint_scope.ts +53 -0
- package/src/scripts/router_telemetry.ts +0 -5
- package/src/scripts/runtime_dispatcher.ts +40 -0
- package/src/scripts/schemas/pack.schema.json +1 -5
- package/src/scripts/schemas/rule.schema.json +1 -2
- package/src/scripts/self_review_gate.ts +15 -73
- package/src/scripts/skill_linter.ts +93 -11
- package/src/scripts/sweep_dead_scan_roots.ts +550 -0
- package/src/scripts/trigger_coverage.ts +11 -37
- package/dist/cli-delegate/chunk-7DSAMZFU.js +0 -356
- package/dist/cli-delegate/chunk-BJGXZNPM.js +0 -266
- package/dist/cli-delegate/chunk-TFG57JJM.js +0 -1969
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"$comment": "Generated by scripts/generate_pack_manifests.py and validated on load by scripts/validate_pack_yaml.py. Schema introduced in road-to-6.0.0-D Phase 0 Step 2. `dependencies` is the artefact-level include graph (skills/rules the pack's commands reference); `requires` is the pack-level hard-dependency graph (must be acyclic — enforced by scripts/lint_pack_dependencies.py).",
|
|
7
7
|
"type": "object",
|
|
8
8
|
"additionalProperties": false,
|
|
9
|
-
"required": ["id", "
|
|
9
|
+
"required": ["id", "artefact_count"],
|
|
10
10
|
"properties": {
|
|
11
11
|
"id": {
|
|
12
12
|
"type": "string",
|
|
@@ -58,10 +58,6 @@
|
|
|
58
58
|
"trust_level_default": {
|
|
59
59
|
"type": "string"
|
|
60
60
|
},
|
|
61
|
-
"version": {
|
|
62
|
-
"type": "string",
|
|
63
|
-
"minLength": 1
|
|
64
|
-
},
|
|
65
61
|
"artefact_count": {
|
|
66
62
|
"type": "integer",
|
|
67
63
|
"minimum": 0
|
|
@@ -63,14 +63,13 @@
|
|
|
63
63
|
"properties": {
|
|
64
64
|
"keyword": {"type": "string"},
|
|
65
65
|
"phrase": {"type": "string"},
|
|
66
|
-
"intent": {"type": "string"},
|
|
67
66
|
"file_pattern": {"type": "string"},
|
|
68
67
|
"path_prefix": {"type": "string", "description": "Literal path-prefix match pattern the host evaluates against the file the agent is editing — NOT a file reference. The rewriter leaves it verbatim. Source-of-truth rules that must fire on edits under `.agent-src.uncondensed/` keep that prefix here (the prefix ban applies only to `load_context:` and body links — see road-to-path-fixes.md P2.2 / AI-Council 2026-05-06)."},
|
|
69
68
|
"command": {"type": "string"},
|
|
70
69
|
"reason": {"type": "string"}
|
|
71
70
|
}
|
|
72
71
|
},
|
|
73
|
-
"description": "Router activation triggers (Phase 3 of road-to-kernel-and-router.md). Forbidden on kernel rules, required on non-kernel rules. Schema: docs/contracts/rule-router.md."
|
|
72
|
+
"description": "Router activation triggers (Phase 3 of road-to-kernel-and-router.md). Forbidden on kernel rules, required on non-kernel rules. Five match keys: keyword, phrase, file_pattern, path_prefix, command. `intent` was removed — it never auto-matched at runtime and only gave rule authors false confidence that an activation path existed; additionalProperties:false now rejects it. Schema: docs/contracts/rule-router.md."
|
|
74
73
|
},
|
|
75
74
|
"routes_to": {
|
|
76
75
|
"type": "array",
|
|
@@ -125,79 +125,21 @@ function changedLineCount(baseRef: string, files: string[], cwd: string = REPO_R
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
// ── Release-PR detection (road-to-feedback-9.2.0-followups Phase 3) ────
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
for (const line of addedLines) {
|
|
144
|
-
const changelogMatch = /^##\s*\[(\d+\.\d+\.\d+)\]/.exec(line);
|
|
145
|
-
if (changelogMatch) changelogVersion = changelogMatch[1] ?? null;
|
|
146
|
-
const packageMatch = /^\s*"version"\s*:\s*"(\d+\.\d+\.\d+)"/.exec(line);
|
|
147
|
-
if (packageMatch) packageVersion = packageMatch[1] ?? null;
|
|
148
|
-
}
|
|
149
|
-
if (changelogVersion && packageVersion && changelogVersion === packageVersion) {
|
|
150
|
-
return changelogVersion;
|
|
151
|
-
}
|
|
152
|
-
return null;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
function releaseDetectionPatch(baseRef: string, cwd: string): string {
|
|
156
|
-
const r = spawnSync('git', ['diff', `${baseRef}...HEAD`, '--', 'CHANGELOG.md', 'package.json'], {
|
|
157
|
-
cwd,
|
|
158
|
-
encoding: 'utf8',
|
|
159
|
-
maxBuffer: 8 * 1024 * 1024,
|
|
160
|
-
});
|
|
161
|
-
return (r.stdout ?? '').toString();
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/** Impure wrapper: collects the packaging patch via git, then detects. */
|
|
165
|
-
export function detectReleaseVersionFromGit(baseRef: string, cwd: string = REPO_ROOT): string | null {
|
|
166
|
-
return detectReleaseVersion(releaseDetectionPatch(baseRef, cwd));
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
/** `major.minor.patch`, tolerating an optional `v` prefix; null if not semver-shaped. */
|
|
170
|
-
function parseSemver(raw: string): [number, number, number] | null {
|
|
171
|
-
const m = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(raw.trim());
|
|
172
|
-
if (!m) return null;
|
|
173
|
-
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function semverLessThan(a: [number, number, number], b: [number, number, number]): boolean {
|
|
177
|
-
const [aMajor, aMinor, aPatch] = a;
|
|
178
|
-
const [bMajor, bMinor, bPatch] = b;
|
|
179
|
-
if (aMajor !== bMajor) return aMajor < bMajor;
|
|
180
|
-
if (aMinor !== bMinor) return aMinor < bMinor;
|
|
181
|
-
return aPatch < bPatch;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
* Highest semver-shaped tag strictly below `version`, or null if none. Pure
|
|
186
|
-
* over the supplied tag list — no git call. Non-semver tags (branch-backup
|
|
187
|
-
* names etc.) are ignored rather than throwing.
|
|
188
|
-
*/
|
|
189
|
-
export function pickPreviousTag(version: string, tags: readonly string[]): string | null {
|
|
190
|
-
const target = parseSemver(version);
|
|
191
|
-
if (!target) return null;
|
|
192
|
-
let best: { raw: string; parsed: [number, number, number] } | null = null;
|
|
193
|
-
for (const raw of tags) {
|
|
194
|
-
const parsed = parseSemver(raw);
|
|
195
|
-
if (!parsed) continue;
|
|
196
|
-
if (!semverLessThan(parsed, target)) continue;
|
|
197
|
-
if (!best || semverLessThan(best.parsed, parsed)) best = { raw, parsed };
|
|
198
|
-
}
|
|
199
|
-
return best ? best.raw : null;
|
|
200
|
-
}
|
|
128
|
+
//
|
|
129
|
+
// Moved to `_lib/release_scope.ts` so the release-aware content checks reuse
|
|
130
|
+
// this detector instead of re-deriving it (road-to-release-shape-honesty
|
|
131
|
+
// Phase 1). Imported for local use AND re-exported — a bare `export … from`
|
|
132
|
+
// would not bind the names in this module's scope. Public surface unchanged.
|
|
133
|
+
import {
|
|
134
|
+
detectReleaseVersionFromGit,
|
|
135
|
+
pickPreviousTag,
|
|
136
|
+
} from './_lib/release_scope.js';
|
|
137
|
+
|
|
138
|
+
export {
|
|
139
|
+
detectReleaseVersion,
|
|
140
|
+
detectReleaseVersionFromGit,
|
|
141
|
+
pickPreviousTag,
|
|
142
|
+
} from './_lib/release_scope.js';
|
|
201
143
|
|
|
202
144
|
function listGitTags(cwd: string): string[] {
|
|
203
145
|
const r = spawnSync('git', ['tag'], { cwd, encoding: 'utf8' });
|
|
@@ -30,7 +30,6 @@
|
|
|
30
30
|
* 2 = errors
|
|
31
31
|
* 3 = internal error / structural malice
|
|
32
32
|
*/
|
|
33
|
-
import { spawnSync } from 'node:child_process';
|
|
34
33
|
import * as fs from 'node:fs';
|
|
35
34
|
import * as path from 'node:path';
|
|
36
35
|
import process from 'node:process';
|
|
@@ -44,6 +43,9 @@ import {
|
|
|
44
43
|
type YamlValue,
|
|
45
44
|
} from './validate_frontmatter.js';
|
|
46
45
|
import { artefact_roots, resolve_logical } from './_lib/agent_src.js';
|
|
46
|
+
import { ProbeOverflowError, runCountedProbe } from './_lib/counted_probe.js';
|
|
47
|
+
import { resolveContentLintScope } from './_lib/release_scope.js';
|
|
48
|
+
import { DeadScopeError, assertScanned } from './_lib/scan_scope.js';
|
|
47
49
|
|
|
48
50
|
// __file__ equivalent for repo-root derivation (mirrors Python
|
|
49
51
|
// `Path(__file__).resolve().parent.parent.parent` = <repo>/src/scripts → repo).
|
|
@@ -166,10 +168,10 @@ const DOUBLE_BLANK_PATTERN = /\n{3,}/;
|
|
|
166
168
|
const VALID_RULE_TYPES = new Set(['always', 'auto', 'manual']);
|
|
167
169
|
const VALID_RULE_SOURCES = new Set(['package', 'project']);
|
|
168
170
|
|
|
171
|
+
// `intent` was removed — see compile_router.ts's copy of this allowlist.
|
|
169
172
|
const ROUTER_ALLOWED_TRIGGER_KEYS = new Set([
|
|
170
173
|
'keyword',
|
|
171
174
|
'phrase',
|
|
172
|
-
'intent',
|
|
173
175
|
'file_pattern',
|
|
174
176
|
'path_prefix',
|
|
175
177
|
'command',
|
|
@@ -2428,20 +2430,42 @@ export function gather_candidate_files_under(srcRoot: string): string[] {
|
|
|
2428
2430
|
return sortedUnique(out);
|
|
2429
2431
|
}
|
|
2430
2432
|
|
|
2431
|
-
|
|
2433
|
+
/**
|
|
2434
|
+
* The scope `--changed` resolved, for the caller to report.
|
|
2435
|
+
*
|
|
2436
|
+
* Exported alongside the file list because a release PR silently widening its
|
|
2437
|
+
* own scope would be as opaque as the blindness it fixes — the caller prints
|
|
2438
|
+
* this line.
|
|
2439
|
+
*/
|
|
2440
|
+
export let last_changed_scope_reason = '';
|
|
2441
|
+
|
|
2442
|
+
/**
|
|
2443
|
+
* Candidate files changed against the resolved base.
|
|
2444
|
+
*
|
|
2445
|
+
* The base is release-aware (`_lib/release_scope.ts`): on a release PR it
|
|
2446
|
+
* widens to `previous_release_tag...HEAD`, because a release PR's own diff is
|
|
2447
|
+
* the version bump and the changelog — everything substantive landed in the
|
|
2448
|
+
* commits before the cut. Scoped to the PR's own file list this returned
|
|
2449
|
+
* nothing on a 179-commit release, and the gate reported
|
|
2450
|
+
* "0 skills checked, INCONCLUSIVE" and passed.
|
|
2451
|
+
*
|
|
2452
|
+
* `since` pins the base explicitly and wins over detection.
|
|
2453
|
+
*/
|
|
2454
|
+
export function gather_changed_candidate_files(root: string, since?: string | null): string[] {
|
|
2455
|
+
const scope = resolveContentLintScope({ cwd: root, since: since ?? null });
|
|
2456
|
+
last_changed_scope_reason = scope.reason;
|
|
2432
2457
|
const diffCommands = [
|
|
2433
|
-
['git', 'diff', '--name-only',
|
|
2458
|
+
['git', 'diff', '--name-only', `${scope.base}...HEAD`],
|
|
2434
2459
|
['git', 'diff', '--name-only', '--cached', 'HEAD'],
|
|
2435
2460
|
['git', 'diff', '--name-only', 'HEAD'],
|
|
2436
2461
|
];
|
|
2437
2462
|
try {
|
|
2438
2463
|
let rawLines: string[] = [];
|
|
2439
2464
|
for (const cmd of diffCommands) {
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
if (result.status === 0 && (result.stdout ?? '').trim()) {
|
|
2465
|
+
// A truncated diff would silently shrink the change set — the same
|
|
2466
|
+
// degrade-to-zero shape this roadmap closes elsewhere.
|
|
2467
|
+
const result = runCountedProbe(cmd[0] as string, cmd.slice(1), { cwd: root });
|
|
2468
|
+
if (result.ok && result.stdout.trim()) {
|
|
2445
2469
|
rawLines = splitlines(result.stdout);
|
|
2446
2470
|
break;
|
|
2447
2471
|
}
|
|
@@ -2479,7 +2503,15 @@ export function gather_changed_candidate_files(root: string): string[] {
|
|
|
2479
2503
|
}
|
|
2480
2504
|
}
|
|
2481
2505
|
return sortedUnique(files);
|
|
2482
|
-
} catch {
|
|
2506
|
+
} catch (exc) {
|
|
2507
|
+
// An overflowed diff is not an empty diff. Everything else (a shallow
|
|
2508
|
+
// clone with no `origin/main`, a detached worktree) legitimately has no
|
|
2509
|
+
// resolvable change set and keeps the historical empty-list degrade.
|
|
2510
|
+
if (exc instanceof ProbeOverflowError) {
|
|
2511
|
+
throw exc;
|
|
2512
|
+
}
|
|
2513
|
+
last_changed_scope_reason =
|
|
2514
|
+
`change set unresolvable (${exc instanceof Error ? exc.message : String(exc)})`;
|
|
2483
2515
|
return [];
|
|
2484
2516
|
}
|
|
2485
2517
|
}
|
|
@@ -4082,6 +4114,8 @@ interface Args {
|
|
|
4082
4114
|
report: boolean;
|
|
4083
4115
|
repoRoot: string;
|
|
4084
4116
|
quiet: boolean;
|
|
4117
|
+
/** Explicit diff base for `--changed`; wins over release detection. */
|
|
4118
|
+
since: string | null;
|
|
4085
4119
|
}
|
|
4086
4120
|
|
|
4087
4121
|
export function parse_args(argv: string[]): Args {
|
|
@@ -4095,6 +4129,7 @@ export function parse_args(argv: string[]): Args {
|
|
|
4095
4129
|
condensationQuality: false,
|
|
4096
4130
|
strictWarnings: false,
|
|
4097
4131
|
report: false,
|
|
4132
|
+
since: null,
|
|
4098
4133
|
repoRoot: '.',
|
|
4099
4134
|
quiet: false,
|
|
4100
4135
|
};
|
|
@@ -4104,6 +4139,15 @@ export function parse_args(argv: string[]): Args {
|
|
|
4104
4139
|
args.all = true;
|
|
4105
4140
|
} else if (a === '--changed') {
|
|
4106
4141
|
args.changed = true;
|
|
4142
|
+
} else if (a === '--since') {
|
|
4143
|
+
const v = argv[i + 1];
|
|
4144
|
+
i += 1;
|
|
4145
|
+
if (v === undefined || v.startsWith('--')) {
|
|
4146
|
+
throw new ArgError('argument --since: expected a git ref');
|
|
4147
|
+
}
|
|
4148
|
+
args.since = v;
|
|
4149
|
+
} else if (a.startsWith('--since=')) {
|
|
4150
|
+
args.since = a.slice('--since='.length);
|
|
4107
4151
|
} else if (a === '--format') {
|
|
4108
4152
|
const v = argv[i + 1];
|
|
4109
4153
|
i += 1;
|
|
@@ -4143,6 +4187,21 @@ export function parse_args(argv: string[]): Args {
|
|
|
4143
4187
|
|
|
4144
4188
|
class ArgError extends Error {}
|
|
4145
4189
|
|
|
4190
|
+
/**
|
|
4191
|
+
* True when an empty change set is a defect rather than a legitimate scope.
|
|
4192
|
+
*
|
|
4193
|
+
* Only on a release PR whose scope actually widened to a tag span: a release
|
|
4194
|
+
* that changed no skill and no rule is possible in principle, but a *resolved*
|
|
4195
|
+
* span that matched nothing is the "0 skills checked, INCONCLUSIVE" shape this
|
|
4196
|
+
* gate exists to stop. A release whose previous tag could not be resolved is
|
|
4197
|
+
* excluded — that scope never widened, so failing it would punish a shallow
|
|
4198
|
+
* clone for the wrong reason.
|
|
4199
|
+
*/
|
|
4200
|
+
function _release_scope_requires_findings(root: string, since?: string | null): boolean {
|
|
4201
|
+
const scope = resolveContentLintScope({ cwd: root, since: since ?? null });
|
|
4202
|
+
return scope.isRelease && scope.previousTag !== null;
|
|
4203
|
+
}
|
|
4204
|
+
|
|
4146
4205
|
export function main(argv: string[]): number {
|
|
4147
4206
|
let args: Args;
|
|
4148
4207
|
try {
|
|
@@ -4162,7 +4221,8 @@ export function main(argv: string[]): number {
|
|
|
4162
4221
|
paths.push(...gather_all_candidate_files(root));
|
|
4163
4222
|
}
|
|
4164
4223
|
if (args.changed) {
|
|
4165
|
-
paths.push(...gather_changed_candidate_files(root));
|
|
4224
|
+
paths.push(...gather_changed_candidate_files(root, args.since));
|
|
4225
|
+
process.stderr.write(`skill_linter --changed: ${last_changed_scope_reason}\n`);
|
|
4166
4226
|
}
|
|
4167
4227
|
for (const raw of args.paths) {
|
|
4168
4228
|
const p = path.isAbsolute(raw) ? raw : path.resolve(root, raw);
|
|
@@ -4183,6 +4243,28 @@ export function main(argv: string[]): number {
|
|
|
4183
4243
|
} else if (args.format === 'json') {
|
|
4184
4244
|
process.stdout.write(`${format_json([])}\n`);
|
|
4185
4245
|
}
|
|
4246
|
+
// A release PR that resolved a real tag span and still matched
|
|
4247
|
+
// nothing has not passed — it examined nothing. Mirrors the
|
|
4248
|
+
// scan-scope regime the other gates already adopted
|
|
4249
|
+
// (`_lib/scan_scope.ts`; exit 2, as `check_iron_law_prominence`).
|
|
4250
|
+
// Ordinary PRs keep the historical exit 0: a change set with no
|
|
4251
|
+
// skill or rule in it is a legitimate empty scope, not a dead one.
|
|
4252
|
+
if (args.changed && _release_scope_requires_findings(root, args.since)) {
|
|
4253
|
+
try {
|
|
4254
|
+
assertScanned({
|
|
4255
|
+
gate: 'skill_linter --changed (release PR)',
|
|
4256
|
+
scanned: 0,
|
|
4257
|
+
units: 'skill/rule files',
|
|
4258
|
+
roots: [last_changed_scope_reason],
|
|
4259
|
+
});
|
|
4260
|
+
} catch (exc) {
|
|
4261
|
+
if (exc instanceof DeadScopeError) {
|
|
4262
|
+
process.stderr.write(`❌ ${exc.message}\n`);
|
|
4263
|
+
return 2;
|
|
4264
|
+
}
|
|
4265
|
+
throw exc;
|
|
4266
|
+
}
|
|
4267
|
+
}
|
|
4186
4268
|
process.stderr.write('No matching skill/rule files found.\n');
|
|
4187
4269
|
return 0;
|
|
4188
4270
|
}
|