@event4u/agent-config 8.9.0 → 8.11.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 +189 -0
- package/README.md +5 -5
- package/dist/agent-src/commands/challenge-me/vision.md +121 -32
- package/dist/agent-src/commands/challenge-me/with-docs.md +21 -8
- package/dist/agent-src/commands/commit/in-chunks.md +1 -1
- package/dist/agent-src/commands/commit.md +2 -1
- package/dist/agent-src/commands/cost/report.md +14 -3
- package/dist/agent-src/commands/feature/dev.md +4 -4
- package/dist/agent-src/commands/humanize.md +101 -0
- package/dist/agent-src/commands/jira-ticket.md +2 -2
- package/dist/agent-src/commands/memory/load.md +15 -0
- package/dist/agent-src/commands/optimize/project.md +12 -0
- package/dist/agent-src/commands/roadmap/create.md +12 -11
- package/dist/agent-src/commands/tests/create.md +29 -7
- package/dist/agent-src/commands/work.md +33 -0
- package/dist/agent-src/commands/worktree/cleanup.md +83 -0
- package/dist/agent-src/commands/worktree/create.md +64 -0
- package/dist/agent-src/commands/worktree/status.md +75 -0
- package/dist/agent-src/commands/worktree/verify.md +70 -0
- package/dist/agent-src/commands/worktree.md +85 -0
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +66 -0
- package/dist/agent-src/contexts/execution/orchestration-benchmark-gate.md +1 -0
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +91 -34
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +14 -0
- package/dist/agent-src/contexts/execution/roadmap-writing-source-derived.md +65 -0
- package/dist/agent-src/contexts/execution/subagent-modes-detail.md +84 -0
- package/dist/agent-src/rules/autonomous-execution.md +7 -37
- package/dist/agent-src/rules/broken-access-control.md +7 -45
- package/dist/agent-src/rules/code-comment-discipline.md +148 -0
- package/dist/agent-src/rules/context-hygiene.md +14 -0
- package/dist/agent-src/rules/delegation-policy.md +10 -8
- package/dist/agent-src/rules/design-fidelity.md +44 -0
- package/dist/agent-src/rules/git-history-discipline.md +4 -79
- package/dist/agent-src/rules/legal-safety-floor.md +11 -55
- package/dist/agent-src/rules/roadmap-progress-sync.md +5 -56
- package/dist/agent-src/rules/spreadsheet-source-quality.md +61 -0
- package/dist/agent-src/rules/think-before-action.md +10 -0
- package/dist/agent-src/rules/verify-before-complete.md +12 -0
- package/dist/agent-src/skills/accessibility-auditor/evals/evals.json +15 -0
- package/dist/agent-src/skills/agent-docs-writing/SKILL.md +13 -12
- package/dist/agent-src/skills/ai-council/SKILL.md +19 -9
- package/dist/agent-src/skills/analysis-skill-router/evals/evals.json +13 -0
- package/dist/agent-src/skills/api-design/SKILL.md +7 -5
- package/dist/agent-src/skills/api-testing/SKILL.md +16 -2
- package/dist/agent-src/skills/authz-review/SKILL.md +59 -2
- package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/bug-analyzer/SKILL.md +19 -16
- package/dist/agent-src/skills/character-consistency/evals/evals.json +16 -0
- package/dist/agent-src/skills/code-refactoring/SKILL.md +9 -9
- package/dist/agent-src/skills/command-routing/evals/evals.json +14 -0
- package/dist/agent-src/skills/content-funnel-design/SKILL.md +2 -0
- package/dist/agent-src/skills/dashboard-design/evals/evals.json +16 -0
- package/dist/agent-src/skills/data-flow-mapper/SKILL.md +1 -1
- package/dist/agent-src/skills/dcf-modeling/evals/evals.json +20 -0
- package/dist/agent-src/skills/decision-record/evals/evals.json +20 -0
- package/dist/agent-src/skills/defense-in-depth/SKILL.md +2 -2
- package/dist/agent-src/skills/dependency-upgrade/SKILL.md +7 -7
- package/dist/agent-src/skills/design-intelligence/SKILL.md +8 -8
- package/dist/agent-src/skills/design-intelligence/evals/evals.json +14 -0
- package/dist/agent-src/skills/design-review/SKILL.md +29 -2
- package/dist/agent-src/skills/design-system-capture/SKILL.md +21 -0
- package/dist/agent-src/skills/design-system-capture/evals/evals.json +15 -0
- package/dist/agent-src/skills/developer-like-execution/evals/evals.json +16 -0
- package/dist/agent-src/skills/doc-coauthoring/SKILL.md +29 -0
- package/dist/agent-src/skills/doc-coauthoring/evals/evals.json +16 -0
- package/dist/agent-src/skills/editorial-calendar/SKILL.md +2 -0
- package/dist/agent-src/skills/editorial-calendar/evals/domain-truth.json +16 -0
- package/dist/agent-src/skills/editorial-calendar/evals/evals.json +16 -0
- package/dist/agent-src/skills/estimate-ticket/evals/evals.json +16 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +30 -0
- package/dist/agent-src/skills/existing-ui-audit/evals/triggers.json +47 -0
- package/dist/agent-src/skills/fe-design/SKILL.md +43 -14
- package/dist/agent-src/skills/fe-design/evals/triggers.json +47 -0
- package/dist/agent-src/skills/forecasting/evals/evals.json +20 -0
- package/dist/agent-src/skills/fundraising-narrative/evals/domain-truth.json +16 -0
- package/dist/agent-src/skills/fundraising-narrative/evals/evals.json +16 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +86 -0
- package/dist/agent-src/skills/html-deck/SKILL.md +27 -0
- package/dist/agent-src/skills/humanizer/SKILL.md +147 -0
- package/dist/agent-src/skills/humanizer/data/patterns.md +190 -0
- package/dist/agent-src/skills/humanizer/evals/triggers.json +17 -0
- package/dist/agent-src/skills/iconography/SKILL.md +24 -0
- package/dist/agent-src/skills/incident-commander/evals/domain-truth.json +16 -0
- package/dist/agent-src/skills/incident-commander/evals/evals.json +20 -0
- package/dist/agent-src/skills/laravel/SKILL.md +14 -1
- package/dist/agent-src/skills/launch-readiness/SKILL.md +20 -19
- package/dist/agent-src/skills/launch-readiness/evals/evals.json +21 -0
- package/dist/agent-src/skills/legal-practice-profile/SKILL.md +126 -0
- package/dist/agent-src/skills/logging-monitoring/SKILL.md +1 -1
- package/dist/agent-src/skills/logging-monitoring/evals/evals.json +16 -0
- package/dist/agent-src/skills/mcp/SKILL.md +1 -1
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +14 -1
- package/dist/agent-src/skills/messaging-architecture/evals/domain-truth.json +16 -0
- package/dist/agent-src/skills/messaging-architecture/evals/evals.json +16 -0
- package/dist/agent-src/skills/migration-architect/SKILL.md +2 -1
- package/dist/agent-src/skills/perf-feedback-craft/evals/evals.json +16 -0
- package/dist/agent-src/skills/performance/SKILL.md +1 -1
- package/dist/agent-src/skills/pest-testing/SKILL.md +1 -1
- package/dist/agent-src/skills/php-debugging/SKILL.md +17 -0
- package/dist/agent-src/skills/playwright-testing/SKILL.md +16 -0
- package/dist/agent-src/skills/prompt-engineering-patterns/evals/evals.json +16 -0
- package/dist/agent-src/skills/readme-writing/SKILL.md +2 -0
- package/dist/agent-src/skills/readme-writing-package/SKILL.md +2 -0
- package/dist/agent-src/skills/refine-prompt/evals/evals.json +16 -0
- package/dist/agent-src/skills/refine-ticket/evals/evals.json +16 -0
- package/dist/agent-src/skills/release-comms/SKILL.md +2 -0
- package/dist/agent-src/skills/release-comms/evals/evals.json +16 -0
- package/dist/agent-src/skills/rice-prioritization/evals/evals.json +20 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +22 -51
- package/dist/agent-src/skills/runway-cognition/evals/evals.json +20 -0
- package/dist/agent-src/skills/scenario-modeling/evals/evals.json +20 -0
- package/dist/agent-src/skills/security-audit/SKILL.md +6 -9
- package/dist/agent-src/skills/sentry-integration/SKILL.md +2 -2
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +8 -0
- package/dist/agent-src/skills/source-discovery/SKILL.md +26 -24
- package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +98 -0
- package/dist/agent-src/skills/spreadsheet-authoring/evals/triggers.json +47 -0
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +55 -46
- package/dist/agent-src/skills/subagent-orchestration/evals/evals.json +42 -0
- package/dist/agent-src/skills/systematic-debugging/SKILL.md +10 -0
- package/dist/agent-src/skills/systematic-debugging/evals/evals.json +20 -0
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +118 -0
- package/dist/agent-src/skills/test-case-discovery/evals/triggers.json +52 -0
- package/dist/agent-src/skills/test-driven-development/SKILL.md +32 -6
- package/dist/agent-src/skills/test-driven-development/evals/evals.json +16 -0
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +7 -6
- package/dist/agent-src/skills/threat-modeling/evals/evals.json +21 -0
- package/dist/agent-src/skills/typography-system/evals/evals.json +14 -0
- package/dist/agent-src/skills/unit-economics-modeling/evals/evals.json +24 -0
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +10 -0
- package/dist/agent-src/skills/verify-completion-evidence/evals/evals.json +16 -0
- package/dist/agent-src/skills/vision-articulation/evals/evals.json +16 -0
- package/dist/agent-src/skills/voice-and-tone-design/evals/evals.json +16 -0
- package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +187 -0
- package/dist/agent-src/skills/worktree-lifecycle/evals/evals.json +38 -0
- package/dist/agent-src/skills/worktree-lifecycle/evals/triggers.json +52 -0
- package/dist/agent-src/templates/agent-settings.md +3 -2
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +15 -1
- package/dist/agent-src/templates/roadmaps.md +14 -0
- package/dist/cli/commands/recordTriggerEval.js +4 -14
- package/dist/cli/commands/recordTriggerEval.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +374 -88
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +9 -9
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +30 -18
- package/dist/discovery/trust-report.md +5 -5
- package/dist/discovery/workspaces.json +31 -15
- package/dist/install/install.mjs +12 -7
- package/dist/mcp/registry-manifest.json +4 -4
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/claude_settings_hooks.js +8 -0
- package/dist/scripts/_lib/claude_settings_hooks.js.map +1 -1
- package/dist/scripts/_lib/trigger_eval_floors.js +24 -0
- package/dist/scripts/_lib/trigger_eval_floors.js.map +1 -0
- package/dist/scripts/condense.js +12 -2
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +5 -2
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/CLAIMS.md +24 -3
- package/docs/architecture.md +3 -3
- package/docs/benchmark.md +51 -0
- package/docs/catalog.md +23 -9
- package/docs/command-flows.md +7 -1
- package/docs/contracts/CHANGELOG-conventions.md +6 -0
- package/docs/contracts/ai-council-config.md +92 -0
- package/docs/contracts/command-clusters.md +1 -0
- package/docs/contracts/design-artifact-lifecycle.md +93 -0
- package/docs/contracts/design-artifact-verification.md +30 -1
- package/docs/contracts/evidence-based-pruning.md +1 -0
- package/docs/contracts/hook-architecture-v1.md +25 -0
- package/docs/contracts/kernel-membership.md +35 -0
- package/docs/contracts/measurement-baseline.md +1 -0
- package/docs/contracts/release-pr-gating.md +26 -0
- package/docs/contracts/release-sizing.md +107 -0
- package/docs/contracts/surface-agent-contracts.md +153 -0
- package/docs/contracts/write-engine.md +38 -1
- package/docs/customization.md +12 -0
- package/docs/decisions/ADR-002-kernel-bucket-overrides.md +11 -0
- package/docs/decisions/ADR-003-flat-cluster-subs-and-colon-syntax.md +11 -0
- package/docs/decisions/ADR-006-skill-tools-python-pilot.md +1 -1
- package/docs/decisions/ADR-028-root-layout.md +1 -1
- package/docs/decisions/ADR-038-canonical-settings-path.md +10 -0
- package/docs/decisions/ADR-092-defer-command-tier-alias-removal.md +29 -5
- package/docs/decisions/ADR-093-ai-council-config-user-global.md +1 -1
- package/docs/decisions/ADR-100-global-knowledge-card-sharing.md +7 -0
- package/docs/decisions/ADR-103-global-knowledge-default-off-until-measured.md +2 -2
- package/docs/decisions/ADR-105-automatic-subagent-orchestration.md +1 -1
- package/docs/decisions/ADR-114-commit-policy-iron-law-override.md +11 -0
- package/docs/decisions/ADR-115-command-cluster-consolidation-phase-4.md +1 -1
- package/docs/decisions/ADR-116-memory-tripwire-activation-path.md +11 -1
- package/docs/decisions/ADR-117-subagents-auto-default-on.md +2 -1
- package/docs/decisions/ADR-118-loop-engineering-boundaries.md +162 -0
- package/docs/decisions/ADR-119-global-knowledge-default-on.md +104 -0
- package/docs/decisions/ADR-200-python-to-typescript-migration.md +11 -1
- package/docs/decisions/ADR-rule-kernel-and-router.md +11 -0
- package/docs/decisions/INDEX.md +11 -9
- package/docs/design/cross-model-parity-eval.md +82 -0
- package/docs/design/length-neutral-judge-rerun.md +92 -0
- package/docs/distribution/consumer-matrix.md +96 -0
- package/docs/featured-skills.md +2 -2
- package/docs/getting-started-by-role.md +1 -1
- package/docs/getting-started.md +2 -2
- package/docs/governance-advantage.md +1 -1
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +80 -5
- package/docs/guidelines/code-clarity.md +106 -1
- package/docs/guidelines/design-antipatterns.md +20 -0
- package/docs/guidelines/php/php-coding-patterns.md +12 -2
- package/docs/proof.md +21 -15
- package/docs/release-runbook.md +3 -0
- package/docs/self-review-gate.md +51 -0
- package/docs/wedge/production-validator/production-validator.md +27 -0
- package/package.json +1 -1
- package/src/config/agent-settings.template.yml +29 -9
- package/src/scripts/_cli/cmd_doctor.ts +34 -1
- package/src/scripts/_lib/auto_dispatch.corpus.test.ts +87 -0
- package/src/scripts/_lib/claude_settings_hooks.ts +8 -0
- package/src/scripts/_lib/knowledge_global.ts +6 -2
- package/src/scripts/_lib/knowledge_global_redaction.ts +42 -4
- package/src/scripts/_lib/lexical_index.ts +15 -2
- package/src/scripts/_lib/orchestration_record.ts +27 -0
- package/src/scripts/_lib/orchestration_savings.ts +52 -0
- package/src/scripts/_lib/trigger_eval_floors.ts +31 -0
- package/src/scripts/ai_council/chairman.ts +90 -0
- package/src/scripts/ai_council/clients.ts +18 -3
- package/src/scripts/ai_council/config.ts +157 -0
- package/src/scripts/ai_council/debate_gates.ts +89 -0
- package/src/scripts/ai_council/orchestrator.ts +65 -2
- package/src/scripts/ai_council/prompts.ts +121 -11
- package/src/scripts/ai_council/replay.ts +17 -0
- package/src/scripts/ai_council/stance_tally.ts +184 -0
- package/src/scripts/ai_tells_rules.ts +433 -0
- package/src/scripts/bench_humanizer_eval.ts +240 -0
- package/src/scripts/build_discovery_manifest.ts +6 -0
- package/src/scripts/build_proof.ts +21 -9
- package/src/scripts/check_claims.ts +40 -0
- package/src/scripts/check_release_adjacent_health.ts +121 -0
- package/src/scripts/check_rule_invariants.ts +282 -0
- package/src/scripts/condense.ts +16 -2
- package/src/scripts/consumer_matrix.ts +392 -0
- package/src/scripts/council_cli.ts +147 -0
- package/src/scripts/detect_ai_tells.ts +312 -0
- package/src/scripts/generate_index.ts +3 -2
- package/src/scripts/install.ts +12 -0
- package/src/scripts/knowledge_global_cli.ts +1 -1
- package/src/scripts/lint_changelog_rollback.ts +293 -0
- package/src/scripts/lint_framework_leakage.ts +88 -7
- package/src/scripts/lint_framework_leakage_allowlist.json +59 -572
- package/src/scripts/lint_knowledge_scale.ts +30 -0
- package/src/scripts/lint_originality_shingles.ts +210 -0
- package/src/scripts/orchestration_record.ts +17 -0
- package/src/scripts/orchestration_savings_report.ts +36 -3
- package/src/scripts/schemas/agent-settings.schema.json +11 -0
- package/src/scripts/second_brain_retrieval.ts +44 -2
- package/src/scripts/self_review_gate.test.ts +65 -0
- package/src/scripts/self_review_gate.ts +298 -0
- package/src/scripts/skill_eval_coverage.ts +71 -3
- package/src/scripts/skill_linter.ts +1 -0
- package/src/scripts/trigger_eval_grandfather.json +223 -224
- package/src/scripts/trigger_eval_rotation.ts +344 -0
- package/src/scripts/update_counts.ts +5 -17
- package/src/scripts/worktree_cleanup_check.ts +263 -0
- package/src/server/schemas/settings.ts +8 -3
- package/src/scripts/analysis_freshness.ts +0 -362
- package/src/scripts/export_replay_corpus.ts +0 -208
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Kernel semantic-invariants checker.
|
|
4
|
+
*
|
|
5
|
+
* Counterfactual (2026-07-10): PRs #840/#844 showed MERGED on GitHub but their
|
|
6
|
+
* content vanished from main (merge commits unreachable after a history repair);
|
|
7
|
+
* re-landed as #847 (13f244c9b — non-destructive "Irreversible external action"
|
|
8
|
+
* row + "Never act while asking" clause) and #849 (2c46e7f3b — direct-answers
|
|
9
|
+
* "no duration estimates" + "never cite the rule"). This checker's invariant set
|
|
10
|
+
* covers those exact strings — it would have flagged the loss at CI time.
|
|
11
|
+
*
|
|
12
|
+
* Loads `tests/golden/invariants.json` and verifies that every invariant
|
|
13
|
+
* string (whitespace-normalised: runs of whitespace collapse to a single
|
|
14
|
+
* space) is present in BOTH the kernel rule's `src/rules/` source and its
|
|
15
|
+
* `dist/agent-src/rules/` projection. A missing string means a rule's
|
|
16
|
+
* behaviour guarantee was silently lost in a merge / condensation pass.
|
|
17
|
+
*
|
|
18
|
+
* Kernel set: docs/contracts/kernel-membership.md § 4 (9 locked rules).
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* npx tsx src/scripts/check_rule_invariants.ts [--root ROOT]
|
|
22
|
+
* npx tsx src/scripts/check_rule_invariants.ts --mutation-selftest
|
|
23
|
+
*
|
|
24
|
+
* `--mutation-selftest` picks the first invariant and verifies the check
|
|
25
|
+
* WOULD fail if that string were absent (in-memory mutation) — guards the
|
|
26
|
+
* checker itself against a silently-green normalisation bug.
|
|
27
|
+
*
|
|
28
|
+
* Exit codes: 0 = clean / selftest passed, 1 = missing invariant(s) or
|
|
29
|
+
* selftest failure, 2 = usage error, 3 = internal error.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import * as fs from 'node:fs';
|
|
33
|
+
import * as path from 'node:path';
|
|
34
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
35
|
+
|
|
36
|
+
// src/scripts/check_rule_invariants.ts → two dirs up is the repo root.
|
|
37
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
38
|
+
const ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
39
|
+
|
|
40
|
+
const INVARIANTS_JSON = 'tests/golden/invariants.json';
|
|
41
|
+
|
|
42
|
+
interface InvariantEntry {
|
|
43
|
+
rule: string;
|
|
44
|
+
file: string;
|
|
45
|
+
dist: string;
|
|
46
|
+
strings: string[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface Miss {
|
|
50
|
+
rule: string;
|
|
51
|
+
file: string;
|
|
52
|
+
invariant: string;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Collapse every run of whitespace (incl. newlines) to a single space. */
|
|
56
|
+
function normalize(text: string): string {
|
|
57
|
+
return text.replace(/\s+/g, ' ').trim();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function loadEntries(root: string): InvariantEntry[] {
|
|
61
|
+
const p = path.join(root, INVARIANTS_JSON);
|
|
62
|
+
const raw = fs.readFileSync(p, 'utf-8');
|
|
63
|
+
const parsed = JSON.parse(raw) as unknown;
|
|
64
|
+
if (!Array.isArray(parsed)) {
|
|
65
|
+
throw new Error(`${INVARIANTS_JSON}: expected a top-level array`);
|
|
66
|
+
}
|
|
67
|
+
// A leading `{"_meta": ...}` element carries the change-process pointer
|
|
68
|
+
// (JSON has no comments); it is not an invariant entry.
|
|
69
|
+
const entries = (parsed as Array<InvariantEntry | { _meta: unknown }>).filter(
|
|
70
|
+
(e): e is InvariantEntry => !('_meta' in e),
|
|
71
|
+
);
|
|
72
|
+
for (const entry of entries) {
|
|
73
|
+
if (
|
|
74
|
+
typeof entry.rule !== 'string' ||
|
|
75
|
+
typeof entry.file !== 'string' ||
|
|
76
|
+
typeof entry.dist !== 'string' ||
|
|
77
|
+
!Array.isArray(entry.strings) ||
|
|
78
|
+
entry.strings.some((s) => typeof s !== 'string' || s.length === 0)
|
|
79
|
+
) {
|
|
80
|
+
throw new Error(
|
|
81
|
+
`${INVARIANTS_JSON}: malformed entry ${JSON.stringify(entry.rule ?? entry)}`,
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return entries;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Check one entry against pre-normalised file contents. */
|
|
89
|
+
function checkEntry(
|
|
90
|
+
entry: InvariantEntry,
|
|
91
|
+
normalizedByFile: ReadonlyMap<string, string>,
|
|
92
|
+
): Miss[] {
|
|
93
|
+
const misses: Miss[] = [];
|
|
94
|
+
for (const target of [entry.file, entry.dist]) {
|
|
95
|
+
const haystack = normalizedByFile.get(target);
|
|
96
|
+
if (haystack === undefined) {
|
|
97
|
+
for (const s of entry.strings) {
|
|
98
|
+
misses.push({ rule: entry.rule, file: target, invariant: s });
|
|
99
|
+
}
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
for (const s of entry.strings) {
|
|
103
|
+
if (!haystack.includes(normalize(s))) {
|
|
104
|
+
misses.push({ rule: entry.rule, file: target, invariant: s });
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return misses;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function readNormalized(root: string, entries: readonly InvariantEntry[]): Map<string, string> {
|
|
112
|
+
const out = new Map<string, string>();
|
|
113
|
+
for (const entry of entries) {
|
|
114
|
+
for (const target of [entry.file, entry.dist]) {
|
|
115
|
+
if (out.has(target)) {
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const p = path.join(root, target);
|
|
119
|
+
try {
|
|
120
|
+
out.set(target, normalize(fs.readFileSync(p, 'utf-8')));
|
|
121
|
+
} catch {
|
|
122
|
+
// Leave absent — checkEntry reports every string as missing.
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return out;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function scan(root: string): Miss[] {
|
|
130
|
+
const entries = loadEntries(root);
|
|
131
|
+
const normalizedByFile = readNormalized(root, entries);
|
|
132
|
+
const misses: Miss[] = [];
|
|
133
|
+
for (const entry of entries) {
|
|
134
|
+
misses.push(...checkEntry(entry, normalizedByFile));
|
|
135
|
+
}
|
|
136
|
+
return misses;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function formatText(misses: Miss[], invariantCount: number): string {
|
|
140
|
+
if (misses.length === 0) {
|
|
141
|
+
return `✅ All ${invariantCount} kernel rule invariants present in src + dist.`;
|
|
142
|
+
}
|
|
143
|
+
const lines: string[] = [
|
|
144
|
+
`❌ ${misses.length} missing kernel rule invariant(s):\n`,
|
|
145
|
+
];
|
|
146
|
+
for (const m of misses) {
|
|
147
|
+
lines.push(` 🔴 ${m.rule} — ${m.file}\n missing: "${m.invariant}"`);
|
|
148
|
+
}
|
|
149
|
+
lines.push(
|
|
150
|
+
'\nA kernel rule lost a load-bearing clause — likely a merge or condensation ' +
|
|
151
|
+
'dropped it silently (see the #840/#844 incident in this file header). ' +
|
|
152
|
+
'Restore the clause, or reword it via the documented change process: ' +
|
|
153
|
+
'docs/contracts/kernel-membership.md § 10 — Changing a protected invariant ' +
|
|
154
|
+
'(never "update the gate green").',
|
|
155
|
+
);
|
|
156
|
+
return lines.join('\n');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Mutation self-test: remove the first invariant string from its src file's
|
|
161
|
+
* content in-memory and verify the check catches the absence.
|
|
162
|
+
*/
|
|
163
|
+
function mutationSelftest(root: string): number {
|
|
164
|
+
const entries = loadEntries(root);
|
|
165
|
+
const first = entries[0];
|
|
166
|
+
if (first === undefined || first.strings[0] === undefined) {
|
|
167
|
+
process.stderr.write('mutation-selftest: no invariants defined\n');
|
|
168
|
+
return 1;
|
|
169
|
+
}
|
|
170
|
+
const invariant = first.strings[0];
|
|
171
|
+
const p = path.join(root, first.file);
|
|
172
|
+
const original = normalize(fs.readFileSync(p, 'utf-8'));
|
|
173
|
+
const needle = normalize(invariant);
|
|
174
|
+
if (!original.includes(needle)) {
|
|
175
|
+
process.stderr.write(
|
|
176
|
+
`mutation-selftest: baseline broken — "${invariant}" not present in ${first.file}\n`,
|
|
177
|
+
);
|
|
178
|
+
return 1;
|
|
179
|
+
}
|
|
180
|
+
const mutated = original.split(needle).join('');
|
|
181
|
+
if (mutated.includes(needle)) {
|
|
182
|
+
process.stderr.write('mutation-selftest: mutation did not remove the string\n');
|
|
183
|
+
return 1;
|
|
184
|
+
}
|
|
185
|
+
// Run the REAL check path against the mutated content: swap the src
|
|
186
|
+
// file's normalised content in-memory and assert checkEntry reports
|
|
187
|
+
// the removed invariant as missing.
|
|
188
|
+
const normalizedByFile = readNormalized(root, [first]);
|
|
189
|
+
normalizedByFile.set(first.file, mutated);
|
|
190
|
+
const misses = checkEntry(first, normalizedByFile);
|
|
191
|
+
const detected = misses.some(
|
|
192
|
+
(m) => m.file === first.file && m.invariant === invariant,
|
|
193
|
+
);
|
|
194
|
+
if (!detected) {
|
|
195
|
+
process.stderr.write(
|
|
196
|
+
`mutation-selftest: FAILED — removing "${invariant}" from ${first.file} was NOT detected\n`,
|
|
197
|
+
);
|
|
198
|
+
return 1;
|
|
199
|
+
}
|
|
200
|
+
process.stdout.write(
|
|
201
|
+
`✅ mutation-selftest passed: removing "${invariant}" from ${first.file} is detected.\n`,
|
|
202
|
+
);
|
|
203
|
+
return 0;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
interface ParsedArgs {
|
|
207
|
+
root: string;
|
|
208
|
+
mutationSelftest: boolean;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function parse_args(argv: readonly string[]): ParsedArgs {
|
|
212
|
+
let root = ROOT;
|
|
213
|
+
let selftest = false;
|
|
214
|
+
for (let i = 0; i < argv.length; i++) {
|
|
215
|
+
const arg = argv[i]!;
|
|
216
|
+
if (arg === '--root') {
|
|
217
|
+
const v = argv[++i];
|
|
218
|
+
if (v === undefined) {
|
|
219
|
+
_argparse_error('argument --root: expected one argument');
|
|
220
|
+
}
|
|
221
|
+
root = v;
|
|
222
|
+
} else if (arg.startsWith('--root=')) {
|
|
223
|
+
root = arg.slice('--root='.length);
|
|
224
|
+
} else if (arg === '--mutation-selftest') {
|
|
225
|
+
selftest = true;
|
|
226
|
+
} else if (arg === '-h' || arg === '--help') {
|
|
227
|
+
process.stdout.write(
|
|
228
|
+
'usage: check_rule_invariants [-h] [--root ROOT] [--mutation-selftest]\n',
|
|
229
|
+
);
|
|
230
|
+
process.exit(0);
|
|
231
|
+
} else {
|
|
232
|
+
_argparse_error(`unrecognized arguments: ${arg}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return { root, mutationSelftest: selftest };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function _argparse_error(message: string): never {
|
|
239
|
+
process.stderr.write(`check_rule_invariants: error: ${message}\n`);
|
|
240
|
+
process.exit(2);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function main(): number {
|
|
244
|
+
const args = parse_args(process.argv.slice(2));
|
|
245
|
+
try {
|
|
246
|
+
if (args.mutationSelftest) {
|
|
247
|
+
return mutationSelftest(args.root);
|
|
248
|
+
}
|
|
249
|
+
const entries = loadEntries(args.root);
|
|
250
|
+
const invariantCount = entries.reduce((n, e) => n + e.strings.length, 0);
|
|
251
|
+
const misses = scan(args.root);
|
|
252
|
+
process.stdout.write(formatText(misses, invariantCount) + '\n');
|
|
253
|
+
return misses.length ? 1 : 0;
|
|
254
|
+
} catch (e) {
|
|
255
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
256
|
+
process.stderr.write(`Internal error: ${msg}\n`);
|
|
257
|
+
return 3;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function _isCliEntry(): boolean {
|
|
262
|
+
if (process.argv[1] === undefined) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
266
|
+
if (import.meta.url === argvUrl) {
|
|
267
|
+
return true;
|
|
268
|
+
}
|
|
269
|
+
try {
|
|
270
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
271
|
+
const argv = fs.realpathSync(path.resolve(process.argv[1]));
|
|
272
|
+
return here === argv;
|
|
273
|
+
} catch {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
if (_isCliEntry() || process.argv[1] === _HERE) {
|
|
279
|
+
process.exit(main());
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
export { type InvariantEntry, type Miss, ROOT, INVARIANTS_JSON, normalize, scan, main };
|
package/src/scripts/condense.ts
CHANGED
|
@@ -1634,10 +1634,20 @@ export function generate_claude_subagents(): number {
|
|
|
1634
1634
|
}
|
|
1635
1635
|
_mkdirp(MODULE_STATE.CLAUDE_AGENTS_DIR);
|
|
1636
1636
|
|
|
1637
|
-
const sources = _rglobSorted(MODULE_STATE.SUBAGENTS_SOURCE, '*.md').filter(
|
|
1637
|
+
const sources = _rglobSorted(MODULE_STATE.SUBAGENTS_SOURCE, '*.md').filter(
|
|
1638
|
+
(p) => _isFile(p) && !path.basename(p).startsWith('_'),
|
|
1639
|
+
);
|
|
1638
1640
|
const current = new Set<string>();
|
|
1639
1641
|
let count = 0;
|
|
1640
1642
|
|
|
1643
|
+
// Prompt-defense preamble partial (road-to-opt-subagent-harvest P1.1):
|
|
1644
|
+
// `_`-prefixed files in src/subagents/ are partials, never agents. The
|
|
1645
|
+
// preamble is injected at the top of every projected body so the whole
|
|
1646
|
+
// fleet carries a uniform injection-defense baseline — each dispatched
|
|
1647
|
+
// subagent is an untrusted-content ingestion point.
|
|
1648
|
+
const defensePath = path.join(MODULE_STATE.SUBAGENTS_SOURCE, '_prompt-defense.md');
|
|
1649
|
+
const defense = _isFile(defensePath) ? _readText(defensePath).trim() : '';
|
|
1650
|
+
|
|
1641
1651
|
for (const src of sources) {
|
|
1642
1652
|
const stem = path.basename(src, '.md');
|
|
1643
1653
|
const text = _readText(src);
|
|
@@ -1661,6 +1671,10 @@ export function generate_claude_subagents(): number {
|
|
|
1661
1671
|
const tier = typeof fm['model_tier'] === 'string' ? (fm['model_tier'] as string) : 'inherit';
|
|
1662
1672
|
const model = tier === 'inherit' ? 'inherit' : (_TIER_TO_CLAUDE_MODEL[tier] ?? 'inherit');
|
|
1663
1673
|
|
|
1674
|
+
const guardedBody =
|
|
1675
|
+
defense !== '' && !body.includes('prompt-defense-preamble')
|
|
1676
|
+
? `\n${defense}\n${body}`
|
|
1677
|
+
: body;
|
|
1664
1678
|
const out =
|
|
1665
1679
|
'---\n' +
|
|
1666
1680
|
`name: ${name}\n` +
|
|
@@ -1668,7 +1682,7 @@ export function generate_claude_subagents(): number {
|
|
|
1668
1682
|
`tools: ${tools}\n` +
|
|
1669
1683
|
`model: ${model}\n` +
|
|
1670
1684
|
'---\n' +
|
|
1671
|
-
|
|
1685
|
+
guardedBody;
|
|
1672
1686
|
|
|
1673
1687
|
const target = path.join(MODULE_STATE.CLAUDE_AGENTS_DIR, `${name}.md`);
|
|
1674
1688
|
_writeText(target, out);
|