@event4u/agent-config 8.10.0 → 8.12.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/AGENTS.md +1 -0
- package/CHANGELOG.md +67 -149
- package/README.md +6 -6
- 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 +2 -1
- 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 +1 -1
- package/dist/agent-src/commands/worktree/cleanup.md +22 -17
- package/dist/agent-src/commands/worktree/create.md +3 -1
- package/dist/agent-src/commands/worktree/status.md +12 -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 +47 -3
- package/dist/agent-src/contexts/execution/roadmap-ci-steps-mechanics.md +117 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +111 -85
- 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/architecture.md +6 -51
- 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 +64 -0
- package/dist/agent-src/rules/context-hygiene.md +14 -0
- package/dist/agent-src/rules/decision-revisit-gate.md +9 -77
- package/dist/agent-src/rules/delegation-policy.md +10 -8
- package/dist/agent-src/rules/design-fidelity.md +4 -0
- package/dist/agent-src/rules/git-history-discipline.md +4 -79
- package/dist/agent-src/rules/improve-before-implement.md +7 -66
- package/dist/agent-src/rules/legal-safety-floor.md +11 -55
- package/dist/agent-src/rules/no-roadmap-references.md +13 -77
- package/dist/agent-src/rules/persona-governance.md +5 -47
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +6 -32
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +21 -104
- package/dist/agent-src/rules/roadmap-progress-sync.md +5 -56
- package/dist/agent-src/rules/think-before-action.md +10 -0
- package/dist/agent-src/rules/untrusted-input-defense.md +3 -75
- package/dist/agent-src/rules/verify-before-complete.md +12 -0
- package/dist/agent-src/skills/agent-docs-writing/SKILL.md +96 -12
- package/dist/agent-src/skills/ai-council/SKILL.md +19 -9
- package/dist/agent-src/skills/api-design/SKILL.md +7 -5
- package/dist/agent-src/skills/api-testing/SKILL.md +1 -1
- 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/code-refactoring/SKILL.md +9 -9
- package/dist/agent-src/skills/content-funnel-design/SKILL.md +2 -0
- package/dist/agent-src/skills/data-flow-mapper/SKILL.md +1 -1
- package/dist/agent-src/skills/decision-review/SKILL.md +86 -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-review/SKILL.md +23 -2
- package/dist/agent-src/skills/doc-coauthoring/SKILL.md +2 -0
- package/dist/agent-src/skills/editorial-calendar/SKILL.md +2 -0
- package/dist/agent-src/skills/fe-design/SKILL.md +7 -9
- package/dist/agent-src/skills/git-workflow/SKILL.md +86 -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/laravel/SKILL.md +14 -1
- package/dist/agent-src/skills/launch-readiness/SKILL.md +20 -19
- 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/mcp/SKILL.md +1 -1
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +14 -1
- package/dist/agent-src/skills/migration-architect/SKILL.md +2 -1
- package/dist/agent-src/skills/module-detect-on-the-fly/SKILL.md +58 -1
- package/dist/agent-src/skills/performance/SKILL.md +1 -1
- package/dist/agent-src/skills/php-debugging/SKILL.md +17 -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/release-comms/SKILL.md +2 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +22 -51
- 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/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/using-git-worktrees/SKILL.md +10 -0
- package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +27 -20
- package/dist/agent-src/skills/worktree-lifecycle/evals/evals.json +38 -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/contexts/knowledge-card.md +12 -0
- 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 +157 -88
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +6 -6
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +13 -10
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +14 -9
- 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 +54 -5
- package/docs/architecture.md +4 -4
- package/docs/archive/CHANGELOG-pre-8.12.0.md +304 -0
- package/docs/benchmark.md +90 -0
- package/docs/catalog.md +8 -5
- package/docs/command-flows.md +2 -1
- package/docs/contracts/ai-council-config.md +97 -0
- package/docs/contracts/command-clusters.md +1 -0
- 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/persona-schema.md +49 -0
- package/docs/contracts/provider-lifecycle.md +29 -4
- package/docs/contracts/release-sizing.md +22 -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-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-120-council-chairman-mode.md +70 -0
- package/docs/decisions/ADR-121-knowledge-sensitivity-classes.md +90 -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 +13 -9
- package/docs/design/council-vs-solo-baseline.md +92 -0
- package/docs/design/cross-model-parity-eval.md +82 -0
- package/docs/design/length-neutral-judge-rerun.md +92 -0
- package/docs/design/utilization-window-criteria.md +51 -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/agent-interaction-and-decision-quality.md +68 -0
- package/docs/guidelines/agent-infra/roadmap-progress-mechanics.md +80 -5
- package/docs/guidelines/agent-infra/rule-body-migration-inventory.md +241 -0
- package/docs/guidelines/agent-infra/untrusted-input-spotlighting.md +80 -3
- package/docs/guidelines/code-clarity.md +191 -1
- package/docs/guidelines/design-antipatterns.md +20 -0
- package/docs/guidelines/php/php-coding-patterns.md +12 -2
- package/docs/maintainers/branch-protection.md +87 -0
- package/docs/maintainers/system-map.md +85 -0
- package/docs/proof.md +32 -15
- package/docs/wedge/production-validator/production-validator.md +27 -0
- package/package.json +1 -1
- package/src/config/agent-settings.template.yml +38 -9
- package/src/scripts/_cli/cmd_doctor.ts +129 -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 +50 -2
- package/src/scripts/_lib/knowledge_global_promote.ts +150 -0
- 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 +14 -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 +252 -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/bench_persona_placebo.ts +308 -0
- package/src/scripts/bench_quality_rerun.ts +357 -0
- package/src/scripts/build_discovery_manifest.ts +6 -0
- package/src/scripts/build_proof.ts +30 -9
- package/src/scripts/check_artefact_count_messaging.ts +56 -0
- package/src/scripts/check_claims.ts +40 -0
- package/src/scripts/check_knowledge_cards.ts +33 -4
- package/src/scripts/check_portability.ts +1 -0
- package/src/scripts/check_rule_invariants.ts +10 -3
- package/src/scripts/complexity_report.ts +776 -0
- package/src/scripts/condense.ts +16 -2
- package/src/scripts/consumer_matrix.ts +292 -14
- package/src/scripts/council_cli.ts +203 -1
- package/src/scripts/detect_ai_tells.ts +312 -0
- package/src/scripts/explain_run.ts +593 -0
- package/src/scripts/install.ts +12 -0
- package/src/scripts/knowledge_global_cli.ts +235 -46
- 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 +1 -0
- package/src/scripts/rule_backlinks.ts +0 -0
- package/src/scripts/schemas/agent-settings.schema.json +11 -0
- package/src/scripts/self_review_gate.ts +41 -15
- package/src/scripts/skill_eval_coverage.ts +71 -3
- package/src/scripts/skill_linter.ts +1 -0
- 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
|
@@ -27,6 +27,7 @@ import { REPO, LEDGER_REL, load_ledger, pointer_unresolved } from './check_claim
|
|
|
27
27
|
import { collectSkillGaps } from './check_skill_gaps.js';
|
|
28
28
|
import { loadRows as loadComparisonRows } from './check_comparison.js';
|
|
29
29
|
import { computeStatus as domainSoundnessStatus } from './domain_soundness_status.js';
|
|
30
|
+
import { computeCoverage } from './skill_eval_coverage.js';
|
|
30
31
|
|
|
31
32
|
const _FILE = fileURLToPath(import.meta.url);
|
|
32
33
|
const OUT_REL = 'docs/proof.md';
|
|
@@ -104,20 +105,40 @@ function render(): string {
|
|
|
104
105
|
L.push(`Benchmark results — **including the runs where the package changed nothing** —`);
|
|
105
106
|
L.push(`live in [\`${BENCH_REL}\`](benchmark.md). We do not delete a measured null to`);
|
|
106
107
|
L.push('make a number look better; the null is the evidence of honesty.');
|
|
108
|
+
L.push('');
|
|
109
|
+
L.push('The freshest example: the **persona-placebo benchmark** <!-- claim:persona-identity-placebo-null -->');
|
|
110
|
+
L.push('(2026-07-12, 3 arms × 2 providers, blind rubric judge, pre-registered');
|
|
111
|
+
L.push('hypotheses) measured whether famous-figure persona framing improves decision');
|
|
112
|
+
L.push('answers over the bare method text it wraps. It does not (Δ=0.17, p=0.607) —');
|
|
113
|
+
L.push('while provider diversity moved judged quality ~15× more than persona identity.');
|
|
114
|
+
L.push('The measured null closed a planned feature (persona panel-mode) instead of');
|
|
115
|
+
L.push('shipping theater; the full per-cell data is committed at');
|
|
116
|
+
L.push('`internal/bench/reports/persona-placebo.json`.');
|
|
107
117
|
} else {
|
|
108
118
|
L.push('Benchmark results are published under `docs/` including measured nulls.');
|
|
109
119
|
}
|
|
110
120
|
L.push('');
|
|
121
|
+
const cov = computeCoverage();
|
|
122
|
+
const prio = cov.tiers.priority;
|
|
123
|
+
const other = cov.tiers.other;
|
|
124
|
+
const prioLine =
|
|
125
|
+
prio.covered === prio.total
|
|
126
|
+
? `\`rich\` + routers) are **fully covered (${prio.covered} of ${prio.total})**, the long tail`
|
|
127
|
+
: `\`rich\` + routers, **${prio.covered} of ${prio.total}**) are partially covered; the long tail`;
|
|
111
128
|
L.push('**Behavioural-eval coverage — the honest baseline.** Skill *quality* is only');
|
|
112
|
-
L.push(
|
|
113
|
-
L.push('`evals.json
|
|
114
|
-
L.push(
|
|
115
|
-
L.push(
|
|
116
|
-
L.push(
|
|
117
|
-
L.push('
|
|
118
|
-
L.push('
|
|
119
|
-
L.push('
|
|
120
|
-
L.push('
|
|
129
|
+
L.push(`as good as its measurement. Today **${cov.overall.covered} of ${cov.overall.total}** skills carry a behavioural`);
|
|
130
|
+
L.push('`evals.json`; the highest-traffic / highest-cost tiers (default-surface +');
|
|
131
|
+
L.push(prioLine);
|
|
132
|
+
L.push(`(${other.covered} of ${other.total}) is not. We publish that gap rather than imply`);
|
|
133
|
+
L.push(`"${cov.overall.total} evaluated skills": coverage is measured per tier`);
|
|
134
|
+
L.push('(`./scripts-run src/scripts/skill_eval_coverage`), **CI-ratcheted so it can');
|
|
135
|
+
L.push('only rise**, and the priority tiers carry a hard **tier floor**: every');
|
|
136
|
+
L.push('rich / default-surface / router skill MUST have a behavioural eval or an');
|
|
137
|
+
L.push('explicit exemption-with-reason in `internal/evals/tier-floor-exemptions.json`');
|
|
138
|
+
L.push('— no silent exemptions (the bright line deliberately replaces a');
|
|
139
|
+
L.push('weighted-coverage score). Authoring long-tail evals is gated on per-case');
|
|
140
|
+
L.push('human ratification (a generated assertion that checks the wrong property is');
|
|
141
|
+
L.push('worse than none), so the number grows deliberately, not overnight.');
|
|
121
142
|
L.push('');
|
|
122
143
|
const ds = domainSoundnessStatus();
|
|
123
144
|
L.push('**Non-coding domain soundness — scoped, not proven.** The `finance` /');
|
|
@@ -113,6 +113,49 @@ export function scan_text(
|
|
|
113
113
|
return { findings, seen };
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
/** Structured-surface totals — generated files whose counts are YAML fields,
|
|
117
|
+
* not prose, so the KIND_PATTERNS prose scan cannot see them. CAPABILITIES.yaml
|
|
118
|
+
* proved this gap: it drifted to 268/177 while every prose surface said
|
|
119
|
+
* 271/178, because only its own `--check` guarded it and a stale commit can
|
|
120
|
+
* land through parallel merges. This scan makes the messaging gate a second,
|
|
121
|
+
* independent net over the same canonical counts. */
|
|
122
|
+
export const STRUCTURED_SURFACES: ReadonlyArray<{
|
|
123
|
+
file: string;
|
|
124
|
+
fields: ReadonlyArray<[kind: string, pattern: RegExp]>;
|
|
125
|
+
}> = [
|
|
126
|
+
{
|
|
127
|
+
file: 'CAPABILITIES.yaml',
|
|
128
|
+
fields: [
|
|
129
|
+
['skills', /^\s*skills_total:\s*(\d+)\s*$/m],
|
|
130
|
+
['commands', /^\s*commands_total:\s*(\d+)\s*$/m],
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
];
|
|
134
|
+
|
|
135
|
+
export function scan_structured(
|
|
136
|
+
rel: string,
|
|
137
|
+
text: string,
|
|
138
|
+
fields: ReadonlyArray<[string, RegExp]>,
|
|
139
|
+
expected: Record<string, number>,
|
|
140
|
+
): { findings: Finding[]; seen: Record<string, Set<number>> } {
|
|
141
|
+
const findings: Finding[] = [];
|
|
142
|
+
const seen: Record<string, Set<number>> = {};
|
|
143
|
+
for (const [kind, pattern] of fields) {
|
|
144
|
+
const m = text.match(pattern);
|
|
145
|
+
if (m === null) {
|
|
146
|
+
continue; // absent field is the generator's own --check's problem
|
|
147
|
+
}
|
|
148
|
+
const found = Number.parseInt(m[1]!, 10);
|
|
149
|
+
(seen[kind] ??= new Set()).add(found);
|
|
150
|
+
const exp = expected[kind]!;
|
|
151
|
+
if (found !== exp) {
|
|
152
|
+
const line = text.slice(0, m.index ?? 0).split('\n').length;
|
|
153
|
+
findings.push({ file: rel, line, kind, found, expected: exp, approx: false });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return { findings, seen };
|
|
157
|
+
}
|
|
158
|
+
|
|
116
159
|
export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
117
160
|
const QUIET = argv.includes('--quiet');
|
|
118
161
|
const expected: Record<string, number> = {};
|
|
@@ -140,6 +183,19 @@ export function main(argv: readonly string[] = process.argv.slice(2)): number {
|
|
|
140
183
|
}
|
|
141
184
|
}
|
|
142
185
|
|
|
186
|
+
for (const { file, fields } of STRUCTURED_SURFACES) {
|
|
187
|
+
const p = path.join(ROOT, file);
|
|
188
|
+
if (!fs.existsSync(p)) {
|
|
189
|
+
process.stderr.write(` ⚠️ surface missing (skipped): ${file}\n`);
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
const { findings, seen } = scan_structured(file, fs.readFileSync(p, 'utf-8'), fields, expected);
|
|
193
|
+
allFindings.push(...findings);
|
|
194
|
+
for (const [kind, nums] of Object.entries(seen)) {
|
|
195
|
+
for (const n of nums) (global_seen[kind] ??= new Set()).add(n);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
143
199
|
// Internal-inconsistency check — the regression case this gate exists
|
|
144
200
|
// for: multiple DIFFERENT numbers for one kind across the surfaces.
|
|
145
201
|
const inconsistent: string[] = [];
|
|
@@ -42,6 +42,13 @@ const SURFACE_ROOTS = ['README.md', 'docs'];
|
|
|
42
42
|
const CLAIM_MARKER = /<!--\s*claim:([A-Za-z0-9._-]+)\s*-->/g;
|
|
43
43
|
const URL_DATED = /^https?:\/\/\S+\(\d{4}-\d{2}-\d{2}\)\s*$/;
|
|
44
44
|
|
|
45
|
+
/** Witness sweep (P1.2) — marketing-class surfaces where a bare number must
|
|
46
|
+
* not appear as a capability claim. docs/proof.md and docs/comparison.yaml
|
|
47
|
+
* are structurally witnessed (pointer columns + their own linters). */
|
|
48
|
+
const WITNESS_SURFACES = ['README.md', 'CAPABILITIES.yaml'];
|
|
49
|
+
/** A percentage or multiplier reading as a measured capability figure. */
|
|
50
|
+
const QUANTIFIED_CLAIM = /\b\d+(?:\.\d+)?\s*(?:%|[x×](?![A-Za-z0-9]))/;
|
|
51
|
+
|
|
45
52
|
class ExitCode extends Error {
|
|
46
53
|
code: number;
|
|
47
54
|
constructor(code: number) {
|
|
@@ -224,6 +231,39 @@ function main(argv: string[] = process.argv.slice(2)): number {
|
|
|
224
231
|
if (un) findings.push({ id: entry.id, file: LEDGER_REL, reason: `backed entry has dangling evidence — ${un}` });
|
|
225
232
|
}
|
|
226
233
|
|
|
234
|
+
// 3. Witness sweep (road-to-opt-subagent-harvest P1.2): a QUANTIFIED
|
|
235
|
+
// capability claim on a marketing-class surface must be witnessed — a
|
|
236
|
+
// `<!-- claim:ID -->` marker on the same line, or an explicit
|
|
237
|
+
// `unverified` annotation. Unmarkered numbers are exactly how an
|
|
238
|
+
// "84.8%"-style figure spreads across surfaces with no methodology
|
|
239
|
+
// (the anti-lesson this check encodes). Fenced code blocks are skipped.
|
|
240
|
+
for (const rel of WITNESS_SURFACES) {
|
|
241
|
+
const abs = path.join(REPO, rel);
|
|
242
|
+
let text: string;
|
|
243
|
+
try {
|
|
244
|
+
text = fs.readFileSync(abs, 'utf-8');
|
|
245
|
+
} catch {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
let inFence = false;
|
|
249
|
+
const lines = text.split('\n');
|
|
250
|
+
for (let i = 0; i < lines.length; i++) {
|
|
251
|
+
const line = lines[i] as string;
|
|
252
|
+
if (/^\s*(```|~~~)/.test(line)) {
|
|
253
|
+
inFence = !inFence;
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (inFence) continue;
|
|
257
|
+
if (!QUANTIFIED_CLAIM.test(line)) continue;
|
|
258
|
+
if (/<!--\s*claim:/.test(line) || /unverified/i.test(line)) continue;
|
|
259
|
+
findings.push({
|
|
260
|
+
id: '(unmarkered)',
|
|
261
|
+
file: `${rel}:${i + 1}`,
|
|
262
|
+
reason: `quantified claim without a claim marker or 'unverified' annotation — ${line.trim().slice(0, 70)}`,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
227
267
|
if (findings.length > 0) {
|
|
228
268
|
process.stderr.write(`❌ check_claims: ${findings.length} unbacked/dangling claim(s):\n`);
|
|
229
269
|
for (const f of findings) {
|
|
@@ -105,13 +105,17 @@ function _frontmatter_get(text: string, ...keys: string[]): string {
|
|
|
105
105
|
// ---------------------------------------------------------------------------
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
|
-
* Global-store-only checks (ADR-100
|
|
109
|
-
*
|
|
110
|
-
*
|
|
108
|
+
* Global-store-only checks (ADR-100 + Phase 1 sensitivity axis,
|
|
109
|
+
* road-to-feedback-8.11 / successor note to ADR-119): tier validity,
|
|
110
|
+
* sensitivity validity, provenance footer (incl. the promotion audit-trail
|
|
111
|
+
* fields), and a redaction-clean assertion (the secret/PII patterns must
|
|
112
|
+
* have been halted/cleaned before the card was written — never present in a
|
|
113
|
+
* global card).
|
|
111
114
|
*/
|
|
112
115
|
function _check_global_card(rel: string, text: string, fm: Record<string, string>): string[] {
|
|
113
116
|
const errors: string[] = [];
|
|
114
117
|
const valid_tiers = _kg !== null ? _kg.TIERS : ['public', 'vendor', 'proprietary'];
|
|
118
|
+
const valid_sensitivities = _kg !== null ? _kg.SENSITIVITIES : ['prohibited', 'project', 'shareable'];
|
|
115
119
|
|
|
116
120
|
// G1 — tier present and valid
|
|
117
121
|
const tier = (fm['tier'] ?? '').trim();
|
|
@@ -121,7 +125,27 @@ function _check_global_card(rel: string, text: string, fm: Record<string, string
|
|
|
121
125
|
errors.push(`${rel}:0 — G1: tier '${tier}' not in ${_pyReprList(_sorted(valid_tiers))}`);
|
|
122
126
|
}
|
|
123
127
|
|
|
124
|
-
//
|
|
128
|
+
// G4 — sensitivity present and valid
|
|
129
|
+
const sensitivity = (fm['sensitivity'] ?? '').trim();
|
|
130
|
+
if (!sensitivity) {
|
|
131
|
+
errors.push(`${rel}:0 — G4: global card missing 'sensitivity' in frontmatter`);
|
|
132
|
+
} else if (!valid_sensitivities.includes(sensitivity)) {
|
|
133
|
+
errors.push(
|
|
134
|
+
`${rel}:0 — G4: sensitivity '${sensitivity}' not in ${_pyReprList(_sorted(valid_sensitivities))}`,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// G6 — a `prohibited` card must never be in the global store at all: it
|
|
139
|
+
// contains redaction-class content and should never have left the
|
|
140
|
+
// project. Hard error regardless of anything else on the card.
|
|
141
|
+
if (sensitivity === 'prohibited') {
|
|
142
|
+
errors.push(
|
|
143
|
+
`${rel}:0 — G6: sensitivity 'prohibited' must never be in the global store ` +
|
|
144
|
+
'(redaction-class content — this card should never have been promoted)',
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// G2 + G5 — provenance footer present with all promotion audit-trail fields
|
|
125
149
|
if (_kg !== null) {
|
|
126
150
|
const prov = _kg.parse_provenance_footer(text);
|
|
127
151
|
if (!_pyTruthyObj(prov)) {
|
|
@@ -132,6 +156,11 @@ function _check_global_card(rel: string, text: string, fm: Record<string, string
|
|
|
132
156
|
errors.push(`${rel}:0 — G2: provenance footer missing '${field}'`);
|
|
133
157
|
}
|
|
134
158
|
}
|
|
159
|
+
for (const field of ['source_repo', 'owner', 'review_after', 'promotion_reason']) {
|
|
160
|
+
if (!prov[field]) {
|
|
161
|
+
errors.push(`${rel}:0 — G5: provenance footer missing '${field}'`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
135
164
|
}
|
|
136
165
|
}
|
|
137
166
|
|
|
@@ -468,6 +468,7 @@ const _TASK_DETECTOR_SKIP = [
|
|
|
468
468
|
// CI-shaped literals; its mechanics doc and the execution loop +
|
|
469
469
|
// authoring skill enumerate the same literals to detect them.
|
|
470
470
|
'rules/roadmap-ci-steps-policy.md',
|
|
471
|
+
'contexts/execution/roadmap-ci-steps-mechanics.md',
|
|
471
472
|
'contexts/execution/roadmap-process-loop.md',
|
|
472
473
|
'skills/roadmap-writing/SKILL.md',
|
|
473
474
|
];
|
|
@@ -64,7 +64,12 @@ function loadEntries(root: string): InvariantEntry[] {
|
|
|
64
64
|
if (!Array.isArray(parsed)) {
|
|
65
65
|
throw new Error(`${INVARIANTS_JSON}: expected a top-level array`);
|
|
66
66
|
}
|
|
67
|
-
|
|
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) {
|
|
68
73
|
if (
|
|
69
74
|
typeof entry.rule !== 'string' ||
|
|
70
75
|
typeof entry.file !== 'string' ||
|
|
@@ -77,7 +82,7 @@ function loadEntries(root: string): InvariantEntry[] {
|
|
|
77
82
|
);
|
|
78
83
|
}
|
|
79
84
|
}
|
|
80
|
-
return
|
|
85
|
+
return entries;
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
/** Check one entry against pre-normalised file contents. */
|
|
@@ -144,7 +149,9 @@ function formatText(misses: Miss[], invariantCount: number): string {
|
|
|
144
149
|
lines.push(
|
|
145
150
|
'\nA kernel rule lost a load-bearing clause — likely a merge or condensation ' +
|
|
146
151
|
'dropped it silently (see the #840/#844 incident in this file header). ' +
|
|
147
|
-
'Restore the clause or
|
|
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").',
|
|
148
155
|
);
|
|
149
156
|
return lines.join('\n');
|
|
150
157
|
}
|