@event4u/agent-config 9.16.0 → 9.18.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 -1
- package/CHANGELOG.md +80 -130
- package/README.md +1 -1
- package/dist/agent-src/commands/agent-handoff.md +100 -48
- package/dist/agent-src/commands/challenge-me/vision.md +5 -0
- package/dist/agent-src/commands/commit.md +1 -1
- package/dist/agent-src/commands/condense.md +19 -64
- package/dist/agent-src/commands/evals/agent-handoff.json +13 -1
- package/dist/agent-src/commands/evals/rule-compliance-audit.json +46 -0
- package/dist/agent-src/commands/feature/plan.md +20 -0
- package/dist/agent-src/commands/feature/roadmap.md +19 -0
- package/dist/agent-src/commands/memory/promote.md +14 -1
- package/dist/agent-src/commands/mode.md +9 -5
- package/dist/agent-src/commands/optimize/deep.md +72 -11
- package/dist/agent-src/commands/pr/create.md +29 -0
- package/dist/agent-src/commands/roadmap/create.md +29 -0
- package/dist/agent-src/commands/rule-compliance-audit.md +28 -5
- package/dist/agent-src/contexts/authority/commit-mechanics.md +5 -5
- package/dist/agent-src/contexts/communication/rules-auto/guidelines-mechanics.md +1 -0
- package/dist/agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +1 -1
- package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +6 -1
- package/dist/agent-src/contexts/communication/rules-auto/token-efficiency-mechanics.md +4 -1
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +27 -1
- package/dist/agent-src/contexts/execution/plan-confidence-gate.md +133 -0
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +5 -2
- package/dist/agent-src/profiles/agency.yml +3 -3
- package/dist/agent-src/profiles/content_creator.yml +2 -2
- package/dist/agent-src/profiles/developer.yml +2 -2
- package/dist/agent-src/profiles/finance.yml +1 -1
- package/dist/agent-src/profiles/founder.yml +2 -2
- package/dist/agent-src/profiles/ops.yml +2 -2
- package/dist/agent-src/rules/active-remediation.md +2 -0
- package/dist/agent-src/rules/architecture.md +4 -2
- package/dist/agent-src/rules/augment-edit-discipline.md +2 -0
- package/dist/agent-src/rules/autonomous-execution.md +1 -1
- package/dist/agent-src/rules/brand-consistency.md +10 -62
- package/dist/agent-src/rules/brand-source-of-truth.md +62 -11
- package/dist/agent-src/rules/broken-access-control.md +4 -0
- package/dist/agent-src/rules/cli-output-handling.md +5 -0
- package/dist/agent-src/rules/code-comment-discipline.md +3 -0
- package/dist/agent-src/rules/commit-conventions.md +2 -0
- package/dist/agent-src/rules/context-hygiene.md +3 -2
- package/dist/agent-src/rules/cross-source-consistency.md +3 -0
- package/dist/agent-src/rules/design-fidelity.md +2 -0
- package/dist/agent-src/rules/doc-screenshot-hygiene.md +2 -0
- package/dist/agent-src/rules/docker-commands.md +4 -0
- package/dist/agent-src/rules/domain-adoption-policy.md +2 -0
- package/dist/agent-src/rules/domain-safety-disclaimer.md +5 -2
- package/dist/agent-src/rules/domain-safety-pii.md +1 -1
- package/dist/agent-src/rules/engineering-safety-floor.md +2 -0
- package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +9 -0
- package/dist/agent-src/rules/image-likeness-and-rights.md +4 -0
- package/dist/agent-src/rules/improve-before-implement.md +4 -0
- package/dist/agent-src/rules/laravel-routing.md +4 -0
- package/dist/agent-src/rules/legal-safety-floor.md +3 -0
- package/dist/agent-src/rules/lethal-trifecta-guard.md +3 -0
- package/dist/agent-src/rules/media-governance-routing.md +5 -0
- package/dist/agent-src/rules/minimal-safe-diff.md +2 -0
- package/dist/agent-src/rules/no-roadmap-references.md +2 -0
- package/dist/agent-src/rules/notes-first-reasoning.md +2 -0
- package/dist/agent-src/rules/output-discipline.md +9 -2
- package/dist/agent-src/rules/php-coding.md +2 -0
- package/dist/agent-src/rules/prefer-enums-over-literals.md +3 -0
- package/dist/agent-src/rules/provider-lifecycle-discipline.md +5 -0
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +2 -0
- package/dist/agent-src/rules/roadmap-progress-sync.md +2 -0
- package/dist/agent-src/rules/rule-type-governance.md +2 -0
- package/dist/agent-src/rules/scale-discipline.md +3 -0
- package/dist/agent-src/rules/secret-vcs-guard.md +2 -0
- package/dist/agent-src/rules/security-sensitive-stop.md +9 -2
- package/dist/agent-src/rules/senior-engineering-discipline.md +6 -0
- package/dist/agent-src/rules/skill-quality.md +2 -0
- package/dist/agent-src/rules/source-confidentiality.md +4 -0
- package/dist/agent-src/rules/source-discovery-gate.md +3 -0
- package/dist/agent-src/rules/source-of-truth.md +2 -0
- package/dist/agent-src/rules/strategy-safety-floor.md +2 -0
- package/dist/agent-src/rules/think-before-action.md +5 -0
- package/dist/agent-src/rules/token-budget-discipline.md +2 -2
- package/dist/agent-src/rules/ui-audit-gate.md +2 -0
- package/dist/agent-src/rules/user-interaction.md +3 -4
- package/dist/agent-src/skills/build-buy-partner/SKILL.md +1 -1
- package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +4 -4
- package/dist/agent-src/skills/copilot-config/SKILL.md +1 -1
- package/dist/agent-src/skills/deep-reading-analyst/SKILL.md +7 -4
- package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
- package/dist/agent-src/skills/design-intelligence/SKILL.md +6 -180
- package/dist/agent-src/skills/design-intelligence/references/context-and-registers.md +100 -0
- package/dist/agent-src/skills/design-intelligence/references/integration-mapping.md +91 -0
- package/dist/agent-src/skills/design-review/SKILL.md +4 -141
- package/dist/agent-src/skills/design-review/references/review-communication.md +92 -0
- package/dist/agent-src/skills/design-review/references/verification-automation.md +61 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +8 -27
- package/dist/agent-src/skills/existing-ui-audit/references/anti-slop-cross-reference.md +31 -0
- package/dist/agent-src/skills/fe-design/SKILL.md +4 -289
- package/dist/agent-src/skills/fe-design/references/design-patterns.md +227 -0
- package/dist/agent-src/skills/fe-design/references/design-read-and-memory.md +75 -0
- package/dist/agent-src/skills/market-entry-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/persona-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/readme-reviewer/SKILL.md +2 -1
- package/dist/agent-src/skills/roadmap-management/SKILL.md +10 -0
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +12 -1
- package/dist/agent-src/skills/rule-writing/SKILL.md +4 -2
- package/dist/agent-src/skills/skill-reviewer/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-writing/SKILL.md +2 -2
- package/dist/agent-src/skills/tailwind-engineer/SKILL.md +3 -1
- package/dist/agent-src/skills/token-optimizer/SKILL.md +2 -2
- package/dist/agent-src/skills/ui-component-architect/SKILL.md +6 -3
- package/dist/agent-src/templates/agent-settings.md +13 -15
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +6 -2
- package/dist/agent-src/templates/persona.md +2 -2
- package/dist/agent-src/templates/roadmaps.md +13 -1
- package/dist/agent-src/templates/rule.md +1 -1
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/_fix_lane.ts +52 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +8 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +6 -0
- package/dist/agent-src/templates/scripts/work_engine/intent/classify.ts +56 -4
- package/dist/agent-src/templates/skill.md +1 -1
- package/dist/cli/registry.js +3 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-AIIUU73N.js +2040 -0
- package/dist/cli-delegate/{chunk-ZXXJLL5K.js → chunk-BSLUHV2F.js} +127 -1487
- package/dist/cli-delegate/{chunk-H574KOUH.js → chunk-ELMFOQPW.js} +35 -1
- package/dist/cli-delegate/chunk-LF2KKJ4Q.js +183 -0
- package/dist/cli-delegate/chunk-VSYT7OHO.js +1382 -0
- package/dist/cli-delegate/chunk-XGA2NTU4.js +3727 -0
- package/dist/cli-delegate/cmd_conformance.js +4 -3
- package/dist/cli-delegate/cmd_converge.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +3 -2
- package/dist/cli-delegate/cmd_explain.js +36 -36
- package/dist/cli-delegate/cmd_export.js +4 -4
- package/dist/cli-delegate/cmd_handoff.js +1169 -0
- package/dist/cli-delegate/cmd_memory_get.js +35 -3754
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_prune.js +4 -4
- package/dist/cli-delegate/cmd_route_audit.js +249 -0
- package/dist/cli-delegate/cmd_route_explain.js +285 -0
- package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
- package/dist/cli-delegate/cmd_sync.js +4 -4
- package/dist/cli-delegate/cmd_uninstall.js +4 -4
- package/dist/cli-delegate/cmd_update.js +3 -3
- package/dist/cli-delegate/cmd_upgrade.js +3 -3
- package/dist/cli-delegate/cmd_validate.js +4 -4
- package/dist/cli-delegate/cmd_versions.js +3 -3
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +84 -84
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +2 -2
- package/dist/discovery/trust-report.md +1 -1
- package/dist/discovery/workspaces.json +2 -2
- package/dist/hooks/dispatch.js +602 -507
- package/dist/install/install.mjs +34 -0
- package/dist/mcp/awesome-mcp-servers.row.md +1 -1
- package/dist/mcp/mcp-cloudflare-catalogue.json +2 -2
- package/dist/mcp/registry-manifest.json +4 -4
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +25 -3
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_src.js +39 -6
- package/dist/scripts/_lib/agent_src.js.map +1 -1
- package/dist/server/schemas/settings.js +25 -0
- package/dist/server/schemas/settings.js.map +1 -1
- package/docs/guidelines/abstraction-thresholds.md +53 -0
- package/docs/guidelines/agent-infra/agent-interaction-and-decision-quality.md +1 -1
- package/docs/guidelines/agent-infra/asking-and-brevity-examples.md +7 -0
- package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +2 -2
- package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +5 -3
- package/docs/guidelines/agent-infra/size-and-scope.md +8 -2
- package/docs/guidelines/component-oriented-and-oop-development.md +11 -6
- package/docs/guidelines/docs/readme-size-and-splitting.md +5 -2
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/src/agent-src/templates/scripts/work_engine/directives/ui/_fix_lane.ts +52 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +8 -0
- package/src/agent-src/templates/scripts/work_engine/directives/ui/design.ts +6 -0
- package/src/agent-src/templates/scripts/work_engine/intent/classify.ts +56 -4
- package/src/config/agent-settings.template.yml +68 -0
- package/src/config/evaluator-budgets.json +8 -11
- package/src/config/gate-coverage.yml +70 -0
- package/src/scripts/_cli/cmd_explain.ts +41 -36
- package/src/scripts/_cli/cmd_handoff.ts +405 -0
- package/src/scripts/_cli/cmd_route_audit.ts +290 -0
- package/src/scripts/_cli/cmd_route_explain.ts +269 -0
- package/src/scripts/_cli/handoff_generate.ts +453 -0
- package/src/scripts/_cli/handoff_sessions.ts +435 -0
- package/src/scripts/_dispatch.bash +32 -0
- package/src/scripts/_lib/agent_src.ts +36 -6
- package/src/scripts/_lib/git_env.ts +40 -0
- package/src/scripts/_lib/md_table.ts +27 -0
- package/src/scripts/_lib/planning_settings.ts +43 -0
- package/src/scripts/_lib/release_material.ts +156 -0
- package/src/scripts/_lib/router_match.ts +301 -0
- package/src/scripts/annotate_r1_outcomes.ts +258 -0
- package/src/scripts/check_completion_review.ts +1140 -0
- package/src/scripts/check_condensation.ts +2 -1
- package/src/scripts/check_finding_dispositions.ts +278 -0
- package/src/scripts/check_pack_size.ts +4 -3
- package/src/scripts/check_references.ts +1 -0
- package/src/scripts/check_release_highlights.ts +300 -0
- package/src/scripts/check_release_pr_shape.ts +4 -0
- package/src/scripts/check_release_surface_equality.ts +132 -0
- package/src/scripts/check_reply_consistency.ts +187 -138
- package/src/scripts/compile_router.ts +20 -3
- package/src/scripts/dispatch_r2_reviewer.ts +968 -0
- package/src/scripts/eval_ui_triviality.ts +156 -0
- package/src/scripts/handoff_context_hook.ts +148 -0
- package/src/scripts/hook_manifest.yaml +17 -7
- package/src/scripts/hooks/concern_registry.ts +2 -0
- package/src/scripts/lint_abstraction_thresholds.ts +327 -0
- package/src/scripts/lint_framework_leakage_allowlist.json +2 -2
- package/src/scripts/lint_plan_risk_register.ts +931 -0
- package/src/scripts/lint_profile_personas.ts +153 -0
- package/src/scripts/lint_token_budget_discipline.ts +148 -0
- package/src/scripts/lint_trigger_collisions.ts +257 -0
- package/src/scripts/release.ts +156 -32
- package/src/scripts/release_drill.ts +491 -0
- package/src/scripts/router_telemetry.ts +16 -290
- package/src/scripts/schemas/command.schema.json +33 -0
- package/src/scripts/schemas/rule.schema.json +10 -0
- package/src/scripts/self_review_gate.ts +41 -3
- package/src/scripts/skill_linter.ts +3 -1
- package/src/scripts/smoke/router.sh +1 -1
- package/src/scripts/update_counts.ts +60 -12
- package/src/server/schemas/settings.ts +41 -0
- package/dist/cli-delegate/{chunk-XX6TOPD7.js → chunk-WR6GTRHJ.js} +3 -3
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* Gate R1 outcome annotation helper (quarterly cadence — see
|
|
4
|
+
* docs/contracts/plan-review-gates.md § 7).
|
|
5
|
+
*
|
|
6
|
+
* Walks the `## Risk Register` sections of ARCHIVED roadmaps
|
|
7
|
+
* (agents/roadmaps/archive/*.md), and for every register row that has no
|
|
8
|
+
* recorded outcome yet, prompts the operator:
|
|
9
|
+
*
|
|
10
|
+
* helped — the mitigation prevented the risk (or materially reduced it)
|
|
11
|
+
* fired — the risk fired despite (or without) the mitigation
|
|
12
|
+
* unknown — cannot be judged (yet)
|
|
13
|
+
*
|
|
14
|
+
* Each answer appends one `r1_mitigation_outcome` event to the tracked
|
|
15
|
+
* metrics JSONL (agents/evidence/metrics/gate-metrics.jsonl) — ids +
|
|
16
|
+
* counters only, PII-free by construction. Already-annotated rows
|
|
17
|
+
* (same file + rank in the JSONL) are skipped, so re-runs are idempotent.
|
|
18
|
+
*
|
|
19
|
+
* Not a gate: no `scanned:` line, no gate-coverage entry. Exit 0 on
|
|
20
|
+
* completion (including nothing-to-annotate), 2 on internal error.
|
|
21
|
+
*
|
|
22
|
+
* Usage:
|
|
23
|
+
* ./scripts-run src/scripts/annotate_r1_outcomes # interactive
|
|
24
|
+
* ./scripts-run src/scripts/annotate_r1_outcomes --list # show pending only
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
import * as fs from 'node:fs';
|
|
28
|
+
import * as path from 'node:path';
|
|
29
|
+
import * as readline from 'node:readline';
|
|
30
|
+
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
31
|
+
|
|
32
|
+
import { splitMarkdownRow } from './_lib/md_table.js';
|
|
33
|
+
|
|
34
|
+
const ARCHIVE_DIR = 'agents/roadmaps/archive';
|
|
35
|
+
const METRICS_FILE = 'agents/evidence/metrics/gate-metrics.jsonl';
|
|
36
|
+
const OUTCOMES = new Set(['helped', 'fired', 'unknown']);
|
|
37
|
+
|
|
38
|
+
interface RegisterRow {
|
|
39
|
+
file: string;
|
|
40
|
+
rank: number;
|
|
41
|
+
item: string;
|
|
42
|
+
mitigation: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** § 1.2 register columns: Rank | Item | Risk type | Description | Mitigation | Anchored under. */
|
|
46
|
+
const REGISTER_CELLS = 6;
|
|
47
|
+
const ITEM_CELL = 1;
|
|
48
|
+
const MITIGATION_CELL = 4;
|
|
49
|
+
|
|
50
|
+
export function extractRegisterRows(file: string, content: string): RegisterRow[] {
|
|
51
|
+
const rows: RegisterRow[] = [];
|
|
52
|
+
const lines = content.split(/\r?\n/);
|
|
53
|
+
let inRegister = false;
|
|
54
|
+
for (const line of lines) {
|
|
55
|
+
if (/^##\s+Risk Register\s*$/.test(line)) {
|
|
56
|
+
inRegister = true;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (inRegister && /^##\s+/.test(line)) break;
|
|
60
|
+
if (!inRegister) continue;
|
|
61
|
+
if (!line.trim().startsWith('|')) continue;
|
|
62
|
+
// Escape-aware split, shared with both validators: a per-column
|
|
63
|
+
// `[^|]*` regex mis-aligns on a `\|` inside a cell — the shape the
|
|
64
|
+
// contract's own §1.2 example uses (`product \| implementation`) —
|
|
65
|
+
// and then records the Description as the mitigation.
|
|
66
|
+
const cells = splitMarkdownRow(line);
|
|
67
|
+
if (cells.length < REGISTER_CELLS) continue;
|
|
68
|
+
const rank = cells[0] ?? '';
|
|
69
|
+
if (!/^\d+$/.test(rank)) continue; // header / separator / prose row
|
|
70
|
+
rows.push({
|
|
71
|
+
file,
|
|
72
|
+
rank: Number(rank),
|
|
73
|
+
item: (cells[ITEM_CELL] ?? '').trim(),
|
|
74
|
+
mitigation: (cells[MITIGATION_CELL] ?? '').trim(),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
return rows;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function annotatedKeys(metricsText: string): Set<string> {
|
|
81
|
+
const keys = new Set<string>();
|
|
82
|
+
for (const line of metricsText.split('\n')) {
|
|
83
|
+
if (line.trim() === '') continue;
|
|
84
|
+
try {
|
|
85
|
+
const ev = JSON.parse(line) as { event?: string; file?: string; rank?: number };
|
|
86
|
+
if (ev.event === 'r1_mitigation_outcome' && ev.file !== undefined && ev.rank !== undefined) {
|
|
87
|
+
keys.add(`${ev.file}#${String(ev.rank)}`);
|
|
88
|
+
}
|
|
89
|
+
} catch {
|
|
90
|
+
// tolerate foreign lines — the JSONL is append-only and shared
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return keys;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Ask one question. Resolves `null` on EOF instead of hanging or throwing:
|
|
98
|
+
* `rl.question`'s callback never fires once the stream ends, so a piped or
|
|
99
|
+
* scheduled invocation would otherwise block forever — and an interface that is
|
|
100
|
+
* ALREADY closed (the input ran out between two prompts) throws
|
|
101
|
+
* `ERR_USE_AFTER_CLOSE` from `question`, which is the same end-of-input state
|
|
102
|
+
* and must end the pass just as cleanly.
|
|
103
|
+
*/
|
|
104
|
+
function ask(rl: readline.Interface, q: string): Promise<string | null> {
|
|
105
|
+
return new Promise((resolve) => {
|
|
106
|
+
if ((rl as { closed?: boolean }).closed === true) {
|
|
107
|
+
resolve(null);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
let settled = false;
|
|
111
|
+
const onClose = (): void => {
|
|
112
|
+
if (!settled) {
|
|
113
|
+
settled = true;
|
|
114
|
+
resolve(null);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
rl.once('close', onClose);
|
|
118
|
+
try {
|
|
119
|
+
rl.question(q, (answer) => {
|
|
120
|
+
settled = true;
|
|
121
|
+
rl.removeListener('close', onClose);
|
|
122
|
+
resolve(answer);
|
|
123
|
+
});
|
|
124
|
+
} catch {
|
|
125
|
+
rl.removeListener('close', onClose);
|
|
126
|
+
if (!settled) {
|
|
127
|
+
settled = true;
|
|
128
|
+
resolve(null);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface AnnotateIo {
|
|
135
|
+
/**
|
|
136
|
+
* readline input; defaults to `process.stdin`.
|
|
137
|
+
*
|
|
138
|
+
* Injected by the tests to drive the EOF path deterministically — a
|
|
139
|
+
* caller-supplied stream is a deliberate non-TTY answer channel, so the
|
|
140
|
+
* TTY refusal below applies to `process.stdin` only.
|
|
141
|
+
*/
|
|
142
|
+
input?: NodeJS.ReadableStream;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export async function main(argv?: readonly string[], io: AnnotateIo = {}): Promise<number> {
|
|
146
|
+
const args = argv ?? process.argv.slice(2);
|
|
147
|
+
const listOnly = args.includes('--list');
|
|
148
|
+
|
|
149
|
+
if (!fs.existsSync(ARCHIVE_DIR)) {
|
|
150
|
+
process.stdout.write(`No archive directory at ${ARCHIVE_DIR} — nothing to annotate.\n`);
|
|
151
|
+
return 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const files = fs
|
|
155
|
+
.readdirSync(ARCHIVE_DIR)
|
|
156
|
+
.filter((f) => f.endsWith('.md'))
|
|
157
|
+
.map((f) => path.join(ARCHIVE_DIR, f));
|
|
158
|
+
|
|
159
|
+
const metricsText = fs.existsSync(METRICS_FILE) ? fs.readFileSync(METRICS_FILE, 'utf8') : '';
|
|
160
|
+
const done = annotatedKeys(metricsText);
|
|
161
|
+
|
|
162
|
+
const pending: RegisterRow[] = [];
|
|
163
|
+
for (const f of files) {
|
|
164
|
+
const rows = extractRegisterRows(f, fs.readFileSync(f, 'utf8'));
|
|
165
|
+
for (const r of rows) {
|
|
166
|
+
if (!done.has(`${r.file}#${String(r.rank)}`)) pending.push(r);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (pending.length === 0) {
|
|
171
|
+
process.stdout.write('✅ No un-annotated Risk-Register rows in archived roadmaps.\n');
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
process.stdout.write(`${String(pending.length)} un-annotated mitigation(s) in archived roadmaps:\n`);
|
|
176
|
+
if (listOnly) {
|
|
177
|
+
for (const r of pending) {
|
|
178
|
+
process.stdout.write(` ${r.file} #${String(r.rank)} — ${r.item}\n`);
|
|
179
|
+
}
|
|
180
|
+
return 0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Interactive-only by construction: the annotation pass is a human quarterly
|
|
184
|
+
// cadence, so a non-TTY invocation is refused up front with the read-only
|
|
185
|
+
// alternative rather than left to block on a prompt nobody can answer.
|
|
186
|
+
if (io.input === undefined && process.stdin.isTTY !== true) {
|
|
187
|
+
process.stderr.write(
|
|
188
|
+
'❌ annotate_r1_outcomes needs an interactive terminal (stdin is not a TTY).\n' +
|
|
189
|
+
' Use --list for the read-only pending inventory.\n',
|
|
190
|
+
);
|
|
191
|
+
return 2;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const rl = readline.createInterface({ input: io.input ?? process.stdin, output: process.stdout });
|
|
195
|
+
try {
|
|
196
|
+
for (const r of pending) {
|
|
197
|
+
process.stdout.write(`\n${r.file} #${String(r.rank)}\n risk: ${r.item}\n mitigation: ${r.mitigation}\n`);
|
|
198
|
+
let answer = '';
|
|
199
|
+
let eof = false;
|
|
200
|
+
while (!OUTCOMES.has(answer)) {
|
|
201
|
+
const raw = await ask(rl, ' outcome [helped/fired/unknown, s=skip]: ');
|
|
202
|
+
if (raw === null) {
|
|
203
|
+
eof = true;
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
answer = raw.trim().toLowerCase();
|
|
207
|
+
if (answer === 's' || answer === 'skip') break;
|
|
208
|
+
}
|
|
209
|
+
if (eof) {
|
|
210
|
+
process.stdout.write('\n⚠️ stdin closed — ending the annotation pass early.\n');
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
if (!OUTCOMES.has(answer)) continue;
|
|
214
|
+
const event = {
|
|
215
|
+
event: 'r1_mitigation_outcome',
|
|
216
|
+
date: new Date().toISOString().slice(0, 10),
|
|
217
|
+
file: r.file,
|
|
218
|
+
rank: r.rank,
|
|
219
|
+
outcome: answer,
|
|
220
|
+
};
|
|
221
|
+
// The metrics dir need not exist yet (a repo whose first recorded
|
|
222
|
+
// event is this one). Creating it here rather than letting
|
|
223
|
+
// `appendFileSync` throw matters because the throw would land AFTER
|
|
224
|
+
// the operator answered — an ENOENT crash that discards answers a
|
|
225
|
+
// human just typed. `recursive: true` is a no-op once it exists.
|
|
226
|
+
fs.mkdirSync(path.dirname(METRICS_FILE), { recursive: true });
|
|
227
|
+
fs.appendFileSync(METRICS_FILE, `${JSON.stringify(event)}\n`);
|
|
228
|
+
}
|
|
229
|
+
} finally {
|
|
230
|
+
rl.close();
|
|
231
|
+
}
|
|
232
|
+
process.stdout.write('\n✅ Annotation pass complete.\n');
|
|
233
|
+
return 0;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const _HERE = fileURLToPath(import.meta.url);
|
|
237
|
+
function _isCliEntry(): boolean {
|
|
238
|
+
if (process.argv[1] === undefined) return false;
|
|
239
|
+
const argvUrl = pathToFileURL(path.resolve(process.argv[1])).href;
|
|
240
|
+
if (import.meta.url === argvUrl) return true;
|
|
241
|
+
try {
|
|
242
|
+
const here = fs.realpathSync(fileURLToPath(import.meta.url));
|
|
243
|
+
const argv1 = fs.realpathSync(path.resolve(process.argv[1]));
|
|
244
|
+
return here === argv1;
|
|
245
|
+
} catch {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
if (_isCliEntry() || process.argv[1] === _HERE) {
|
|
251
|
+
main()
|
|
252
|
+
.then((code) => process.exit(code))
|
|
253
|
+
.catch((exc: unknown) => {
|
|
254
|
+
const msg = exc instanceof Error ? exc.message : String(exc);
|
|
255
|
+
process.stderr.write(`❌ Internal error: ${msg}\n`);
|
|
256
|
+
process.exit(2);
|
|
257
|
+
});
|
|
258
|
+
}
|