@event4u/agent-config 16.0.0 → 16.1.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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +297 -137
- package/CONTRIBUTING.md +9 -0
- package/README.md +2 -2
- package/dist/agent-src/commands/analyze/inbox.md +26 -0
- package/dist/agent-src/commands/analyze/roadmap-repos.md +27 -0
- package/dist/agent-src/commands/challenge-me/closure.md +178 -0
- package/dist/agent-src/commands/challenge-me.md +9 -2
- package/dist/agent-src/commands/council/default.md +25 -5
- package/dist/agent-src/commands/feature/plan.md +28 -1
- package/dist/agent-src/commands/feature/roadmap.md +28 -1
- package/dist/agent-src/commands/implement-ticket.md +27 -0
- package/dist/agent-src/commands/jira-ticket.md +27 -0
- package/dist/agent-src/commands/pr/create.md +29 -0
- package/dist/agent-src/commands/pr/merge.md +60 -9
- package/dist/agent-src/commands/roadmap/ai-council.md +7 -1
- package/dist/agent-src/commands/roadmap/create.md +74 -27
- package/dist/agent-src/commands/roadmap/materialize.md +27 -0
- package/dist/agent-src/commands/roadmap/process-full.md +123 -18
- package/dist/agent-src/commands/team.md +22 -0
- package/dist/agent-src/contexts/authority/scope-growth-ownership.md +80 -0
- package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +47 -0
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +44 -3
- package/dist/agent-src/contexts/execution/autonomy-mechanics.md +15 -15
- package/dist/agent-src/contexts/execution/decision-closure-execution.md +93 -0
- package/dist/agent-src/contexts/execution/fix-loop-ladder.md +108 -0
- package/dist/agent-src/contexts/execution/plan-confidence-gate.md +4 -2
- package/dist/agent-src/contexts/execution/roadmap-process-loop.md +75 -6
- package/dist/agent-src/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
- package/dist/agent-src/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
- package/dist/agent-src/guidelines/design-fidelity-routing.md +29 -0
- package/dist/agent-src/rules/autonomous-execution.md +15 -8
- package/dist/agent-src/rules/delegation-policy.md +23 -45
- package/dist/agent-src/rules/design-fidelity.md +32 -37
- package/dist/agent-src/rules/evaluator-independence.md +43 -49
- package/dist/agent-src/rules/test-first.md +41 -0
- package/dist/agent-src/skills/accessibility-auditor/data/manifest.json +3 -3
- package/dist/agent-src/skills/ai-council/SKILL.md +11 -3
- package/dist/agent-src/skills/api-design/data/manifest.json +3 -3
- package/dist/agent-src/skills/database/data/manifest.json +4 -4
- package/dist/agent-src/skills/database/data/query-tuning.csv +3 -3
- package/dist/agent-src/skills/design-review/SKILL.md +50 -0
- package/dist/agent-src/skills/existing-ui-audit/SKILL.md +14 -4
- package/dist/agent-src/skills/experiment-loop/SKILL.md +31 -1
- package/dist/agent-src/skills/roadmap-writing/SKILL.md +1 -1
- package/dist/agent-src/skills/storybook-workshop/SKILL.md +42 -3
- package/dist/agent-src/skills/threat-modeling/SKILL.md +9 -4
- package/dist/agent-src/skills/threat-modeling/data/manifest.json +4 -4
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +37 -3
- package/dist/agent-src/templates/agent-settings.md +1 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +188 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
- package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -0
- package/dist/cli-delegate/check_update_banner.js +40 -2
- package/dist/cli-delegate/chunk-4E2W63DA.js +335 -0
- package/dist/cli-delegate/chunk-5R7HOLAF.js +99 -0
- package/dist/cli-delegate/{chunk-IVBPRCQO.js → chunk-6KFEC3G7.js} +1 -1
- package/dist/cli-delegate/{chunk-2TAQ2K4V.js → chunk-6KM6ORRY.js} +55 -386
- package/dist/cli-delegate/{chunk-2XY7ILBT.js → chunk-FC75PGJE.js} +42 -2
- package/dist/cli-delegate/{chunk-GYC3VRYN.js → chunk-FXYUYU4N.js} +57 -13
- package/dist/cli-delegate/{chunk-55ACLDUE.js → chunk-GJCBB2UG.js} +168 -10
- package/dist/cli-delegate/{chunk-AK6HODNQ.js → chunk-HDVVGPQW.js} +873 -539
- package/dist/cli-delegate/{chunk-H32DGUJH.js → chunk-P6ZHP5W2.js} +1 -1
- package/dist/cli-delegate/{chunk-57PN4GYJ.js → chunk-RGNIWTEA.js} +1 -1
- package/dist/cli-delegate/chunk-ROYYTEZU.js +39 -0
- package/dist/cli-delegate/{chunk-3FKR64R5.js → chunk-UNCRJBT3.js} +31 -7
- package/dist/cli-delegate/{chunk-2DK2VJWG.js → chunk-WGXTVKCQ.js} +20 -6
- package/dist/cli-delegate/chunk-YDPILCOL.js +152 -0
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +1 -1
- package/dist/cli-delegate/cmd_conformance.js +90 -56
- package/dist/cli-delegate/cmd_doctor.js +7 -5
- package/dist/cli-delegate/cmd_explain.js +2 -2
- package/dist/cli-delegate/cmd_export.js +9 -7
- package/dist/cli-delegate/cmd_fleet.js +4 -2
- package/dist/cli-delegate/cmd_handoff.js +4 -4
- package/dist/cli-delegate/cmd_mcp_available.js +1 -1
- package/dist/cli-delegate/cmd_migrate.js +2 -2
- package/dist/cli-delegate/cmd_packs_active.js +2 -2
- package/dist/cli-delegate/cmd_preflight.js +4 -2
- package/dist/cli-delegate/cmd_prune.js +10 -8
- package/dist/cli-delegate/cmd_route_audit.js +2 -2
- package/dist/cli-delegate/cmd_route_explain.js +1 -1
- package/dist/cli-delegate/cmd_session_recycle.js +2 -2
- package/dist/cli-delegate/cmd_settings_get.js +28 -2
- package/dist/cli-delegate/cmd_settings_migrate.js +9 -7
- package/dist/cli-delegate/cmd_settings_set.js +1 -1
- package/dist/cli-delegate/cmd_sync.js +10 -8
- package/dist/cli-delegate/cmd_uninstall.js +16 -13
- package/dist/cli-delegate/cmd_update.js +1 -1
- package/dist/cli-delegate/cmd_upgrade.js +1 -1
- package/dist/cli-delegate/cmd_validate.js +12 -10
- package/dist/cli-delegate/cmd_versions.js +1 -1
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +85 -38
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -4
- package/dist/discovery/dormancy-report.md +1 -1
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +10 -8
- package/dist/discovery/trust-report.md +3 -3
- package/dist/discovery/workspaces.json +8 -6
- package/dist/hooks/dispatch.js +1832 -1007
- package/dist/install/claudeRuleRewrite.js +14 -3
- package/dist/install/conflict.js +60 -10
- package/dist/install/conflictTracker.js +218 -0
- package/dist/install/fsPrimitives.js +54 -0
- package/dist/install/install.mjs +2007 -1481
- package/dist/install/manifestFiles.js +259 -0
- package/dist/install/preflight.js +14 -2
- package/dist/install/preserve.js +157 -0
- package/dist/install/recordedOwnership.js +132 -0
- package/dist/install/txlog.js +11 -2
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +398 -39
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +3 -2
- package/dist/scripts/_lib/fs_atomic.js +167 -0
- package/dist/scripts/_lib/installed_tools.js +460 -0
- package/dist/scripts/_lib/lean_projection_mode.js +3 -2
- package/dist/scripts/_lib/settings_renamed_keys.js +78 -0
- package/dist/server/routes/install.js +8 -0
- package/dist/server/routes/wizard.js +9 -3
- package/dist/server/schemas/settings.js +17 -5
- package/dist/shared/missionExecution.js +97 -0
- package/dist/ui/assets/{index-D0jaCRPM.js → index-DH1xc62v.js} +17 -17
- package/dist/ui/index.html +1 -1
- package/docs/MIGRATION.md +103 -0
- package/docs/contracts/settings-classes.md +26 -7
- package/docs/guidelines/agent-infra/active-remediation-mechanics.md +57 -0
- package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +102 -0
- package/docs/guidelines/design-fidelity-routing.md +29 -0
- package/package.json +1 -1
- package/src/agent-src/templates/scripts/work_engine/directives/backend/_self_fix.ts +62 -2
- package/src/agent-src/templates/scripts/work_engine/directives/backend/test.ts +1 -0
- package/src/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +1 -0
- package/src/config/agent-settings.template.yml +139 -27
- package/src/config/auto-rule-budget.json +16 -0
- package/src/config/ci-local-parity.yml +18 -5
- package/src/config/continuity-surface.json +21 -0
- package/src/config/gate-coverage.yml +146 -13
- package/src/config/gate-violation-baselines.json +6 -6
- package/src/config/hook-token-budget.json +2 -0
- package/src/config/loop-surfaces.yaml +215 -0
- package/src/config/platform-anchor.json +3 -2
- package/src/config/release-gate-locality.yml +11 -0
- package/src/config/routing-coverage-seed.json +18 -4
- package/src/config/rule-enforcement-baseline.json +0 -1
- package/src/install/claudeRuleRewrite.ts +16 -2
- package/src/install/conflict.ts +65 -9
- package/src/install/conflictTracker.ts +299 -0
- package/src/install/fsPrimitives.ts +54 -0
- package/src/install/manifestFiles.ts +312 -0
- package/src/install/preflight.ts +16 -2
- package/src/install/preserve.ts +205 -0
- package/src/install/recordedOwnership.ts +149 -0
- package/src/install/txlog.ts +11 -2
- package/src/install/types.ts +19 -4
- package/src/scripts/_cli/cmd_conformance.ts +88 -15
- package/src/scripts/_cli/cmd_doctor.ts +4 -3
- package/src/scripts/_cli/cmd_route_explain.ts +9 -2
- package/src/scripts/_cli/cmd_settings_get.ts +44 -0
- package/src/scripts/_cli/doctor_execution.ts +90 -0
- package/src/scripts/_lib/activation_payload.ts +247 -0
- package/src/scripts/_lib/agent_settings.ts +4 -2
- package/src/scripts/_lib/authority_path.ts +102 -0
- package/src/scripts/_lib/cascade_base.ts +94 -0
- package/src/scripts/_lib/changelog_eras.ts +7 -2
- package/src/scripts/_lib/continuation_ladder.ts +149 -2
- package/src/scripts/_lib/council_transport.ts +129 -0
- package/src/scripts/_lib/delivery_ready.ts +112 -0
- package/src/scripts/_lib/forge_protection.ts +267 -0
- package/src/scripts/_lib/hook_platform_keys.ts +27 -0
- package/src/scripts/_lib/json_python_parity.ts +127 -0
- package/src/scripts/_lib/lean_projection_mode.ts +14 -3
- package/src/scripts/_lib/loop_surfaces.ts +382 -0
- package/src/scripts/_lib/mission_record.ts +190 -0
- package/src/scripts/_lib/obligation_frequency.ts +217 -0
- package/src/scripts/_lib/obligations.ts +402 -0
- package/src/scripts/_lib/orchestration_record.ts +11 -20
- package/src/scripts/_lib/release_highlights.ts +199 -10
- package/src/scripts/_lib/release_holds.ts +493 -0
- package/src/scripts/_lib/release_migration_gate.ts +184 -0
- package/src/scripts/_lib/rides_along.ts +102 -0
- package/src/scripts/_lib/settings_renamed_keys.ts +82 -0
- package/src/scripts/_lib/test_delta.ts +166 -0
- package/src/scripts/_lib/test_provenance.ts +171 -0
- package/src/scripts/_lib/typed_op_grant.ts +246 -0
- package/src/scripts/_lib/typed_op_watch.ts +185 -0
- package/src/scripts/ai_council/config.ts +8 -11
- package/src/scripts/ai_council/fallback_config.ts +5 -3
- package/src/scripts/ai_council/ownership_classes.ts +118 -0
- package/src/scripts/ask_block_census.ts +285 -15
- package/src/scripts/check_enforcement_matrix.ts +624 -0
- package/src/scripts/check_gate_reachability.ts +173 -10
- package/src/scripts/check_generator_sync.ts +954 -0
- package/src/scripts/check_preamble_payload_budget.ts +75 -2
- package/src/scripts/check_release_highlights.ts +33 -1
- package/src/scripts/check_release_holds.ts +567 -0
- package/src/scripts/check_rule_projection_integrity.ts +22 -12
- package/src/scripts/check_test_delta.ts +294 -0
- package/src/scripts/check_test_weakening.ts +299 -0
- package/src/scripts/closure_scan.ts +333 -0
- package/src/scripts/compile_hook_manifest.ts +43 -3
- package/src/scripts/council_record_shape.ts +209 -0
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +88 -9
- package/src/scripts/hooks/concern_registry.ts +4 -0
- package/src/scripts/hooks/design_pass_hook.ts +128 -3
- package/src/scripts/hooks/evidence_independence.ts +96 -0
- package/src/scripts/hooks/memory_recall_hook.ts +540 -0
- package/src/scripts/hooks/obligation_settle_hook.ts +182 -0
- package/src/scripts/hooks/rule_inject_hook.ts +49 -1
- package/src/scripts/hooks/run_continuation_hook.ts +17 -20
- package/src/scripts/hooks_doctor.ts +85 -0
- package/src/scripts/hooks_status.ts +19 -0
- package/src/scripts/install.ts +106 -206
- package/src/scripts/janitor.ts +7 -0
- package/src/scripts/lint_decision_classes.ts +464 -0
- package/src/scripts/lint_hook_manifest.ts +11 -0
- package/src/scripts/lint_major_migration_sections.ts +450 -0
- package/src/scripts/lint_plan_risk_register.ts +47 -3
- package/src/scripts/lint_roadmap_blockers.ts +61 -0
- package/src/scripts/lint_roadmap_producers.ts +202 -0
- package/src/scripts/measure_rule_budget.ts +101 -5
- package/src/scripts/new_roadmap.ts +37 -0
- package/src/scripts/orchestration_record.ts +0 -5
- package/src/scripts/release.ts +14 -98
- package/src/scripts/release_drill.ts +267 -1
- package/src/scripts/release_publication.ts +51 -0
- package/src/scripts/report_enforcement_drift.ts +566 -0
- package/src/scripts/report_host_injection_effect.ts +3 -11
- package/src/scripts/report_standing_payload_by_host.ts +26 -152
- package/src/scripts/schemas/agent-settings.schema.json +23 -0
- package/src/scripts/schemas/command.schema.json +4 -0
- package/src/scripts/scope_growth.ts +219 -0
- package/src/scripts/trigger_eval_grandfather.json +0 -1
- package/src/scripts/ui_conformance_probe.ts +622 -0
- package/src/server/schemas/settings.ts +31 -7
- package/src/shared/missionExecution.ts +126 -0
- package/dist/cli-delegate/chunk-523HCFYO.js +0 -90
|
@@ -15,16 +15,23 @@
|
|
|
15
15
|
* A **region** is one contiguous stretch of an authored file. Every region
|
|
16
16
|
* falls into exactly one of four classes, decided in this precedence order:
|
|
17
17
|
*
|
|
18
|
-
* 1. `
|
|
18
|
+
* 1. `bypass` — a line recording an EXPLICIT user bypass of a gate
|
|
19
|
+
* ("just write it", "skip closure", "einfach machen").
|
|
20
|
+
* Its own axis, and that is the whole point: a bypass is
|
|
21
|
+
* a decision the user took, and counting it as an absent
|
|
22
|
+
* closure would read as a surface that forgot to close
|
|
23
|
+
* rather than one the user told to stop. It is also never
|
|
24
|
+
* inferred — only an explicit phrasing matches.
|
|
25
|
+
* 2. `count-only` — a line that renders a NUMBER where a question belongs:
|
|
19
26
|
* it mentions `question(s)` and carries a `{count}`
|
|
20
27
|
* placeholder. This is the shape that prints how many
|
|
21
28
|
* decisions are outstanding instead of putting one.
|
|
22
|
-
*
|
|
29
|
+
* 3. `file-parked` — an `Open questions` SECTION heading whose body carries
|
|
23
30
|
* no ask obligation. The section is then a parking lot:
|
|
24
31
|
* a place a question is written down instead of asked.
|
|
25
|
-
*
|
|
32
|
+
* 4. `batch` — a run of non-blank lines carrying TWO OR MORE question
|
|
26
33
|
* lines: one hand-back, several decisions.
|
|
27
|
-
*
|
|
34
|
+
* 5. `single` — the same run carrying exactly one.
|
|
28
35
|
*
|
|
29
36
|
* A **question line** is a non-blank line that either ends in `?` (after
|
|
30
37
|
* trailing backticks, emphasis and whitespace are stripped) or is a list item
|
|
@@ -77,7 +84,7 @@ const _HERE = fileURLToPath(import.meta.url);
|
|
|
77
84
|
export const REPO_ROOT = path.resolve(path.dirname(_HERE), '..', '..');
|
|
78
85
|
|
|
79
86
|
/** The census classes, in precedence order. */
|
|
80
|
-
export const ASK_CLASSES = ['single', 'batch', 'count-only', 'file-parked'] as const;
|
|
87
|
+
export const ASK_CLASSES = ['single', 'batch', 'count-only', 'file-parked', 'bypass'] as const;
|
|
81
88
|
export type AskClass = (typeof ASK_CLASSES)[number];
|
|
82
89
|
|
|
83
90
|
/** Default scan roots. `src/domains` is narrowed to `command.md` — the ask surface. */
|
|
@@ -87,6 +94,16 @@ export const DEFAULT_ROOTS: readonly string[] = [
|
|
|
87
94
|
'src/agent-src/contexts',
|
|
88
95
|
];
|
|
89
96
|
|
|
97
|
+
/**
|
|
98
|
+
* An EXPLICIT user bypass of a gate. Every alternative is a phrasing the user
|
|
99
|
+
* types; none of them is a state the agent can infer. A mission grant, an
|
|
100
|
+
* autonomy setting and momentum are deliberately absent from this list — an
|
|
101
|
+
* inferred bypass is the failure this axis exists to make visible, not a
|
|
102
|
+
* second way to match.
|
|
103
|
+
*/
|
|
104
|
+
export const BYPASS_RE =
|
|
105
|
+
/\b(?:just write it|just do it|skip (?:the )?(?:closure|protocol|validation)|einfach machen|mach einfach|skip closure)\b/i;
|
|
106
|
+
|
|
90
107
|
/** A line printing a question COUNT where a question belongs. */
|
|
91
108
|
export const COUNT_ONLY_RE = /\bquestions?\b/i;
|
|
92
109
|
export const COUNT_PLACEHOLDER_RE = /\{count\}/;
|
|
@@ -124,10 +141,149 @@ export function isQuestionLine(line: string): boolean {
|
|
|
124
141
|
return line.replace(TRAILING_NOISE_RE, '').endsWith('?');
|
|
125
142
|
}
|
|
126
143
|
|
|
144
|
+
/**
|
|
145
|
+
* THE FOUR AXES
|
|
146
|
+
*
|
|
147
|
+
* The class above says what SHAPE an ask has. It does not say whether the ask
|
|
148
|
+
* should have existed, and that is the question the targets are about. Four
|
|
149
|
+
* axes, each decidable from the region and its file — never from intent:
|
|
150
|
+
*
|
|
151
|
+
* `phase` planning · execution · delivery. Read from the file's
|
|
152
|
+
* role, because "an owner ask in execution" and the same
|
|
153
|
+
* ask during planning are different defects: planning is
|
|
154
|
+
* where a decision is SUPPOSED to be closed.
|
|
155
|
+
* `ownership` which class the ask routes to, from the same mapping
|
|
156
|
+
* `closure_scan` uses. `unknown` when the region carries
|
|
157
|
+
* no signal — reported as unknown, never as technical.
|
|
158
|
+
* `avoidable` the ask is one the surface could have closed itself: a
|
|
159
|
+
* commit / push / CI / conflict ask, a continuation, a
|
|
160
|
+
* count, or a TECHNICAL question routed to the owner.
|
|
161
|
+
* `resolver_attempted` the region names a rung it tried before asking —
|
|
162
|
+
* evidence, convention, the agent, an independent
|
|
163
|
+
* session, the council, the team. An ask that names none
|
|
164
|
+
* went to the person first.
|
|
165
|
+
*
|
|
166
|
+
* All four are properties of an AUTHORED surface. The third target — zero
|
|
167
|
+
* repeats of an already-answered question — is a property of a TRANSCRIPT and
|
|
168
|
+
* is reported NOT MEASURED rather than as zero, on the same ground the
|
|
169
|
+
* native-ask rate is carried in rather than computed: a number this script
|
|
170
|
+
* cannot see must not be published as a number it measured.
|
|
171
|
+
*/
|
|
172
|
+
export const PHASES = ['planning', 'execution', 'delivery'] as const;
|
|
173
|
+
export type Phase = (typeof PHASES)[number];
|
|
174
|
+
|
|
175
|
+
/** Path fragments that put a file in a phase. First match wins, in order. */
|
|
176
|
+
const PHASE_MARKERS: ReadonlyArray<readonly [Phase, RegExp]> = [
|
|
177
|
+
['delivery', /(commit|\/pr\/|pull-request|release|push|merge)/],
|
|
178
|
+
[
|
|
179
|
+
'planning',
|
|
180
|
+
/(roadmap\/create|roadmap\/materialize|feature\/plan|feature\/roadmap|challenge-me|analyze\/|refine-ticket|estimate-ticket|plan-confidence)/,
|
|
181
|
+
],
|
|
182
|
+
['execution', /(process-full|process-phase|process-step|implement-ticket|work|roadmap-process-loop|jira-ticket)/],
|
|
183
|
+
];
|
|
184
|
+
|
|
185
|
+
/** Ask shapes the surface could have closed itself. */
|
|
186
|
+
export const AVOIDABLE_RE =
|
|
187
|
+
/\b(?:shall i (?:continue|go on|proceed)|weiter\?|should i commit|commit this|one commit or multiple|push (?:this|it)\?|re-?run ci|resolve the conflicts?\?|which branch|new pr\?)\b/i;
|
|
188
|
+
|
|
189
|
+
/** A rung named before the ask — the region tried something first. */
|
|
190
|
+
export const RESOLVER_RE =
|
|
191
|
+
/\b(?:evidence|convention|ADR-\d+|contract|independent session|the council|council:status|the team|ai_team)\b/i;
|
|
192
|
+
|
|
193
|
+
/** Ownership signals, the same mapping the closure detector uses. */
|
|
194
|
+
const OWNERSHIP_MARKERS: ReadonlyArray<readonly [string, RegExp]> = [
|
|
195
|
+
['destructive-owned', /\b(?:merge|force-push|deploy|publish|purchase|delete the branch)\b/i],
|
|
196
|
+
['product-owned', /\b(?:user-visible|what the user sees|product semantics|UX)\b/i],
|
|
197
|
+
['business-owned', /\b(?:deadline|budget|policy|pricing)\b/i],
|
|
198
|
+
['spend-exhaustion', /\b(?:ceiling|quota|spend)\b/i],
|
|
199
|
+
['critical-technical', /\b(?:security|auth|tenant|authority)\b/i],
|
|
200
|
+
['contested-technical', /\b(?:architecture|two valid|trade-?off|migration design)\b/i],
|
|
201
|
+
['reversible-technical', /\b(?:refactor|test organisation|pattern)\b/i],
|
|
202
|
+
['deterministic', /\b(?:naming|file placement|commit split)\b/i],
|
|
203
|
+
];
|
|
204
|
+
|
|
205
|
+
/** The three owner-routed classes — the ones an ask legitimately reaches. */
|
|
206
|
+
const OWNER_OWNED: ReadonlySet<string> = new Set([
|
|
207
|
+
'product-owned',
|
|
208
|
+
'business-owned',
|
|
209
|
+
'destructive-owned',
|
|
210
|
+
]);
|
|
211
|
+
|
|
212
|
+
export function phaseOf(file: string): Phase {
|
|
213
|
+
for (const [phase, re] of PHASE_MARKERS) {
|
|
214
|
+
if (re.test(file)) return phase;
|
|
215
|
+
}
|
|
216
|
+
return 'planning';
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export function ownershipOf(text: string): string {
|
|
220
|
+
for (const [cls, re] of OWNERSHIP_MARKERS) {
|
|
221
|
+
if (re.test(text)) return cls;
|
|
222
|
+
}
|
|
223
|
+
return 'unknown';
|
|
224
|
+
}
|
|
225
|
+
|
|
127
226
|
export interface Region {
|
|
128
227
|
readonly cls: AskClass;
|
|
129
228
|
readonly line: number;
|
|
130
229
|
readonly questions: number;
|
|
230
|
+
/** The region's own text, for the axis classifiers. */
|
|
231
|
+
readonly text: string;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** One region with its four axes resolved. */
|
|
235
|
+
export interface AxisRow {
|
|
236
|
+
readonly file: string;
|
|
237
|
+
readonly line: number;
|
|
238
|
+
readonly cls: AskClass;
|
|
239
|
+
readonly phase: Phase;
|
|
240
|
+
readonly ownership: string;
|
|
241
|
+
/** A commit / push / CI / conflict / continuation ask — target 2's subject. */
|
|
242
|
+
readonly workflow: boolean;
|
|
243
|
+
readonly avoidable: boolean;
|
|
244
|
+
readonly resolver_attempted: boolean;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function axesFor(file: string, region: Region): AxisRow {
|
|
248
|
+
const ownership = ownershipOf(region.text);
|
|
249
|
+
const technical = ownership !== 'unknown' && !OWNER_OWNED.has(ownership);
|
|
250
|
+
const phase = phaseOf(file);
|
|
251
|
+
const workflow = AVOIDABLE_RE.test(region.text);
|
|
252
|
+
return {
|
|
253
|
+
file,
|
|
254
|
+
line: region.line,
|
|
255
|
+
cls: region.cls,
|
|
256
|
+
phase,
|
|
257
|
+
ownership,
|
|
258
|
+
workflow,
|
|
259
|
+
// A technical question put to a person in EXECUTION is avoidable by
|
|
260
|
+
// construction: planning owned it, and the ownership ladder closes it
|
|
261
|
+
// without a person at all.
|
|
262
|
+
avoidable: workflow || (technical && phase === 'execution'),
|
|
263
|
+
resolver_attempted: RESOLVER_RE.test(region.text),
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** The three targets, and whether the corpus meets them. */
|
|
268
|
+
export interface Targets {
|
|
269
|
+
readonly technical_owner_asks_in_execution: number;
|
|
270
|
+
readonly workflow_asks: number;
|
|
271
|
+
/** Transcript-only. `null` is NOT MEASURED, never zero. */
|
|
272
|
+
readonly repeat_asks: number | null;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export function targets(rows: readonly AxisRow[]): Targets {
|
|
276
|
+
const asks = rows.filter((r) => r.cls === 'single' || r.cls === 'batch');
|
|
277
|
+
return {
|
|
278
|
+
technical_owner_asks_in_execution: asks.filter(
|
|
279
|
+
(r) =>
|
|
280
|
+
r.phase === 'execution' &&
|
|
281
|
+
r.ownership !== 'unknown' &&
|
|
282
|
+
!OWNER_OWNED.has(r.ownership),
|
|
283
|
+
).length,
|
|
284
|
+
workflow_asks: asks.filter((r) => r.workflow).length,
|
|
285
|
+
repeat_asks: null,
|
|
286
|
+
};
|
|
131
287
|
}
|
|
132
288
|
|
|
133
289
|
/**
|
|
@@ -143,8 +299,13 @@ export function scanFile(text: string): Region[] {
|
|
|
143
299
|
|
|
144
300
|
for (let i = 0; i < lines.length; i += 1) {
|
|
145
301
|
const line = lines[i] as string;
|
|
302
|
+
if (BYPASS_RE.test(line)) {
|
|
303
|
+
out.push({ cls: 'bypass', line: i + 1, questions: 0, text: line });
|
|
304
|
+
consumed.add(i);
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
146
307
|
if (COUNT_ONLY_RE.test(line) && COUNT_PLACEHOLDER_RE.test(line)) {
|
|
147
|
-
out.push({ cls: 'count-only', line: i + 1, questions: 0 });
|
|
308
|
+
out.push({ cls: 'count-only', line: i + 1, questions: 0, text: line });
|
|
148
309
|
consumed.add(i);
|
|
149
310
|
}
|
|
150
311
|
}
|
|
@@ -159,22 +320,25 @@ export function scanFile(text: string): Region[] {
|
|
|
159
320
|
}
|
|
160
321
|
const body = lines.slice(i, end);
|
|
161
322
|
if (!body.some((l) => ASK_OBLIGATION_RE.test(l))) {
|
|
162
|
-
out.push({ cls: 'file-parked', line: i + 1, questions: 0 });
|
|
323
|
+
out.push({ cls: 'file-parked', line: i + 1, questions: 0, text: body.join(' ') });
|
|
163
324
|
}
|
|
164
325
|
}
|
|
165
326
|
|
|
166
327
|
let start = -1;
|
|
167
328
|
let questions = 0;
|
|
329
|
+
let end = -1;
|
|
168
330
|
const flush = (): void => {
|
|
169
331
|
if (start >= 0 && questions > 0) {
|
|
170
332
|
out.push({
|
|
171
333
|
cls: questions >= 2 ? 'batch' : 'single',
|
|
172
334
|
line: start + 1,
|
|
173
335
|
questions,
|
|
336
|
+
text: lines.slice(start, end + 1).join(' '),
|
|
174
337
|
});
|
|
175
338
|
}
|
|
176
339
|
start = -1;
|
|
177
340
|
questions = 0;
|
|
341
|
+
end = -1;
|
|
178
342
|
};
|
|
179
343
|
let inFence = false;
|
|
180
344
|
for (let i = 0; i < lines.length; i += 1) {
|
|
@@ -194,6 +358,7 @@ export function scanFile(text: string): Region[] {
|
|
|
194
358
|
if (start < 0) {
|
|
195
359
|
start = i;
|
|
196
360
|
}
|
|
361
|
+
end = i;
|
|
197
362
|
if (!consumed.has(i) && isQuestionLine(line)) {
|
|
198
363
|
questions += 1;
|
|
199
364
|
}
|
|
@@ -246,19 +411,33 @@ export interface Census {
|
|
|
246
411
|
readonly totals: Record<AskClass, number>;
|
|
247
412
|
readonly files: readonly FileCensus[];
|
|
248
413
|
readonly scanned: number;
|
|
414
|
+
readonly axes: readonly AxisRow[];
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/** One line per target, for the terminal summary. */
|
|
418
|
+
export function renderTargets(t: Targets): string[] {
|
|
419
|
+
const verdict = (n: number): string => (n === 0 ? 'MET' : `MISSED (${String(n)})`);
|
|
420
|
+
return [
|
|
421
|
+
` target: zero technical owner asks in execution ${verdict(t.technical_owner_asks_in_execution)}`,
|
|
422
|
+
` target: zero commit/push/CI/conflict asks ${verdict(t.workflow_asks)}`,
|
|
423
|
+
` target: zero repeats of an answered question NOT MEASURED (transcript axis)`,
|
|
424
|
+
];
|
|
249
425
|
}
|
|
250
426
|
|
|
251
427
|
function zero(): Record<AskClass, number> {
|
|
252
|
-
return { single: 0, batch: 0, 'count-only': 0, 'file-parked': 0 };
|
|
428
|
+
return { single: 0, batch: 0, 'count-only': 0, 'file-parked': 0, bypass: 0 };
|
|
253
429
|
}
|
|
254
430
|
|
|
255
431
|
export function census(roots: readonly string[], only: string | null): Census {
|
|
256
432
|
const totals = zero();
|
|
433
|
+
const axes: AxisRow[] = [];
|
|
257
434
|
const files: FileCensus[] = [];
|
|
258
|
-
|
|
435
|
+
// Renamed off `targets` — that name is the exported target-summary
|
|
436
|
+
// function now, and a local shadowing it reads as a call site that works.
|
|
437
|
+
const targetFiles = only
|
|
259
438
|
? [path.join(REPO_ROOT, only)]
|
|
260
439
|
: roots.flatMap((r) => filesUnder(r));
|
|
261
|
-
for (const abs of
|
|
440
|
+
for (const abs of targetFiles) {
|
|
262
441
|
let text: string;
|
|
263
442
|
try {
|
|
264
443
|
text = fs.readFileSync(abs, 'utf8');
|
|
@@ -266,15 +445,17 @@ export function census(roots: readonly string[], only: string | null): Census {
|
|
|
266
445
|
continue;
|
|
267
446
|
}
|
|
268
447
|
const counts = zero();
|
|
448
|
+
const rel = path.relative(REPO_ROOT, abs).split(path.sep).join('/');
|
|
269
449
|
for (const r of scanFile(text)) {
|
|
270
450
|
counts[r.cls] += 1;
|
|
271
451
|
totals[r.cls] += 1;
|
|
452
|
+
axes.push(axesFor(rel, r));
|
|
272
453
|
}
|
|
273
454
|
if (ASK_CLASSES.some((c) => counts[c] > 0)) {
|
|
274
455
|
files.push({ file: path.relative(REPO_ROOT, abs).split(path.sep).join('/'), counts });
|
|
275
456
|
}
|
|
276
457
|
}
|
|
277
|
-
return { roots, totals, files, scanned:
|
|
458
|
+
return { roots, totals, files, scanned: targetFiles.length, axes };
|
|
278
459
|
}
|
|
279
460
|
|
|
280
461
|
/** `<sha> <ISO commit date>` — the pin. Deterministic at a given commit. */
|
|
@@ -345,14 +526,76 @@ export function render(c: Census, native: NativeRate | null): string {
|
|
|
345
526
|
lines.push('MEASURED zero, not an uninstrumented one.');
|
|
346
527
|
}
|
|
347
528
|
lines.push('');
|
|
529
|
+
lines.push('## Axes');
|
|
530
|
+
lines.push('');
|
|
531
|
+
lines.push(
|
|
532
|
+
'Four axes per ask region — `phase`, `ownership`, `avoidable`,',
|
|
533
|
+
);
|
|
534
|
+
lines.push(
|
|
535
|
+
'`resolver_attempted`. Every one is decidable from the region and its file;',
|
|
536
|
+
);
|
|
537
|
+
lines.push('none is read from intent.');
|
|
538
|
+
lines.push('');
|
|
539
|
+
lines.push('| phase | regions | avoidable | resolver named |');
|
|
540
|
+
lines.push('|---|---|---|---|');
|
|
541
|
+
for (const phase of PHASES) {
|
|
542
|
+
const rows = c.axes.filter((r) => r.phase === phase);
|
|
543
|
+
lines.push(
|
|
544
|
+
`| \`${phase}\` | ${String(rows.length)} | ` +
|
|
545
|
+
`${String(rows.filter((r) => r.avoidable).length)} | ` +
|
|
546
|
+
`${String(rows.filter((r) => r.resolver_attempted).length)} |`,
|
|
547
|
+
);
|
|
548
|
+
}
|
|
549
|
+
lines.push('');
|
|
550
|
+
lines.push('| ownership | regions |');
|
|
551
|
+
lines.push('|---|---|');
|
|
552
|
+
const byOwnership = new Map<string, number>();
|
|
553
|
+
for (const r of c.axes) byOwnership.set(r.ownership, (byOwnership.get(r.ownership) ?? 0) + 1);
|
|
554
|
+
for (const key of [...byOwnership.keys()].sort()) {
|
|
555
|
+
lines.push(`| \`${key}\` | ${String(byOwnership.get(key) ?? 0)} |`);
|
|
556
|
+
}
|
|
557
|
+
lines.push('');
|
|
558
|
+
lines.push('### Targets');
|
|
559
|
+
lines.push('');
|
|
560
|
+
const t = targets(c.axes);
|
|
561
|
+
const verdict = (n: number): string => (n === 0 ? 'MET' : `MISSED (${String(n)})`);
|
|
562
|
+
lines.push(
|
|
563
|
+
`- **Zero technical owner asks in execution:** ${verdict(t.technical_owner_asks_in_execution)}`,
|
|
564
|
+
);
|
|
565
|
+
lines.push(`- **Zero commit / push / CI / conflict asks:** ${verdict(t.workflow_asks)}`);
|
|
566
|
+
lines.push(
|
|
567
|
+
'- **Zero repeats of an already-answered question:** NOT MEASURED — a repeat is a',
|
|
568
|
+
);
|
|
569
|
+
lines.push(
|
|
570
|
+
' property of a TRANSCRIPT, not of an authored surface. Reported absent rather than',
|
|
571
|
+
);
|
|
572
|
+
lines.push(' as zero, on the same ground the native-ask rate is carried in.');
|
|
573
|
+
if (t.technical_owner_asks_in_execution > 0 || t.workflow_asks > 0) {
|
|
574
|
+
lines.push('');
|
|
575
|
+
lines.push('Rows that miss a target:');
|
|
576
|
+
lines.push('');
|
|
577
|
+
for (const r of c.axes) {
|
|
578
|
+
if (r.cls !== 'single' && r.cls !== 'batch') continue;
|
|
579
|
+
const missesOne =
|
|
580
|
+
r.phase === 'execution' && r.ownership !== 'unknown' && !OWNER_OWNED.has(r.ownership);
|
|
581
|
+
if (!missesOne && !r.workflow) continue;
|
|
582
|
+
lines.push(
|
|
583
|
+
`- \`${r.file}:${String(r.line)}\` — ${r.cls}, ${r.phase}, ${r.ownership}` +
|
|
584
|
+
(r.workflow ? ', workflow ask' : ''),
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
lines.push('');
|
|
348
589
|
lines.push('## Per file');
|
|
349
590
|
lines.push('');
|
|
350
|
-
|
|
351
|
-
|
|
591
|
+
// Derived from ASK_CLASSES rather than written out: a hand-written header
|
|
592
|
+
// and a derived Totals block drift the moment a class is added, and the
|
|
593
|
+
// drift is silent because both tables still render.
|
|
594
|
+
lines.push(`| file | ${ASK_CLASSES.join(' | ')} |`);
|
|
595
|
+
lines.push(`|${'---|'.repeat(ASK_CLASSES.length + 1)}`);
|
|
352
596
|
for (const f of c.files) {
|
|
353
597
|
lines.push(
|
|
354
|
-
`| \`${f.file}\` | ${
|
|
355
|
-
`${String(f.counts['count-only'])} | ${String(f.counts['file-parked'])} |`,
|
|
598
|
+
`| \`${f.file}\` | ${ASK_CLASSES.map((cls) => String(f.counts[cls])).join(' | ')} |`,
|
|
356
599
|
);
|
|
357
600
|
}
|
|
358
601
|
lines.push('');
|
|
@@ -367,6 +610,30 @@ export function selfTest(): number {
|
|
|
367
610
|
'count-only',
|
|
368
611
|
1,
|
|
369
612
|
],
|
|
613
|
+
[
|
|
614
|
+
'an explicit user bypass is its own axis',
|
|
615
|
+
'An explicit *just write it* drops the closure pass.\n',
|
|
616
|
+
'bypass',
|
|
617
|
+
1,
|
|
618
|
+
],
|
|
619
|
+
[
|
|
620
|
+
'a bypass line is not also counted as a question',
|
|
621
|
+
'Did the user say just write it?\n',
|
|
622
|
+
'single',
|
|
623
|
+
0,
|
|
624
|
+
],
|
|
625
|
+
[
|
|
626
|
+
'a mission grant is NOT a bypass — an inferred one never matches',
|
|
627
|
+
'The mission grant authorises the run end to end.\n',
|
|
628
|
+
'bypass',
|
|
629
|
+
0,
|
|
630
|
+
],
|
|
631
|
+
[
|
|
632
|
+
'an autonomy setting is NOT a bypass either',
|
|
633
|
+
'With personal.autonomy on, trivial questions are suppressed.\n',
|
|
634
|
+
'bypass',
|
|
635
|
+
0,
|
|
636
|
+
],
|
|
370
637
|
[
|
|
371
638
|
'a bare Open questions section with no obligation is file-parked',
|
|
372
639
|
'## Open questions\n\n- something\n',
|
|
@@ -491,6 +758,9 @@ export function main(argv: string[]): number {
|
|
|
491
758
|
for (const cls of ASK_CLASSES) {
|
|
492
759
|
process.stdout.write(` ${cls.padEnd(12)} ${String(c.totals[cls])}\n`);
|
|
493
760
|
}
|
|
761
|
+
for (const line of renderTargets(targets(c.axes))) {
|
|
762
|
+
process.stdout.write(`${line}\n`);
|
|
763
|
+
}
|
|
494
764
|
return 0;
|
|
495
765
|
}
|
|
496
766
|
|