@event4u/agent-config 9.20.0 → 9.22.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 +86 -0
- package/dist/agent-src/commands/worktree/cleanup.md +17 -0
- package/dist/agent-src/commands/worktree/status.md +6 -0
- package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +22 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli-delegate/{chunk-XGA2NTU4.js → chunk-3EWYC3YK.js} +40 -0
- package/dist/cli-delegate/cmd_handoff.js +1 -1
- package/dist/cli-delegate/cmd_memory_get.js +1 -1
- package/dist/cli-delegate/cmd_route_audit.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +5 -5
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +58 -2
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +47 -29
- package/package.json +1 -1
- package/src/config/gate-coverage.yml +22 -4
- package/src/config/gate-violation-baselines.json +3 -8
- package/src/scripts/_lib/bench_ab_activation.ts +368 -0
- package/src/scripts/_lib/gate_population.ts +70 -0
- package/src/scripts/_lib/roadmap_granularity.ts +157 -0
- package/src/scripts/_lib/scan_scope.ts +44 -0
- package/src/scripts/_lib/stdin.ts +82 -0
- package/src/scripts/audit_adr_coverage.ts +38 -0
- package/src/scripts/audit_auto_rules.ts +17 -3
- package/src/scripts/audit_command_surface.ts +51 -0
- package/src/scripts/audit_initial_context.ts +39 -3
- package/src/scripts/audit_mcp_tools.ts +25 -0
- package/src/scripts/audit_overlap.ts +24 -1
- package/src/scripts/audit_skill_descriptions.ts +19 -0
- package/src/scripts/{verify_before_complete_hook.ts → before_complete_hook.ts} +16 -3
- package/src/scripts/bench_ab_task_runner.ts +18 -0
- package/src/scripts/bench_ab_v2_run.ts +147 -6
- package/src/scripts/bench_ab_v2_stats.ts +74 -2
- package/src/scripts/check_adr_frontmatter.ts +23 -3
- package/src/scripts/check_always_budget.ts +24 -0
- package/src/scripts/check_artefact_checksums.ts +24 -1
- package/src/scripts/check_artefact_count_messaging.ts +20 -0
- package/src/scripts/check_augmentignore.ts +22 -15
- package/src/scripts/check_backstop_debt.ts +22 -0
- package/src/scripts/check_beta_review_markers.ts +22 -1
- package/src/scripts/check_bridge_derivation.ts +22 -1
- package/src/scripts/check_bundle_path_leakage.ts +26 -0
- package/src/scripts/check_ci_strict_superset.ts +21 -3
- package/src/scripts/check_claims.ts +22 -0
- package/src/scripts/check_cli_registry_budget_sync.ts +33 -4
- package/src/scripts/check_cluster_patterns.ts +26 -4
- package/src/scripts/check_command_count_messaging.ts +20 -4
- package/src/scripts/check_comparison.ts +18 -0
- package/src/scripts/check_condensed_paths.ts +23 -2
- package/src/scripts/check_consumer_scope_flip.ts +21 -2
- package/src/scripts/check_council_config_location.ts +20 -0
- package/src/scripts/check_council_layout.ts +22 -2
- package/src/scripts/check_council_references.ts +23 -1
- package/src/scripts/check_dependency_floors.ts +19 -3
- package/src/scripts/check_discovery_determinism.ts +26 -0
- package/src/scripts/check_enforcement_coverage.ts +20 -0
- package/src/scripts/check_evaluator_budgets.ts +23 -0
- package/src/scripts/check_finding_dispositions.ts +29 -0
- package/src/scripts/check_gate_coverage.ts +63 -22
- package/src/scripts/check_gate_paths.ts +30 -5
- package/src/scripts/check_generated_artefact_headers.ts +21 -0
- package/src/scripts/check_generator_output_coverage.ts +23 -0
- package/src/scripts/check_gitignore_freshness.ts +23 -0
- package/src/scripts/check_host_loadability.ts +34 -8
- package/src/scripts/check_installer_import_purity.ts +22 -8
- package/src/scripts/check_kernel_prefix_stability.ts +19 -1
- package/src/scripts/check_kernel_rule_bundle.ts +23 -0
- package/src/scripts/check_knowledge_cards.ts +13 -0
- package/src/scripts/check_knowledge_pages.ts +23 -0
- package/src/scripts/check_knowledge_sharing.ts +27 -0
- package/src/scripts/check_md_language.ts +24 -0
- package/src/scripts/check_media_deps.ts +23 -0
- package/src/scripts/check_memory.ts +26 -1
- package/src/scripts/check_memory_contradiction.ts +16 -1
- package/src/scripts/check_memory_proposal.ts +15 -0
- package/src/scripts/check_memory_similarity.ts +16 -0
- package/src/scripts/check_module_management_neutral.ts +19 -11
- package/src/scripts/check_no_conflict_markers.ts +22 -1
- package/src/scripts/check_no_external_sources.ts +26 -1
- package/src/scripts/check_no_local_settings_committed.ts +37 -10
- package/src/scripts/check_no_new_legacy_path.ts +30 -1
- package/src/scripts/check_one_off_location.ts +43 -0
- package/src/scripts/check_originality_freshness.ts +25 -1
- package/src/scripts/check_overlay_cascade_subdirs.ts +21 -0
- package/src/scripts/check_pack_size.ts +22 -0
- package/src/scripts/check_preamble_payload_budget.ts +35 -5
- package/src/scripts/check_proposal.ts +24 -1
- package/src/scripts/check_public_catalog_links.ts +27 -0
- package/src/scripts/check_public_links.ts +19 -0
- package/src/scripts/check_quality_regression.ts +19 -0
- package/src/scripts/check_reach_channels.ts +44 -0
- package/src/scripts/check_reach_staleness.ts +27 -0
- package/src/scripts/check_release_adjacent_health.ts +28 -0
- package/src/scripts/check_release_highlights.ts +34 -0
- package/src/scripts/check_release_includes_discovery.ts +25 -6
- package/src/scripts/check_release_pr_shape.ts +18 -1
- package/src/scripts/check_release_published.ts +21 -0
- package/src/scripts/check_release_surface_equality.ts +22 -0
- package/src/scripts/check_release_trunk_sync.ts +19 -0
- package/src/scripts/check_reply_consistency.ts +22 -0
- package/src/scripts/check_roadmap_trackable.ts +20 -0
- package/src/scripts/check_role_doc_links.ts +23 -0
- package/src/scripts/check_rule_invariants.ts +14 -0
- package/src/scripts/check_secret_leak.ts +47 -0
- package/src/scripts/check_skill_gaps.ts +32 -0
- package/src/scripts/check_skill_requires.ts +19 -0
- package/src/scripts/check_source_pointer_freshness.ts +20 -0
- package/src/scripts/check_structural_breaking.ts +29 -2
- package/src/scripts/check_surface_tiers.ts +34 -0
- package/src/scripts/check_template_pin_drift.ts +23 -1
- package/src/scripts/check_test_coverage_diff.ts +17 -1
- package/src/scripts/check_token_optimizer_freshness.ts +18 -3
- package/src/scripts/check_token_quality_golden.ts +21 -0
- package/src/scripts/check_token_regression.ts +25 -0
- package/src/scripts/check_tracked_but_ignored.ts +26 -0
- package/src/scripts/check_trigger_eval_presence.ts +23 -1
- package/src/scripts/check_trigger_evals.ts +36 -0
- package/src/scripts/check_trunk_drift.ts +23 -0
- package/src/scripts/check_update_banner.ts +24 -0
- package/src/scripts/gate_scope_classify.ts +513 -0
- package/src/scripts/hook_manifest.yaml +1 -1
- package/src/scripts/hooks/block_kernel_rule_writes.ts +1 -1
- package/src/scripts/hooks/concern_registry.ts +2 -2
- package/src/scripts/lint_agent_security.ts +19 -0
- package/src/scripts/lint_agent_skill_names.ts +30 -0
- package/src/scripts/lint_agents_layout.ts +20 -0
- package/src/scripts/lint_agents_md.ts +20 -0
- package/src/scripts/lint_archived_skills.ts +24 -3
- package/src/scripts/lint_behavioural_eval_freshness.ts +29 -3
- package/src/scripts/lint_bench_ab.ts +25 -0
- package/src/scripts/lint_bench_corpus.ts +20 -4
- package/src/scripts/lint_breaking_changes_index.ts +24 -0
- package/src/scripts/lint_budget_ownership.ts +20 -3
- package/src/scripts/lint_changelog_rollback.ts +24 -0
- package/src/scripts/lint_command_flow_coverage.ts +22 -0
- package/src/scripts/lint_command_tiers.ts +29 -5
- package/src/scripts/lint_commit_subjects.ts +15 -0
- package/src/scripts/lint_confusables.ts +24 -0
- package/src/scripts/lint_consumer_internal_refs.ts +24 -0
- package/src/scripts/lint_design_quality.ts +22 -0
- package/src/scripts/lint_design_slop.ts +23 -0
- package/src/scripts/lint_discovery_manifest.ts +23 -0
- package/src/scripts/lint_discovery_vocabulary.ts +19 -0
- package/src/scripts/lint_documented_commands.ts +23 -0
- package/src/scripts/lint_empty_roadmaps.ts +23 -0
- package/src/scripts/lint_eval_fixture_citations.ts +19 -0
- package/src/scripts/lint_eval_freshness.ts +35 -0
- package/src/scripts/lint_examples.ts +18 -3
- package/src/scripts/lint_explain_trace.ts +23 -0
- package/src/scripts/lint_featured_skills.ts +26 -1
- package/src/scripts/lint_flows.ts +19 -0
- package/src/scripts/lint_frontmatter_boilerplate.ts +20 -0
- package/src/scripts/lint_ghostwriter_source.ts +26 -6
- package/src/scripts/lint_glama_drift.ts +24 -0
- package/src/scripts/lint_global_paths.ts +24 -0
- package/src/scripts/lint_governed_writes.ts +20 -0
- package/src/scripts/lint_hidden_unicode.ts +25 -0
- package/src/scripts/lint_hook_concern_budget.ts +39 -6
- package/src/scripts/lint_hook_manifest.ts +22 -0
- package/src/scripts/lint_instruction_smuggling.ts +23 -0
- package/src/scripts/lint_knowledge_scale.ts +32 -2
- package/src/scripts/lint_legal_pack.ts +31 -0
- package/src/scripts/lint_marketplace.ts +26 -0
- package/src/scripts/lint_marketplace_install_completeness.ts +23 -0
- package/src/scripts/lint_mcp_config_security.ts +24 -0
- package/src/scripts/lint_mcp_registry_manifest.ts +22 -1
- package/src/scripts/lint_memory_tripwire.ts +35 -0
- package/src/scripts/lint_missions.ts +23 -7
- package/src/scripts/lint_model_tier_coverage.ts +18 -0
- package/src/scripts/lint_namespace_collisions.ts +19 -0
- package/src/scripts/lint_no_new_atomic_commands.ts +33 -0
- package/src/scripts/lint_no_python_twin_rationale.ts +18 -0
- package/src/scripts/lint_one_off_age.ts +38 -2
- package/src/scripts/lint_orchestration_dsl.ts +23 -3
- package/src/scripts/lint_orchestrator_auto_detect.ts +19 -12
- package/src/scripts/lint_originality.ts +22 -4
- package/src/scripts/lint_originality_shingles.ts +28 -3
- package/src/scripts/lint_output_slop.ts +19 -0
- package/src/scripts/lint_override_kernel_guard.ts +30 -0
- package/src/scripts/lint_pack_first_win.ts +23 -0
- package/src/scripts/lint_pack_risk_class.ts +19 -3
- package/src/scripts/lint_persistence.ts +19 -0
- package/src/scripts/lint_persona_governance.ts +18 -3
- package/src/scripts/lint_positioning.ts +23 -0
- package/src/scripts/lint_pre_migration_refs.ts +24 -0
- package/src/scripts/lint_profile_overlay_set_only.ts +24 -0
- package/src/scripts/lint_provenance.ts +21 -0
- package/src/scripts/lint_provenance_vocabulary.ts +24 -1
- package/src/scripts/lint_readme_jargon.ts +21 -3
- package/src/scripts/lint_readme_serial_comma.ts +21 -3
- package/src/scripts/lint_readme_size.ts +21 -3
- package/src/scripts/lint_regression.ts +28 -0
- package/src/scripts/lint_roadmap_blockers.ts +43 -0
- package/src/scripts/lint_roadmap_ci_steps.ts +45 -0
- package/src/scripts/lint_roadmap_complexity.ts +47 -0
- package/src/scripts/lint_roadmap_later_disposition.ts +23 -0
- package/src/scripts/lint_rule_interactions.ts +16 -2
- package/src/scripts/lint_rule_tiers.ts +19 -6
- package/src/scripts/lint_showcase_sessions.ts +19 -3
- package/src/scripts/lint_skill_descriptions.ts +19 -0
- package/src/scripts/lint_skill_frontmatter_safety.ts +24 -0
- package/src/scripts/lint_skill_originality.ts +18 -3
- package/src/scripts/lint_skill_scripts_readonly.ts +20 -0
- package/src/scripts/lint_skill_tools.ts +84 -145
- package/src/scripts/lint_spawn_payload.ts +27 -1
- package/src/scripts/lint_store_boundary.ts +19 -0
- package/src/scripts/lint_subagent_determinism.ts +23 -1
- package/src/scripts/lint_supported_tools_matrix.ts +18 -0
- package/src/scripts/lint_surface_matrix.ts +19 -3
- package/src/scripts/lint_ticket_buildable.ts +23 -0
- package/src/scripts/lint_topics_yaml.ts +19 -12
- package/src/scripts/lint_trigger_precision.ts +27 -0
- package/src/scripts/lint_trust_coherence.ts +21 -0
- package/src/scripts/lint_ui_stack_bundles.ts +17 -3
- package/src/scripts/lint_value_dashboard.ts +19 -3
- package/src/scripts/lint_versioned_cache.ts +19 -1
- package/src/scripts/lint_workflow_security.ts +22 -14
- package/src/scripts/pr_url_reminder_hook.ts +1 -1
- package/src/scripts/skill_collision_clusters.ts +37 -3
- package/src/scripts/skill_discovery.ts +20 -0
- package/src/scripts/skill_eval_coverage.ts +22 -0
- package/src/scripts/skill_overlap.ts +32 -6
- package/src/scripts/skill_preview.ts +31 -0
- package/src/scripts/skill_trigger_eval.ts +18 -0
- package/src/scripts/skill_usage_collect.ts +21 -0
- package/src/scripts/skill_usage_report.ts +21 -0
- package/src/scripts/sweep_dead_scan_roots.ts +11 -3
- package/src/scripts/verify_physical_move.ts +24 -0
- package/src/scripts/worktree_cleanup_check.ts +319 -4
- package/src/scripts/check_bite_sized_granularity.ts +0 -116
- package/src/scripts/lint_workspace_boundary.ts +0 -267
|
@@ -43,6 +43,8 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
43
43
|
|
|
44
44
|
import * as yaml from 'js-yaml';
|
|
45
45
|
|
|
46
|
+
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
47
|
+
|
|
46
48
|
const _HERE = fileURLToPath(import.meta.url);
|
|
47
49
|
const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
48
50
|
const CORPUS = path.join(REPO_ROOT, 'internal/bench/corpora/token-quality-golden.yaml');
|
|
@@ -350,6 +352,25 @@ function main(argv: string[]): number {
|
|
|
350
352
|
// Structure (incl. the fires-check) always validates against the FULL
|
|
351
353
|
// universe — a maintainer-rule tag is not "unknown" under consumer scope.
|
|
352
354
|
const report = validate(corpus, ruleIds, router);
|
|
355
|
+
// `tasks: []` parses, validates clean, and covers nothing — and without
|
|
356
|
+
// `--require-complete` an uncovered universe is only a ⚠️, so an emptied
|
|
357
|
+
// corpus exits 0 while proving nothing about any rule.
|
|
358
|
+
try {
|
|
359
|
+
assertScanned({
|
|
360
|
+
gate: 'check_token_quality_golden',
|
|
361
|
+
scanned: report.task_count,
|
|
362
|
+
units: 'golden task(s)',
|
|
363
|
+
roots: [path.relative(REPO_ROOT, CORPUS)],
|
|
364
|
+
});
|
|
365
|
+
} catch (e) {
|
|
366
|
+
if (e instanceof DeadScopeError) {
|
|
367
|
+
// 2 = invalid corpus; 1 is reserved for an unreadable file, and this one
|
|
368
|
+
// read and parsed fine.
|
|
369
|
+
process.stderr.write(`❌ ${e.message}\n`);
|
|
370
|
+
return 2;
|
|
371
|
+
}
|
|
372
|
+
throw e;
|
|
373
|
+
}
|
|
353
374
|
|
|
354
375
|
// Coverage accounting runs against the SCOPED universe: which flip is
|
|
355
376
|
// being gated decides what "complete" means.
|
|
@@ -41,6 +41,8 @@ import * as path from 'node:path';
|
|
|
41
41
|
import process from 'node:process';
|
|
42
42
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
43
43
|
|
|
44
|
+
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
45
|
+
|
|
44
46
|
const _HERE = fileURLToPath(import.meta.url);
|
|
45
47
|
// REPO_ROOT = <repo>/src/scripts/<file> → up two.
|
|
46
48
|
const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
@@ -216,6 +218,29 @@ function main(argv: string[]): number {
|
|
|
216
218
|
}
|
|
217
219
|
const current = extract_metrics(report);
|
|
218
220
|
|
|
221
|
+
// `_num` returns 0 both for "absent from the report" and for "genuinely
|
|
222
|
+
// zero", and no gated surface is ever legitimately zero tokens — so a
|
|
223
|
+
// renamed report key reads as 0, every pct goes negative against the
|
|
224
|
+
// baseline, and the gate reports ✅ while measuring nothing. Counting the
|
|
225
|
+
// metrics that resolved is counting units READ, not units passing. Asserted
|
|
226
|
+
// BEFORE --update-baseline so a report of zeros can never be recorded as the
|
|
227
|
+
// baseline every later run compares against. Exit 1 (the file/argument
|
|
228
|
+
// error class — the gate could not run); 2 means a real regression.
|
|
229
|
+
try {
|
|
230
|
+
assertScanned({
|
|
231
|
+
gate: 'check_token_regression',
|
|
232
|
+
scanned: Object.values(current.metrics).filter((v) => v > 0).length,
|
|
233
|
+
units: 'gated metric(s)',
|
|
234
|
+
roots: [path.relative(REPO_ROOT, PROJECTION_REPORT)],
|
|
235
|
+
});
|
|
236
|
+
} catch (err) {
|
|
237
|
+
if (err instanceof DeadScopeError) {
|
|
238
|
+
process.stderr.write(`❌ ${err.message}\n`);
|
|
239
|
+
return 1;
|
|
240
|
+
}
|
|
241
|
+
throw err;
|
|
242
|
+
}
|
|
243
|
+
|
|
219
244
|
if (updateBaseline) {
|
|
220
245
|
const payload = JSON.stringify(current, null, 2) + '\n';
|
|
221
246
|
fs.writeFileSync(BASELINE_FILE, payload);
|
|
@@ -19,14 +19,23 @@ import * as fs from 'node:fs';
|
|
|
19
19
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
20
20
|
import * as path from 'node:path';
|
|
21
21
|
|
|
22
|
+
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
23
|
+
|
|
22
24
|
const _HERE = fileURLToPath(import.meta.url);
|
|
23
25
|
|
|
24
26
|
function main(argv?: readonly string[]): number {
|
|
25
27
|
const args = argv ?? process.argv.slice(2);
|
|
26
28
|
const quiet = args.includes('--quiet');
|
|
27
29
|
|
|
30
|
+
let tracked: string;
|
|
28
31
|
let output: string;
|
|
29
32
|
try {
|
|
33
|
+
// The corpus is the tracked index, not the `-ci` result — that result IS
|
|
34
|
+
// the finding list, so counting it would count violations. Read the index
|
|
35
|
+
// itself: `git ls-files` is path-scoped to the cwd, so running from a
|
|
36
|
+
// subtree with nothing tracked yields an empty index AND an empty `-ci`
|
|
37
|
+
// result, and the gate prints its green line having examined nothing.
|
|
38
|
+
tracked = execSync('git ls-files', { encoding: 'utf-8', cwd: process.cwd() }).trim();
|
|
30
39
|
output = execSync('git ls-files -ci --exclude-standard', {
|
|
31
40
|
encoding: 'utf-8',
|
|
32
41
|
cwd: process.cwd(),
|
|
@@ -36,6 +45,23 @@ function main(argv?: readonly string[]): number {
|
|
|
36
45
|
return 2;
|
|
37
46
|
}
|
|
38
47
|
|
|
48
|
+
try {
|
|
49
|
+
assertScanned({
|
|
50
|
+
gate: 'check_tracked_but_ignored',
|
|
51
|
+
scanned: tracked ? tracked.split('\n').filter(Boolean).length : 0,
|
|
52
|
+
units: 'tracked file(s)',
|
|
53
|
+
roots: ['git ls-files (cwd-scoped index)'],
|
|
54
|
+
});
|
|
55
|
+
} catch (exc) {
|
|
56
|
+
if (exc instanceof DeadScopeError) {
|
|
57
|
+
// 2 = "this gate could not run" (its git-unavailable code), never 1,
|
|
58
|
+
// which asserts the stronger claim that ignored-but-tracked files exist.
|
|
59
|
+
process.stderr.write(`❌ ${exc.message}\n`);
|
|
60
|
+
return 2;
|
|
61
|
+
}
|
|
62
|
+
throw exc;
|
|
63
|
+
}
|
|
64
|
+
|
|
39
65
|
if (!output) {
|
|
40
66
|
if (!quiet) {
|
|
41
67
|
process.stdout.write(`✅ No tracked-but-ignored files found.\n`);
|
|
@@ -26,6 +26,8 @@ import * as fs from 'node:fs';
|
|
|
26
26
|
import * as path from 'node:path';
|
|
27
27
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
28
28
|
|
|
29
|
+
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
30
|
+
|
|
29
31
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
30
32
|
const SKILLS_DIR = path.join(REPO_ROOT, 'src', 'skills');
|
|
31
33
|
const ALLOWLIST_PATH = path.join(REPO_ROOT, 'src', 'scripts', 'trigger_eval_grandfather.json');
|
|
@@ -128,7 +130,27 @@ function main(): number {
|
|
|
128
130
|
return 2;
|
|
129
131
|
}
|
|
130
132
|
|
|
131
|
-
|
|
133
|
+
// The ratchet only bites per skill directory found: an empty (or moved)
|
|
134
|
+
// skills root makes every rule in `check` iterate nothing, and the ✅ line
|
|
135
|
+
// reads "0/0 skills carry evals/triggers.json" — a passing presence gate
|
|
136
|
+
// over no skills at all.
|
|
137
|
+
const skills = list_skill_dirs(SKILLS_DIR);
|
|
138
|
+
try {
|
|
139
|
+
assertScanned({
|
|
140
|
+
gate: 'check_trigger_eval_presence',
|
|
141
|
+
scanned: skills.length,
|
|
142
|
+
units: 'skill director(ies)',
|
|
143
|
+
roots: ['src/skills'],
|
|
144
|
+
});
|
|
145
|
+
} catch (exc) {
|
|
146
|
+
if (exc instanceof DeadScopeError) {
|
|
147
|
+
process.stderr.write(`❌ ${exc.message}\n`);
|
|
148
|
+
return 1;
|
|
149
|
+
}
|
|
150
|
+
throw exc;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const { errors, covered, total } = check(skills, allowlist.skills);
|
|
132
154
|
|
|
133
155
|
if (errors.length) {
|
|
134
156
|
process.stderr.write('❌ check-trigger-eval-presence: presence-ratchet violation(s):\n');
|
|
@@ -27,6 +27,8 @@ import * as fs from 'node:fs';
|
|
|
27
27
|
import * as path from 'node:path';
|
|
28
28
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
29
29
|
|
|
30
|
+
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
31
|
+
|
|
30
32
|
const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..', '..');
|
|
31
33
|
const GLOB = 'src/skills/*/evals/triggers.json';
|
|
32
34
|
const MAX_AGE_DAYS = 90;
|
|
@@ -276,6 +278,20 @@ function _isFile(p: string): boolean {
|
|
|
276
278
|
}
|
|
277
279
|
}
|
|
278
280
|
|
|
281
|
+
/** Immediate `src/skills/*` directories — the population `_glob_triggers` filters. */
|
|
282
|
+
function _skill_dirs(root: string): string[] {
|
|
283
|
+
const skillsDir = path.join(root, 'src', 'skills');
|
|
284
|
+
let entries: fs.Dirent[];
|
|
285
|
+
try {
|
|
286
|
+
entries = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
287
|
+
} catch {
|
|
288
|
+
return [];
|
|
289
|
+
}
|
|
290
|
+
return entries
|
|
291
|
+
.filter((ent) => ent.isDirectory() || ent.isSymbolicLink())
|
|
292
|
+
.map((ent) => path.join(skillsDir, ent.name));
|
|
293
|
+
}
|
|
294
|
+
|
|
279
295
|
/** Component-wise path comparison matching PosixPath ordering. */
|
|
280
296
|
function _pathSort(a: string, b: string): number {
|
|
281
297
|
const pa = a.split(path.sep);
|
|
@@ -342,6 +358,26 @@ function main(): number {
|
|
|
342
358
|
return 2;
|
|
343
359
|
}
|
|
344
360
|
|
|
361
|
+
// The scanned unit is the skill directory, not the triggers.json subset:
|
|
362
|
+
// whether a given skill ships evals is `check_trigger_eval_presence`'s
|
|
363
|
+
// ratchet, so zero trigger sets under a populated tree is that gate's
|
|
364
|
+
// finding, not this one's. Zero skill DIRECTORIES is this gate's blindness
|
|
365
|
+
// — the ✅ line then reads "0 trigger set(s) fresh + valid".
|
|
366
|
+
try {
|
|
367
|
+
assertScanned({
|
|
368
|
+
gate: 'check_trigger_evals',
|
|
369
|
+
scanned: _skill_dirs(REPO_ROOT).length,
|
|
370
|
+
units: 'skill director(ies)',
|
|
371
|
+
roots: ['src/skills'],
|
|
372
|
+
});
|
|
373
|
+
} catch (exc) {
|
|
374
|
+
if (exc instanceof DeadScopeError) {
|
|
375
|
+
process.stderr.write(`❌ ${exc.message}\n`);
|
|
376
|
+
return 1;
|
|
377
|
+
}
|
|
378
|
+
throw exc;
|
|
379
|
+
}
|
|
380
|
+
|
|
345
381
|
const files = _glob_triggers(REPO_ROOT);
|
|
346
382
|
const errors: string[] = [];
|
|
347
383
|
for (const p of files) {
|
|
@@ -16,6 +16,8 @@ import * as fs from 'node:fs';
|
|
|
16
16
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
17
17
|
import * as path from 'node:path';
|
|
18
18
|
|
|
19
|
+
import { assertScanned, DeadScopeError } from './_lib/scan_scope.js';
|
|
20
|
+
|
|
19
21
|
export type DriftInput = {
|
|
20
22
|
/** True when origin/main is an ancestor of HEAD (branch contains trunk tip). */
|
|
21
23
|
trunkIsAncestor: boolean;
|
|
@@ -42,8 +44,13 @@ function _git(args: string[]): string {
|
|
|
42
44
|
|
|
43
45
|
export function main(): number {
|
|
44
46
|
let input: DriftInput;
|
|
47
|
+
let trunkCommits = 0;
|
|
45
48
|
try {
|
|
46
49
|
_git(['fetch', 'origin', 'main', '--quiet']);
|
|
50
|
+
// The comparison is only meaningful against a trunk that has history.
|
|
51
|
+
// An origin/main pointing at an empty/orphan ref answers "0 behind" and
|
|
52
|
+
// scores the branch up to date without ever having read a trunk commit.
|
|
53
|
+
trunkCommits = Number(_git(['rev-list', '--count', 'origin/main']) || '0');
|
|
47
54
|
let isAncestor = true;
|
|
48
55
|
try {
|
|
49
56
|
execFileSync('git', ['merge-base', '--is-ancestor', 'origin/main', 'HEAD'], { stdio: 'ignore' });
|
|
@@ -56,6 +63,22 @@ export function main(): number {
|
|
|
56
63
|
process.stdout.write(`⚠️ trunk-drift check skipped (no origin/main or git error): ${String(e)}\n`);
|
|
57
64
|
return 0; // advisory — never block on a missing remote
|
|
58
65
|
}
|
|
66
|
+
try {
|
|
67
|
+
assertScanned({
|
|
68
|
+
gate: 'check_trunk_drift',
|
|
69
|
+
scanned: trunkCommits,
|
|
70
|
+
units: 'trunk commit(s)',
|
|
71
|
+
roots: ['origin/main'],
|
|
72
|
+
});
|
|
73
|
+
} catch (exc) {
|
|
74
|
+
if (exc instanceof DeadScopeError) {
|
|
75
|
+
// 1 is the only failure code; 0 means pass/advisory-skip, so a dead
|
|
76
|
+
// scope must not borrow it — a gate that read no trunk has not passed.
|
|
77
|
+
process.stderr.write(`❌ ${exc.message}\n`);
|
|
78
|
+
return 1;
|
|
79
|
+
}
|
|
80
|
+
throw exc;
|
|
81
|
+
}
|
|
59
82
|
const v = driftVerdict(input);
|
|
60
83
|
process.stdout.write(`${v.message}\n`);
|
|
61
84
|
return v.ok ? 0 : 1;
|
|
@@ -22,6 +22,7 @@ import * as path from 'node:path';
|
|
|
22
22
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
23
23
|
|
|
24
24
|
import * as agent_settings from './_lib/agent_settings.js';
|
|
25
|
+
import { assertWatchlistResolves, DeadScopeError } from './_lib/scan_scope.js';
|
|
25
26
|
import * as update_check from './_lib/update_check.js';
|
|
26
27
|
|
|
27
28
|
const _HERE = fileURLToPath(import.meta.url);
|
|
@@ -107,6 +108,29 @@ async function main(argv: readonly string[] = process.argv.slice(2)): Promise<nu
|
|
|
107
108
|
return 0;
|
|
108
109
|
}
|
|
109
110
|
|
|
111
|
+
if (!args.installed_version) {
|
|
112
|
+
// Without the flag, `$PACKAGE_ROOT/package.json` IS the whole input.
|
|
113
|
+
// `_read_installed_version` swallows a missing or unparseable file into
|
|
114
|
+
// '' and the banner then simply never fires — indistinguishable from
|
|
115
|
+
// "you are up to date". The exit code stays 0 on purpose: "never
|
|
116
|
+
// raises, never exits non-zero" is this wrapper's pinned CLI contract,
|
|
117
|
+
// so the only loudness available is stderr, which is where the banner
|
|
118
|
+
// itself goes anyway.
|
|
119
|
+
try {
|
|
120
|
+
assertWatchlistResolves({
|
|
121
|
+
gate: 'check_update_banner',
|
|
122
|
+
candidates: ['package.json'],
|
|
123
|
+
repoRoot: ROOT,
|
|
124
|
+
});
|
|
125
|
+
} catch (err) {
|
|
126
|
+
if (err instanceof DeadScopeError) {
|
|
127
|
+
process.stderr.write(`❌ ${err.message}\n`);
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
throw err;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
110
134
|
const installed = args.installed_version || _read_installed_version(ROOT);
|
|
111
135
|
if (!installed) {
|
|
112
136
|
return 0;
|