@event4u/agent-config 8.7.0 → 8.9.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 +109 -222
- package/CONTRIBUTING.md +25 -0
- package/README.md +7 -4
- package/dist/agent-src/commands/agent-handoff.md +39 -2
- package/dist/agent-src/commands/research/deep.md +8 -0
- package/dist/agent-src/commands/research/report.md +7 -0
- package/dist/agent-src/commands/roadmap/create.md +12 -0
- package/dist/agent-src/commands/roadmap/process-full.md +31 -5
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +30 -1
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +1 -1
- package/dist/agent-src/contexts/execution/orchestration-benchmark-gate.md +28 -16
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +36 -5
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +37 -0
- package/dist/agent-src/contexts/execution/subagent-topologies.md +34 -0
- package/dist/agent-src/contexts/execution/verification-mechanics.md +9 -9
- package/dist/agent-src/rules/active-remediation.md +92 -0
- package/dist/agent-src/rules/agent-authority.md +1 -1
- package/dist/agent-src/rules/broken-access-control.md +106 -0
- package/dist/agent-src/rules/communication-through-line.md +42 -0
- package/dist/agent-src/rules/decision-revisit-gate.md +8 -0
- package/dist/agent-src/rules/delegation-policy.md +5 -0
- package/dist/agent-src/rules/direct-answers.md +1 -1
- package/dist/agent-src/rules/downstream-changes.md +1 -0
- package/dist/agent-src/rules/external-code-graph-interop.md +65 -0
- package/dist/agent-src/rules/git-history-discipline.md +18 -0
- package/dist/agent-src/rules/lethal-trifecta-guard.md +6 -1
- package/dist/agent-src/rules/minimal-safe-diff.md +66 -1
- package/dist/agent-src/rules/non-destructive-by-default.md +3 -0
- package/dist/agent-src/rules/prefer-enums-over-literals.md +65 -0
- package/dist/agent-src/rules/question-not-instruction.md +76 -0
- package/dist/agent-src/rules/senior-engineering-discipline.md +82 -0
- package/dist/agent-src/rules/think-before-action.md +1 -0
- package/dist/agent-src/rules/tool-safety.md +8 -0
- package/dist/agent-src/rules/untrusted-input-defense.md +87 -22
- package/dist/agent-src/scripts/update_roadmap_progress.ts +2 -1
- package/dist/agent-src/skills/accessibility-auditor/SKILL.md +19 -0
- package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +112 -0
- package/dist/agent-src/skills/ai-code-blindspots/evals/triggers.json +52 -0
- package/dist/agent-src/skills/authz-review/SKILL.md +21 -4
- package/dist/agent-src/skills/code-review/SKILL.md +2 -0
- package/dist/agent-src/skills/command-writing/SKILL.md +53 -40
- package/dist/agent-src/skills/dcf-modeling/evals/domain-truth.json +29 -0
- package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +1 -0
- package/dist/agent-src/skills/dependency-upgrade/SKILL.md +20 -0
- package/dist/agent-src/skills/design-intelligence/SKILL.md +49 -12
- package/dist/agent-src/skills/design-review/SKILL.md +29 -15
- package/dist/agent-src/skills/design-system-capture/SKILL.md +63 -24
- package/dist/agent-src/skills/forecasting/evals/domain-truth.json +29 -0
- package/dist/agent-src/skills/frontend-render-security/SKILL.md +104 -0
- package/dist/agent-src/skills/frontend-render-security/evals/triggers.json +52 -0
- package/dist/agent-src/skills/markitdown/SKILL.md +1 -0
- package/dist/agent-src/skills/mcp/SKILL.md +24 -0
- package/dist/agent-src/skills/mcp-builder/SKILL.md +9 -1
- package/dist/agent-src/skills/memory-consolidation/SKILL.md +55 -4
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +46 -5
- package/dist/agent-src/skills/runway-cognition/evals/domain-truth.json +29 -0
- package/dist/agent-src/skills/scenario-modeling/evals/domain-truth.json +29 -0
- package/dist/agent-src/skills/secrets-management/SKILL.md +7 -0
- package/dist/agent-src/skills/skill-writing/SKILL.md +12 -3
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +27 -33
- package/dist/agent-src/skills/supply-chain-intake/SKILL.md +112 -0
- package/dist/agent-src/skills/supply-chain-intake/evals/triggers.json +52 -0
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +72 -2
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +9 -0
- package/dist/agent-src/skills/unit-economics-modeling/evals/domain-truth.json +40 -0
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +60 -0
- package/dist/cli/registry.js +3 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +268 -46
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +18 -8
- package/dist/discovery/trust-report.md +11 -11
- package/dist/discovery/workspaces.json +16 -6
- package/dist/install/install.mjs +141 -3
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +1 -1
- package/dist/mcp/registry-manifest.json +4 -4
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/claude_builtin_names.js +145 -0
- package/dist/scripts/_lib/claude_builtin_names.js.map +1 -0
- package/dist/scripts/condense.js +14 -0
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +2 -1
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/CLAIMS.md +58 -2
- package/docs/architecture.md +3 -3
- package/docs/archive/CHANGELOG-pre-8.9.0.md +306 -0
- package/docs/benchmark.md +113 -0
- package/docs/catalog.md +32 -5
- package/docs/contracts/command-clusters.md +18 -0
- package/docs/contracts/design-artifact-verification.md +124 -0
- package/docs/contracts/injected-block-authenticity-model.md +66 -0
- package/docs/contracts/mcp-tool-inventory.md +31 -30
- package/docs/decisions/ADR-061-corpus-grounding-layer.md +13 -0
- package/docs/decisions/ADR-105-automatic-subagent-orchestration.md +6 -0
- package/docs/decisions/ADR-116-memory-tripwire-activation-path.md +11 -2
- package/docs/decisions/ADR-117-subagents-auto-default-on.md +88 -0
- package/docs/decisions/INDEX.md +1 -0
- package/docs/experiences/content_creator.md +2 -0
- package/docs/experiences/finance.md +2 -0
- package/docs/experiences/founder.md +2 -0
- package/docs/experiences/ops.md +2 -0
- package/docs/featured-skills.md +2 -2
- package/docs/getting-started-by-role.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/governance-advantage.md +1 -1
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +27 -0
- package/docs/guidelines/agent-infra/emphasis-budget.md +45 -0
- package/docs/guidelines/agent-infra/memory-access.md +12 -0
- package/docs/guidelines/agent-infra/simplicity-and-goal-demos.md +151 -0
- package/docs/guidelines/agent-infra/tool-description-as-policy.md +35 -0
- package/docs/guidelines/design-canon.md +1 -0
- package/docs/proof.md +60 -3
- package/docs/release-runbook.md +138 -0
- package/docs/second-brain-scope.md +116 -0
- package/docs/succession.md +80 -0
- package/package.json +2 -2
- package/src/agent-src/scripts/update_roadmap_progress.ts +2 -1
- package/src/config/agent-settings.template.yml +25 -6
- package/src/scripts/_dispatch.bash +27 -0
- package/src/scripts/_lib/claude_builtin_names.ts +148 -0
- package/src/scripts/_lib/file_slicer.ts +117 -0
- package/src/scripts/_lib/lexical_index.ts +155 -0
- package/src/scripts/_lib/orchestration_gate.ts +12 -8
- package/src/scripts/_lib/orchestration_record.ts +170 -0
- package/src/scripts/_lib/orchestration_savings.ts +180 -0
- package/src/scripts/_lib/retrieval_sanitize.ts +71 -0
- package/src/scripts/_lib/security_lint.ts +1 -0
- package/src/scripts/_lib/stat_index.ts +98 -0
- package/src/scripts/benchmark.ts +122 -0
- package/src/scripts/build_proof.ts +51 -0
- package/src/scripts/chat_history.ts +79 -7
- package/src/scripts/check_memory.ts +2 -0
- package/src/scripts/check_quality_regression.ts +51 -0
- package/src/scripts/check_roadmap_trackable.ts +3 -2
- package/src/scripts/condense.ts +14 -0
- package/src/scripts/discovery_graph.ts +0 -0
- package/src/scripts/domain_soundness_status.ts +236 -0
- package/src/scripts/external_sources_denylist.json +4 -1
- package/src/scripts/generate_index.ts +17 -0
- package/src/scripts/hot_context_hook.ts +47 -2
- package/src/scripts/install-hooks.sh +25 -0
- package/src/scripts/install.ts +35 -2
- package/src/scripts/learning_sidecar.ts +0 -0
- package/src/scripts/lint_agent_skill_names.ts +29 -0
- package/src/scripts/lint_behavioural_eval_freshness.ts +140 -0
- package/src/scripts/lint_knowledge_scale.ts +4 -3
- package/src/scripts/lint_roadmap_complexity.ts +124 -0
- package/src/scripts/lint_versioned_cache.ts +195 -0
- package/src/scripts/mcp_server/consumer_tool_catalog.json +23 -3
- package/src/scripts/mcp_server/tools.ts +182 -1
- package/src/scripts/measure_lexical_ranking.ts +173 -0
- package/src/scripts/memory_lookup.ts +0 -0
- package/src/scripts/memory_replay.ts +285 -0
- package/src/scripts/orchestration_record.ts +140 -0
- package/src/scripts/orchestration_savings_report.ts +124 -0
- package/src/scripts/schemas/domain-truth.schema.json +94 -0
- package/src/scripts/schemas/evals.schema.json +113 -0
- package/src/scripts/schemas/skill.schema.json +4 -0
- package/src/scripts/score_domain_truth.ts +192 -0
- package/src/scripts/second_brain_retrieval.ts +278 -0
- package/src/scripts/second_brain_run.ts +341 -0
- package/src/scripts/second_brain_score.ts +186 -0
- package/src/scripts/session_memory_index.ts +94 -0
- package/src/scripts/skill_eval_coverage.ts +318 -0
- package/src/server/schemas/settings.ts +5 -2
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Succession — the minimal knowledge to take over
|
|
2
|
+
|
|
3
|
+
> **Bus-factor doc (road-to-maintainer-bus-factor Phase 3).** If the maintainer
|
|
4
|
+
> is unavailable, this is what a successor needs to keep `main` healthy and cut
|
|
5
|
+
> releases. **No secret values live here — pointers only.** Companion:
|
|
6
|
+
> [`release-runbook.md`](release-runbook.md) (the how-to-release steps).
|
|
7
|
+
|
|
8
|
+
## Honest bus-factor (tracked, not inflated)
|
|
9
|
+
|
|
10
|
+
- **Distinct humans who have reviewed/merged in the trailing 90 days: 1** (the
|
|
11
|
+
maintainer, `@matze4u`). The project is a single-maintainer repo; an AI
|
|
12
|
+
self-review gate (deferred — see the roadmap Phase 1) raises the floor but is
|
|
13
|
+
**not** independent human review.
|
|
14
|
+
- Recompute this number honestly at any time:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# merged PRs in the last 90 days + who reviewed them
|
|
18
|
+
gh pr list --state merged --search "merged:>=$(date -v-90d +%Y-%m-%d 2>/dev/null || date -d '90 days ago' +%Y-%m-%d)" \
|
|
19
|
+
--json number,author,reviews \
|
|
20
|
+
--jq '[.[] | .reviews[]?.author.login] | unique'
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Report the count as-is. A bus-factor of 1 stated plainly beats a bus-factor of
|
|
24
|
+
1 implied to be more.
|
|
25
|
+
|
|
26
|
+
## Secrets / tokens — where they live, what they gate
|
|
27
|
+
|
|
28
|
+
Configured in **GitHub → Settings → Secrets and variables → Actions** (repo
|
|
29
|
+
secrets), never in the tree. None is required for the *core* release (version
|
|
30
|
+
bump + tag + GitHub Release); they gate the **downstream** publish/deploy legs.
|
|
31
|
+
|
|
32
|
+
| Secret | Gates | Missing → |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `RELEASE_PR_TOKEN` (optional PAT / App token, `contents:write` + `pull-requests:write`) | Unattended release PR checks in [`release.yml`](../.github/workflows/release.yml) | One manual **"Approve workflows to run"** click per release (deliberate checkpoint, not a failure). |
|
|
35
|
+
| — (none: **npm OIDC Trusted Publishing**) | `publish-npm.yml` — uses `id-token: write`, no stored npm token | If OIDC trust is misconfigured on npmjs, npm publish fails; fix the trusted-publisher config on the npm package, not a secret. |
|
|
36
|
+
| `CLOUDFLARE_ACCOUNT_ID`, `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_WORKER_SUBDOMAIN`, `MCP_SMOKE_TOKEN` | `deploy-mcp-worker.yml` (MCP worker deploy + smoke) | MCP worker deploy skips/fails; core release unaffected. |
|
|
37
|
+
| `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY` | `cross-model-canary.yml` + any AI-council / self-review automation | Canary + council automation skip; core release unaffected. |
|
|
38
|
+
| `GITHUB_TOKEN` (auto-provided) | all workflows' default auth | n/a — GitHub injects it. |
|
|
39
|
+
|
|
40
|
+
The live source of truth for which workflow needs which secret is the
|
|
41
|
+
`secrets.*` references in [`.github/workflows/`](../.github/workflows/) — grep
|
|
42
|
+
there if this table drifts:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
grep -rhoE "secrets\.[A-Z_]+" .github/workflows/ | sort -u
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Operator-gated steps (need a human with credentials)
|
|
49
|
+
|
|
50
|
+
- **Release-PR workflow approval** — the "Approve workflows to run" click when
|
|
51
|
+
`RELEASE_PR_TOKEN` is absent (see the runbook § 3.A).
|
|
52
|
+
- **Branch-protection ruleset** — applied in GitHub → Settings → Rules UI;
|
|
53
|
+
source of truth mirrored in [`branch-protection-policy.md`](contracts/branch-protection-policy.md).
|
|
54
|
+
Not in code; a successor edits it in the UI.
|
|
55
|
+
- **Repo administration** (visibility / rename / delete) — the
|
|
56
|
+
`production-visibility` environment gates manual approval; see
|
|
57
|
+
[`CONTRIBUTING.md`](../CONTRIBUTING.md).
|
|
58
|
+
- **npm trusted-publisher config** — set on npmjs.org for the package, not in
|
|
59
|
+
this repo.
|
|
60
|
+
|
|
61
|
+
## "Healthy main" — what good looks like
|
|
62
|
+
|
|
63
|
+
- Latest `main` commit is green on all required checks for its PR shape
|
|
64
|
+
(see [`branch-protection-policy.md`](contracts/branch-protection-policy.md),
|
|
65
|
+
[`ci-green-floor.md`](contracts/ci-green-floor.md)).
|
|
66
|
+
- No drift gate red: `release-drift.yml`, `release-guard.yml`,
|
|
67
|
+
`check-visibility-drift.yml`, the consistency + claims + proof gates.
|
|
68
|
+
- `docs/CLAIMS.md` resolves (`task check-claims`); `docs/proof.md` is in sync
|
|
69
|
+
(`task build-proof-check`).
|
|
70
|
+
- No completed roadmap left unarchived in `agents/roadmaps/` (the
|
|
71
|
+
`roadmap:progress-check` backstop).
|
|
72
|
+
|
|
73
|
+
## Minimal takeover checklist
|
|
74
|
+
|
|
75
|
+
1. Get `gh` authenticated as a repo admin; confirm `gh auth status`.
|
|
76
|
+
2. Read [`release-runbook.md`](release-runbook.md) end-to-end.
|
|
77
|
+
3. Confirm the secrets above are present for whichever downstream legs matter.
|
|
78
|
+
4. Cut a `--dry-run` release (`task release -- --dry-run`) to see the pipeline
|
|
79
|
+
with zero mutations.
|
|
80
|
+
5. When ready, follow the runbook for a real release.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@event4u/agent-config",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.9.0",
|
|
4
4
|
"description": "Universal AI Agent OS — audited skills, governance rules, commands, and templates for AI coding tools (Claude Code, Cursor, Windsurf, Copilot).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"bugs": {
|
|
13
13
|
"url": "https://github.com/event4u-app/agent-config/issues"
|
|
14
14
|
},
|
|
15
|
-
"homepage": "https://
|
|
15
|
+
"homepage": "https://event4u-app.github.io/agent-config",
|
|
16
16
|
"keywords": [
|
|
17
17
|
"ai-agent",
|
|
18
18
|
"mcp",
|
|
@@ -67,8 +67,9 @@ const _require = createRequire(import.meta.url);
|
|
|
67
67
|
// CHECKBOX_RE = re.compile(r"^\s*[-*]\s+\[([ xX~\-])\]\s", re.MULTILINE)
|
|
68
68
|
const CHECKBOX_RE = /^[ \t\n\r\f\v]*[-*][ \t\n\r\f\v]+\[([ xX~\-])\][ \t\n\r\f\v]/gm;
|
|
69
69
|
// PHASE_RE (MULTILINE) — H2/H3 "Phase <id>" with optional separator + name.
|
|
70
|
+
// Numeric ids accept dotted sub-phases ("1.0", "4.1", "2.3.1").
|
|
70
71
|
const PHASE_RE =
|
|
71
|
-
/^(#{2,3})[ \t\n\r\f\v]+Phase[ \t\n\r\f\v]+(\d+[a-z]?|[IVX]+|[A-Z](?:\d+)?)(?:[\s:—\-]+([\s\S]*?))?[ \t\f\v\r]*$/gm;
|
|
72
|
+
/^(#{2,3})[ \t\n\r\f\v]+Phase[ \t\n\r\f\v]+(\d+(?:\.\d+)*[a-z]?|[IVX]+|[A-Z](?:\d+)?)(?:[\s:—\-]+([\s\S]*?))?[ \t\f\v\r]*$/gm;
|
|
72
73
|
// TITLE_RE = re.compile(r"^#\s+(?:Roadmap:\s*)?(.+?)\s*$", re.MULTILINE)
|
|
73
74
|
const TITLE_RE = /^#[ \t\n\r\f\v]+(?:Roadmap:[ \t\n\r\f\v]*)?(.+?)[ \t\f\v\r]*$/m;
|
|
74
75
|
const EXCLUDE_NAMES: ReadonlySet<string> = new Set([
|
|
@@ -524,13 +524,21 @@ subagents:
|
|
|
524
524
|
# on = auto-dispatch delegable tasks without asking (surface the choice
|
|
525
525
|
# in one line).
|
|
526
526
|
#
|
|
527
|
-
#
|
|
527
|
+
# SHIPPED default is `on` on hosts whose capability manifest reports
|
|
528
528
|
# `subagent_spawn: true`, and `off` on hosts without a subagent primitive.
|
|
529
|
-
#
|
|
530
|
-
#
|
|
531
|
-
#
|
|
532
|
-
#
|
|
533
|
-
|
|
529
|
+
# Auto-dispatch stays a no-op wherever the manifest reports
|
|
530
|
+
# `subagent_spawn: false`, regardless of this value.
|
|
531
|
+
#
|
|
532
|
+
# The default was `ask` until 2026-07-09, when it was flipped to `on` after a
|
|
533
|
+
# re-evaluation (agents/settings/contexts/orchestration-default-flip-verdict.md
|
|
534
|
+
# § 2026-07-09; ADR-117). The flip rests on a bounded-downside argument, NOT a
|
|
535
|
+
# passed benchmark: delegable slices are already cost-routed to the cheapest
|
|
536
|
+
# capable tier, classification fires only on real structural signals (never
|
|
537
|
+
# unstructured or tiny work), and every return is verified — so `on` cannot
|
|
538
|
+
# delegate frontier-priced or speculative work. `resolveShippedDefault()`
|
|
539
|
+
# remains the telemetry-driven DEMOTION gate: a measured regression demotes
|
|
540
|
+
# back to `ask`.
|
|
541
|
+
auto: on
|
|
534
542
|
|
|
535
543
|
# Route delegable sub-tasks to the lowest-capable model tier (cost + speed
|
|
536
544
|
# via model downshift). true (default) = downshift per declared model_tier;
|
|
@@ -695,6 +703,17 @@ memory:
|
|
|
695
703
|
# Example: ["api[_-]?key", "/Users/[a-z]+/Library"]
|
|
696
704
|
redact_patterns: []
|
|
697
705
|
|
|
706
|
+
# Opt-in compact memory index at session start
|
|
707
|
+
# (road-to-memory-retrieval-economy Phase 5). When `on`, session_start
|
|
708
|
+
# injects a compact index of curated entries — id + title + ~tokens,
|
|
709
|
+
# hard cap 30 rows — through the hot-context hook surface. Bodies are
|
|
710
|
+
# never injected; the model fetches full entries via memory_get on
|
|
711
|
+
# demand. Default OFF: the ship-criterion (measured hit-rate gain at
|
|
712
|
+
# bounded fixed cost) is unproven — off unless proven.
|
|
713
|
+
# off = (default) no session-start index.
|
|
714
|
+
# on = inject the compact index (spotlighted as DATA).
|
|
715
|
+
session_index: "off"
|
|
716
|
+
|
|
698
717
|
# --- Knowledge cards: global cross-project sharing (ADR-100) ---
|
|
699
718
|
#
|
|
700
719
|
# Structure-grounding v2. Promote *expensive* (remote) knowledge cards from
|
|
@@ -167,6 +167,12 @@ Tier 2 — maintenance / internal (hooks, MCP, memory, telemetry):
|
|
|
167
167
|
mcp:run Run the built-in MCP server over stdio
|
|
168
168
|
(requires `mcp:setup` first; see docs/mcp-server.md)
|
|
169
169
|
(experimental — beta gates: docs/contracts/mcp-beta-criteria.md)
|
|
170
|
+
affected Show artefacts related to <artefact> via the discovery
|
|
171
|
+
relation-graph (relation-filtered BFS). Flags: --depth N
|
|
172
|
+
graph-explain Seed on a <concept>, expand 2 hops over the discovery
|
|
173
|
+
relation-graph with a node budget. Flags: --budget N
|
|
174
|
+
benchmark Report context-token reduction vs the full always-loaded
|
|
175
|
+
projection (from the pinned token baseline). Flags: --format
|
|
170
176
|
roadmap:progress Regenerate agents/roadmaps-progress.md from open roadmaps
|
|
171
177
|
roadmap:progress-check Fail if agents/roadmaps-progress.md is stale (for CI)
|
|
172
178
|
roadmap:archive Archive completed roadmaps (branch-touched by default;
|
|
@@ -431,6 +437,24 @@ cmd_mcp_render() {
|
|
|
431
437
|
exec_ts "$script" "$@"
|
|
432
438
|
}
|
|
433
439
|
|
|
440
|
+
cmd_affected() {
|
|
441
|
+
local script
|
|
442
|
+
script="$(resolve_script "src/scripts/discovery_graph.ts")"
|
|
443
|
+
exec_ts "$script" affected "$@"
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
cmd_graph_explain() {
|
|
447
|
+
local script
|
|
448
|
+
script="$(resolve_script "src/scripts/discovery_graph.ts")"
|
|
449
|
+
exec_ts "$script" explain "$@"
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
cmd_benchmark() {
|
|
453
|
+
local script
|
|
454
|
+
script="$(resolve_script "src/scripts/benchmark.ts")"
|
|
455
|
+
exec_ts "$script" "$@"
|
|
456
|
+
}
|
|
457
|
+
|
|
434
458
|
cmd_mcp_check() {
|
|
435
459
|
local script
|
|
436
460
|
script="$(resolve_script "src/scripts/mcp_render.ts")"
|
|
@@ -1031,6 +1055,9 @@ main() {
|
|
|
1031
1055
|
mcp:setup) cmd_mcp_setup "$@" ;;
|
|
1032
1056
|
mcp:run) cmd_mcp_run "$@" ;;
|
|
1033
1057
|
use) cmd_use "$@" ;;
|
|
1058
|
+
affected) cmd_affected "$@" ;;
|
|
1059
|
+
graph-explain) cmd_graph_explain "$@" ;;
|
|
1060
|
+
benchmark) cmd_benchmark "$@" ;;
|
|
1034
1061
|
roadmap:progress) cmd_roadmap_progress "$@" ;;
|
|
1035
1062
|
roadmap:progress-check) cmd_roadmap_progress_check "$@" ;;
|
|
1036
1063
|
roadmap:archive) cmd_roadmap_archive "$@" ;;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
// Claude Code built-in command / bundled-skill names — the reserved namespace.
|
|
2
|
+
//
|
|
3
|
+
// A user- or project-scope skill (or flat command) whose name equals a
|
|
4
|
+
// built-in Claude Code slash command SHADOWS the built-in: typing `/mcp`
|
|
5
|
+
// then opens the package's skill instead of Claude Code's MCP auth dialog
|
|
6
|
+
// (observed 2026-07-10). The suite's contract is to complement the host,
|
|
7
|
+
// never to overlay or degrade it — so no Claude-facing projection may claim
|
|
8
|
+
// one of these names.
|
|
9
|
+
//
|
|
10
|
+
// Enforced at three layers:
|
|
11
|
+
// 1. `condense.ts::generate_claude_commands` — project-scope `.claude/skills/`
|
|
12
|
+
// command entries skip reserved slugs.
|
|
13
|
+
// 2. `install.ts::_apply_claude_flat_command_wrappers` — user-scope
|
|
14
|
+
// `~/.claude/` deploys neither a skill wrapper nor a flat command file
|
|
15
|
+
// for a reserved slug (nested `/cluster:sub` commands are unaffected —
|
|
16
|
+
// built-ins carry no `:`).
|
|
17
|
+
// 3. `lint_agent_skill_names.ts` — a skill in `src/skills/` (or a domain
|
|
18
|
+
// pack) with a reserved name fails CI unless it opts out of slash
|
|
19
|
+
// registration with `user-invocable: false` (Claude may still load it
|
|
20
|
+
// automatically; the built-in keeps the `/name`).
|
|
21
|
+
//
|
|
22
|
+
// Source: https://code.claude.com/docs/en/commands (fetched 2026-07-10),
|
|
23
|
+
// plus a small legacy set still present in older Claude Code versions.
|
|
24
|
+
// Refresh trigger: a package artefact stops appearing in Claude Code, or a
|
|
25
|
+
// release-notes entry adds a new built-in command.
|
|
26
|
+
|
|
27
|
+
const _CURRENT = [
|
|
28
|
+
'add-dir',
|
|
29
|
+
'advisor',
|
|
30
|
+
'agents',
|
|
31
|
+
'autofix-pr',
|
|
32
|
+
'background',
|
|
33
|
+
'batch',
|
|
34
|
+
'branch',
|
|
35
|
+
'btw',
|
|
36
|
+
'cd',
|
|
37
|
+
'chrome',
|
|
38
|
+
'claude-api',
|
|
39
|
+
'clear',
|
|
40
|
+
'code-review',
|
|
41
|
+
'color',
|
|
42
|
+
'compact',
|
|
43
|
+
'config',
|
|
44
|
+
'context',
|
|
45
|
+
'copy',
|
|
46
|
+
'cost',
|
|
47
|
+
'dataviz',
|
|
48
|
+
'debug',
|
|
49
|
+
'deep-research',
|
|
50
|
+
'design-login',
|
|
51
|
+
'design-sync',
|
|
52
|
+
'desktop',
|
|
53
|
+
'diff',
|
|
54
|
+
'doctor',
|
|
55
|
+
'effort',
|
|
56
|
+
'exit',
|
|
57
|
+
'export',
|
|
58
|
+
'fast',
|
|
59
|
+
'feedback',
|
|
60
|
+
'fewer-permission-prompts',
|
|
61
|
+
'focus',
|
|
62
|
+
'fork',
|
|
63
|
+
'goal',
|
|
64
|
+
'heapdump',
|
|
65
|
+
'help',
|
|
66
|
+
'hooks',
|
|
67
|
+
'ide',
|
|
68
|
+
'init',
|
|
69
|
+
'insights',
|
|
70
|
+
'install-github-app',
|
|
71
|
+
'install-slack-app',
|
|
72
|
+
'keybindings',
|
|
73
|
+
'login',
|
|
74
|
+
'logout',
|
|
75
|
+
'loop',
|
|
76
|
+
'mcp',
|
|
77
|
+
'memory',
|
|
78
|
+
'mobile',
|
|
79
|
+
'model',
|
|
80
|
+
'passes',
|
|
81
|
+
'permissions',
|
|
82
|
+
'plan',
|
|
83
|
+
'plugin',
|
|
84
|
+
'powerup',
|
|
85
|
+
'pr-comments',
|
|
86
|
+
'privacy-settings',
|
|
87
|
+
'radio',
|
|
88
|
+
'recap',
|
|
89
|
+
'release-notes',
|
|
90
|
+
'reload-plugins',
|
|
91
|
+
'reload-skills',
|
|
92
|
+
'remote-control',
|
|
93
|
+
'remote-env',
|
|
94
|
+
'rename',
|
|
95
|
+
'resume',
|
|
96
|
+
'review',
|
|
97
|
+
'rewind',
|
|
98
|
+
'run',
|
|
99
|
+
'run-skill-generator',
|
|
100
|
+
'sandbox',
|
|
101
|
+
'schedule',
|
|
102
|
+
'scroll-speed',
|
|
103
|
+
'security-review',
|
|
104
|
+
'setup-bedrock',
|
|
105
|
+
'setup-vertex',
|
|
106
|
+
'simplify',
|
|
107
|
+
'skills',
|
|
108
|
+
'stats',
|
|
109
|
+
'status',
|
|
110
|
+
'statusline',
|
|
111
|
+
'stickers',
|
|
112
|
+
'teleport',
|
|
113
|
+
'thinking',
|
|
114
|
+
'trust',
|
|
115
|
+
'upgrade',
|
|
116
|
+
'usage',
|
|
117
|
+
'verify',
|
|
118
|
+
'vim',
|
|
119
|
+
'web',
|
|
120
|
+
'whats-new',
|
|
121
|
+
'workflow',
|
|
122
|
+
'workflows',
|
|
123
|
+
'worktree',
|
|
124
|
+
] as const;
|
|
125
|
+
|
|
126
|
+
// Retired from the current docs but still registered by older Claude Code
|
|
127
|
+
// versions users may run — reserving them costs nothing (no package artefact
|
|
128
|
+
// uses these names) and avoids version-dependent shadowing.
|
|
129
|
+
const _LEGACY = [
|
|
130
|
+
'bashes',
|
|
131
|
+
'bug',
|
|
132
|
+
'migrate-installer',
|
|
133
|
+
'output-style',
|
|
134
|
+
'terminal-setup',
|
|
135
|
+
'theme',
|
|
136
|
+
'todos',
|
|
137
|
+
] as const;
|
|
138
|
+
|
|
139
|
+
/** Lowercase names a Claude-facing `/name` projection must never claim. */
|
|
140
|
+
export const CLAUDE_CODE_BUILTIN_NAMES: ReadonlySet<string> = new Set<string>([
|
|
141
|
+
..._CURRENT,
|
|
142
|
+
..._LEGACY,
|
|
143
|
+
]);
|
|
144
|
+
|
|
145
|
+
/** True when `slug` would shadow a Claude Code built-in command or bundled skill. */
|
|
146
|
+
export function is_claude_builtin_name(slug: string): boolean {
|
|
147
|
+
return CLAUDE_CODE_BUILTIN_NAMES.has(slug.toLowerCase());
|
|
148
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic document slicer for oversized knowledge ingest
|
|
3
|
+
* (road-to-retrieval-substrate-hardening B8).
|
|
4
|
+
*
|
|
5
|
+
* Splits a large markdown document into bounded slices at the cleanest
|
|
6
|
+
* available boundary — heading > paragraph (blank line) > line — while
|
|
7
|
+
* guaranteeing three invariants a downstream re-assembler can rely on:
|
|
8
|
+
*
|
|
9
|
+
* 1. GAP-FREE + NON-OVERLAPPING — slices cover contiguous line ranges over
|
|
10
|
+
* the whole document, in order.
|
|
11
|
+
* 2. CONCAT == ORIGINAL — joining every slice's `text` in order reproduces
|
|
12
|
+
* the input byte-for-byte (slices are exact offset ranges).
|
|
13
|
+
* 3. PARENTED — every slice carries its source `parentPath` (when given) and
|
|
14
|
+
* its `[startLine, endLine)` range, so a chunk can point home.
|
|
15
|
+
*
|
|
16
|
+
* Deterministic: identical input + budget → identical slices.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
export interface Slice {
|
|
20
|
+
parentPath: string | null;
|
|
21
|
+
index: number;
|
|
22
|
+
startLine: number; // 0-based, inclusive
|
|
23
|
+
endLine: number; // 0-based, exclusive
|
|
24
|
+
text: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** Default per-slice character budget. */
|
|
28
|
+
export const DEFAULT_MAX_CHARS = 2000;
|
|
29
|
+
|
|
30
|
+
function _lineStartOffsets(text: string): number[] {
|
|
31
|
+
const starts = [0];
|
|
32
|
+
for (let i = 0; i < text.length; i++) {
|
|
33
|
+
if (text[i] === '\n') starts.push(i + 1);
|
|
34
|
+
}
|
|
35
|
+
return starts; // one entry per line; starts[k] = offset where line k begins
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function _isHeading(line: string): boolean {
|
|
39
|
+
return /^#{1,6}\s/.test(line);
|
|
40
|
+
}
|
|
41
|
+
function _isBlank(line: string): boolean {
|
|
42
|
+
return line.trim() === '';
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Slice `text` into ≤ `maxChars` pieces (best-effort — a single over-long line
|
|
47
|
+
* is emitted whole rather than split mid-line, preserving invariant 2).
|
|
48
|
+
* `parentPath` is stamped on every slice.
|
|
49
|
+
*/
|
|
50
|
+
export function sliceDocument(
|
|
51
|
+
text: string,
|
|
52
|
+
opts: { maxChars?: number; parentPath?: string } = {},
|
|
53
|
+
): Slice[] {
|
|
54
|
+
const maxChars = opts.maxChars ?? DEFAULT_MAX_CHARS;
|
|
55
|
+
const parentPath = opts.parentPath ?? null;
|
|
56
|
+
if (text === '') return [];
|
|
57
|
+
|
|
58
|
+
const starts = _lineStartOffsets(text);
|
|
59
|
+
const nLines = starts.length;
|
|
60
|
+
// lineAt(k) = the raw text of line k INCLUDING its trailing newline (if any).
|
|
61
|
+
const lineEnd = (k: number): number => (k + 1 < nLines ? starts[k + 1]! : text.length);
|
|
62
|
+
const lines: string[] = [];
|
|
63
|
+
for (let k = 0; k < nLines; k++) lines.push(text.slice(starts[k]!, lineEnd(k)));
|
|
64
|
+
|
|
65
|
+
const slices: Slice[] = [];
|
|
66
|
+
let sliceStartLine = 0;
|
|
67
|
+
let idx = 0;
|
|
68
|
+
const flush = (endLine: number): void => {
|
|
69
|
+
if (endLine <= sliceStartLine) return;
|
|
70
|
+
const from = starts[sliceStartLine]!;
|
|
71
|
+
const to = endLine < nLines ? starts[endLine]! : text.length;
|
|
72
|
+
slices.push({ parentPath, index: idx++, startLine: sliceStartLine, endLine, text: text.slice(from, to) });
|
|
73
|
+
sliceStartLine = endLine;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
let curChars = 0;
|
|
77
|
+
for (let k = 0; k < nLines; k++) {
|
|
78
|
+
const lineLen = lines[k]!.length;
|
|
79
|
+
const wouldExceed = curChars + lineLen > maxChars && k > sliceStartLine;
|
|
80
|
+
// Cut BEFORE a heading that opens a new section (clean boundary), or
|
|
81
|
+
// when the budget would overflow — preferring a preceding blank line.
|
|
82
|
+
const headingBoundary = _isHeading(lines[k]!) && k > sliceStartLine;
|
|
83
|
+
if (headingBoundary || wouldExceed) {
|
|
84
|
+
// Prefer to end the previous slice at the last blank line in-range,
|
|
85
|
+
// so a slice ends on a paragraph boundary when one is available.
|
|
86
|
+
let cut = k;
|
|
87
|
+
if (wouldExceed && !headingBoundary) {
|
|
88
|
+
for (let b = k - 1; b > sliceStartLine; b--) {
|
|
89
|
+
if (_isBlank(lines[b]!)) {
|
|
90
|
+
cut = b + 1;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
flush(cut);
|
|
96
|
+
curChars = 0;
|
|
97
|
+
for (let j = sliceStartLine; j <= k; j++) curChars += lines[j]!.length;
|
|
98
|
+
} else {
|
|
99
|
+
curChars += lineLen;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
flush(nLines);
|
|
103
|
+
return slices;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** True iff the slices reproduce `text` exactly, gap-free and non-overlapping. */
|
|
107
|
+
export function verifySlices(text: string, slices: readonly Slice[]): boolean {
|
|
108
|
+
if (slices.length === 0) return text === '';
|
|
109
|
+
let expectedLine = 0;
|
|
110
|
+
const parts: string[] = [];
|
|
111
|
+
for (const s of slices) {
|
|
112
|
+
if (s.startLine !== expectedLine) return false; // gap or overlap
|
|
113
|
+
expectedLine = s.endLine;
|
|
114
|
+
parts.push(s.text);
|
|
115
|
+
}
|
|
116
|
+
return parts.join('') === text;
|
|
117
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hand-rolled, dependency-free lexical index for memory/knowledge retrieval
|
|
3
|
+
* (road-to-retrieval-substrate-hardening B2).
|
|
4
|
+
*
|
|
5
|
+
* The current `memory_lookup._score` gives every keyword match the SAME coarse
|
|
6
|
+
* bucket (0.8 glob / 0.6 substring), so several entries tie at the top and
|
|
7
|
+
* retrieval "recalls but does not rank" (the mean-tie-set 3.3 finding from
|
|
8
|
+
* road-to-second-brain-retrieval-precision). This module replaces that bucket
|
|
9
|
+
* with a continuous BM25 score over an IDF-weighted term index, plus a
|
|
10
|
+
* character-trigram candidate prefilter so it stays cheap at corpus scale.
|
|
11
|
+
*
|
|
12
|
+
* It is the BM25 core ADR-061 already sanctions — pure Node stdlib, NO engine
|
|
13
|
+
* fork, NO minisearch-class dependency. `_score` stays as the below-tripwire
|
|
14
|
+
* mini-corpus fallback; this index activates at the `lint_knowledge_scale`
|
|
15
|
+
* tripwire. Deterministic: identical docs + query → identical scores + order.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/** BM25 term-frequency saturation. */
|
|
19
|
+
export const BM25_K1 = 1.5;
|
|
20
|
+
/** BM25 length-normalisation strength. */
|
|
21
|
+
export const BM25_B = 0.75;
|
|
22
|
+
/** Minimum token length kept (drops single chars / punctuation noise). */
|
|
23
|
+
export const MIN_TOKEN_LEN = 2;
|
|
24
|
+
|
|
25
|
+
export interface IndexDoc {
|
|
26
|
+
id: string;
|
|
27
|
+
/** All searchable text of the entry, already concatenated. */
|
|
28
|
+
text: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface DocStats {
|
|
32
|
+
id: string;
|
|
33
|
+
len: number; // token count
|
|
34
|
+
tf: Map<string, number>; // term → frequency in this doc
|
|
35
|
+
trigrams: Set<string>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Lowercase, split on non-alphanumeric, keep tokens ≥ MIN_TOKEN_LEN. */
|
|
39
|
+
export function tokenize(s: string): string[] {
|
|
40
|
+
const out: string[] = [];
|
|
41
|
+
for (const raw of s.toLowerCase().split(/[^a-z0-9]+/)) {
|
|
42
|
+
if (raw.length >= MIN_TOKEN_LEN) out.push(raw);
|
|
43
|
+
}
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Character trigrams of a normalised string (alphanumerics + single spaces). */
|
|
48
|
+
export function trigrams(s: string): Set<string> {
|
|
49
|
+
const norm = s.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim();
|
|
50
|
+
const out = new Set<string>();
|
|
51
|
+
if (norm.length < 3) {
|
|
52
|
+
if (norm.length > 0) out.add(norm);
|
|
53
|
+
return out;
|
|
54
|
+
}
|
|
55
|
+
for (let i = 0; i + 3 <= norm.length; i++) {
|
|
56
|
+
out.add(norm.slice(i, i + 3));
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* An in-memory BM25 index over a fixed document set. Built once, queried many
|
|
63
|
+
* times. Stateless after construction — `rank()` / `score()` never mutate it,
|
|
64
|
+
* so a cached instance is safe to reuse until the underlying corpus changes.
|
|
65
|
+
*/
|
|
66
|
+
export class LexicalIndex {
|
|
67
|
+
private readonly docs: Map<string, DocStats> = new Map();
|
|
68
|
+
private readonly df: Map<string, number> = new Map();
|
|
69
|
+
private readonly n: number;
|
|
70
|
+
private readonly avgdl: number;
|
|
71
|
+
|
|
72
|
+
constructor(documents: readonly IndexDoc[]) {
|
|
73
|
+
let totalLen = 0;
|
|
74
|
+
for (const d of documents) {
|
|
75
|
+
const tokens = tokenize(d.text);
|
|
76
|
+
const tf = new Map<string, number>();
|
|
77
|
+
for (const t of tokens) tf.set(t, (tf.get(t) ?? 0) + 1);
|
|
78
|
+
for (const t of tf.keys()) this.df.set(t, (this.df.get(t) ?? 0) + 1);
|
|
79
|
+
this.docs.set(d.id, { id: d.id, len: tokens.length, tf, trigrams: trigrams(d.text) });
|
|
80
|
+
totalLen += tokens.length;
|
|
81
|
+
}
|
|
82
|
+
this.n = documents.length;
|
|
83
|
+
this.avgdl = this.n > 0 ? totalLen / this.n : 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Robertson–Spärck-Jones IDF, floored at 0 so common terms never subtract. */
|
|
87
|
+
private idf(term: string): number {
|
|
88
|
+
const df = this.df.get(term) ?? 0;
|
|
89
|
+
if (df === 0) return 0;
|
|
90
|
+
return Math.max(0, Math.log(1 + (this.n - df + 0.5) / (df + 0.5)));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/** BM25 score of one document against the tokenised query terms. */
|
|
94
|
+
score(queryTerms: readonly string[], docId: string): number {
|
|
95
|
+
const doc = this.docs.get(docId);
|
|
96
|
+
if (doc === undefined || doc.len === 0) return 0;
|
|
97
|
+
let s = 0;
|
|
98
|
+
for (const term of queryTerms) {
|
|
99
|
+
const tf = doc.tf.get(term);
|
|
100
|
+
if (tf === undefined) continue;
|
|
101
|
+
const idf = this.idf(term);
|
|
102
|
+
if (idf === 0) continue;
|
|
103
|
+
const denom = tf + BM25_K1 * (1 - BM25_B + (BM25_B * doc.len) / (this.avgdl || 1));
|
|
104
|
+
s += (idf * (tf * (BM25_K1 + 1))) / denom;
|
|
105
|
+
}
|
|
106
|
+
return s;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Rank documents for a set of query keys (phrases are tokenised). A
|
|
111
|
+
* character-trigram prefilter selects candidates cheaply; the guard keeps
|
|
112
|
+
* any doc sharing a query TOKEN even when no trigram overlaps, so the
|
|
113
|
+
* prefilter never drops a genuine lexical match. Ties break by id for a
|
|
114
|
+
* stable, deterministic order.
|
|
115
|
+
*/
|
|
116
|
+
rank(queryKeys: readonly string[]): Array<{ id: string; score: number }> {
|
|
117
|
+
const queryText = queryKeys.join(' ');
|
|
118
|
+
const qTerms = tokenize(queryText);
|
|
119
|
+
const qTermSet = new Set(qTerms);
|
|
120
|
+
const qTrigrams = trigrams(queryText);
|
|
121
|
+
|
|
122
|
+
const candidates: string[] = [];
|
|
123
|
+
for (const [id, doc] of this.docs) {
|
|
124
|
+
let hit = false;
|
|
125
|
+
for (const t of qTrigrams) {
|
|
126
|
+
if (doc.trigrams.has(t)) {
|
|
127
|
+
hit = true;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (!hit) {
|
|
132
|
+
// Guard: keep a doc that shares an exact query token even with
|
|
133
|
+
// no trigram overlap (short tokens / edge normalisation).
|
|
134
|
+
for (const t of qTermSet) {
|
|
135
|
+
if (doc.tf.has(t)) {
|
|
136
|
+
hit = true;
|
|
137
|
+
break;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (hit) candidates.push(id);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const scored = candidates
|
|
145
|
+
.map((id) => ({ id, score: this.score(qTerms, id) }))
|
|
146
|
+
.filter((r) => r.score > 0);
|
|
147
|
+
scored.sort((a, b) => (b.score - a.score) || (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
148
|
+
return scored;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Document count — for the caller's tripwire / diagnostics. */
|
|
152
|
+
get size(): number {
|
|
153
|
+
return this.n;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Default-flip decision gate (Phase 6).
|
|
2
|
+
* Default-flip / demotion decision gate (Phase 6 → telemetry-demotion).
|
|
3
3
|
*
|
|
4
|
-
* Pure, no-I/O.
|
|
5
|
-
* `subagents.auto`
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* Pure, no-I/O. Originally the Phase-6 falsification gate: the SHIPPED default
|
|
5
|
+
* for `subagents.auto` was to flip toward `on` ONLY on a passed benchmark.
|
|
6
|
+
*
|
|
7
|
+
* As of 2026-07-09 the shipped default IS `on` on subagent-capable hosts
|
|
8
|
+
* (ADR-117; agents/settings/contexts/orchestration-default-flip-verdict.md
|
|
9
|
+
* § 2026-07-09) — flipped on a bounded-downside re-evaluation, not a passed
|
|
10
|
+
* benchmark. This helper is therefore now the telemetry-driven DEMOTION gate:
|
|
11
|
+
* a `fail` verdict from accumulated real-world orchestration telemetry demotes
|
|
12
|
+
* the default back to `ask` (conservative). Contract:
|
|
9
13
|
* `src/agent-src/contexts/execution/orchestration-benchmark-gate.md`.
|
|
10
14
|
*
|
|
11
|
-
* This helper decides; it never runs the
|
|
12
|
-
*
|
|
15
|
+
* This helper decides; it never runs the measurement. The signal is realized
|
|
16
|
+
* orchestration telemetry, aggregated + evaluated out of band.
|
|
13
17
|
*/
|
|
14
18
|
|
|
15
19
|
export interface BenchmarkResult {
|