@event4u/agent-config 14.17.0 → 14.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/.augment-plugin/marketplace.json +3 -3
- package/.augment-plugin/plugin.json +1 -1
- package/.claude-plugin/marketplace.json +1 -1
- package/CHANGELOG.md +170 -79
- package/README.md +1 -1
- package/dist/agent-src/commands/pr/merge.md +35 -44
- package/dist/agent-src/skills/accessibility-auditor/SKILL.md +2 -0
- package/dist/agent-src/skills/ai-code-blindspots/SKILL.md +27 -1
- package/dist/agent-src/skills/code-intelligence/SKILL.md +60 -12
- package/dist/agent-src/skills/complexity-first-planning/SKILL.md +27 -0
- package/dist/agent-src/skills/design-review/SKILL.md +2 -0
- package/dist/agent-src/skills/feature-planning/SKILL.md +34 -0
- package/dist/agent-src/skills/git-workflow/SKILL.md +37 -12
- package/dist/agent-src/skills/git-workflow/references/push-closes-its-loop.md +176 -0
- package/dist/agent-src/skills/laravel-mail/SKILL.md +44 -0
- package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +40 -0
- package/dist/agent-src/skills/using-git-worktrees/SKILL.md +12 -0
- package/dist/agent-src/skills/verify-repair-loop/SKILL.md +53 -8
- package/dist/agent-src/skills/worktree-lifecycle/SKILL.md +3 -1
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/cli-delegate/cmd_conformance.js +335 -659
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +15 -15
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +1 -1
- package/dist/discovery/dormancy-report.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 +959 -1304
- package/dist/mcp/registry-manifest.json +2 -2
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +671 -1002
- package/dist/shared/settingsConsent.js +1 -1
- package/package.json +1 -1
- package/src/config/conformance-claim-baseline.json +9 -0
- package/src/config/gate-violation-baselines.json +3 -3
- package/src/config/release-gate-locality.yml +129 -0
- package/src/scripts/_lib/release_highlights.ts +172 -1
- package/src/scripts/_lib/release_material.ts +66 -0
- package/src/scripts/_lib/repeated_run.ts +77 -0
- package/src/scripts/_lib/tamper_vocabulary.ts +242 -0
- package/src/scripts/_lib/unified_diff.ts +121 -0
- package/src/scripts/check_finding_dispositions.ts +179 -3
- package/src/scripts/check_installed_hooks_fresh.ts +381 -0
- package/src/scripts/check_release_highlights.ts +25 -13
- package/src/scripts/check_suppression_hygiene.ts +11 -0
- package/src/scripts/code_graph/build.ts +230 -33
- package/src/scripts/code_graph/extract.ts +168 -33
- package/src/scripts/code_graph/types.ts +37 -2
- package/src/scripts/code_graph/validate.ts +12 -1
- package/src/scripts/conformance_scan.ts +2 -2
- package/src/scripts/detect_silent_catch.ts +403 -0
- package/src/scripts/detect_verification_tampering.ts +538 -0
- package/src/scripts/git_authorization_hook.ts +153 -17
- package/src/scripts/hook_manifest.json +1 -1
- package/src/scripts/hook_manifest.yaml +33 -19
- package/src/scripts/hooks/block_no_verify.ts +3 -3
- package/src/scripts/hooks/concern_registry.ts +2 -2
- package/src/scripts/hooks/evidence_independence.ts +21 -2
- package/src/scripts/hooks/{block_unauthorized_git.ts → git_command_classifier.ts} +25 -369
- package/src/scripts/hooks/push_settle_hook.ts +250 -0
- package/src/scripts/hooks/ship_diff_volume_hook.ts +1 -1
- package/src/scripts/install-hooks.sh +134 -1
- package/src/scripts/language_mirror_hook.ts +27 -5
- package/src/scripts/release.ts +31 -143
- package/src/scripts/release_drill.ts +71 -1
- package/src/scripts/release_publication.ts +243 -3
- package/src/scripts/release_verify.ts +220 -0
- package/src/scripts/schemas/review-findings.schema.json +1 -1
- package/src/scripts/schemas/skill.schema.json +11 -1
- package/src/scripts/self_review_gate.ts +10 -1
- package/src/shared/settingsConsent.ts +1 -1
|
@@ -2,9 +2,14 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Git-authorization ledger — `user_prompt_submit` concern.
|
|
4
4
|
*
|
|
5
|
-
* Records which git operations the user's OWN WORDS authorize this turn
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* Records which git operations the user's OWN WORDS authorize this turn.
|
|
6
|
+
*
|
|
7
|
+
* NOTHING ENFORCES THIS LEDGER ANY MORE. Its consumer — the
|
|
8
|
+
* `block-unauthorized-git` gate — was removed by owner decision on 2026-09-04
|
|
9
|
+
* (ADR-254). What still reads the file is `hooks/evidence_independence.ts`,
|
|
10
|
+
* which takes `detected_at` as a per-turn stamp, and `conformance_scan.ts`,
|
|
11
|
+
* which MEASURES unauthorized operations after the fact. The record is kept
|
|
12
|
+
* because measuring is worth keeping; it refuses nothing.
|
|
8
13
|
*
|
|
9
14
|
* WHY — the measured defect (30-session conformance audit, 2026-08-06):
|
|
10
15
|
*
|
|
@@ -630,10 +635,9 @@ function _errText(err: unknown): string {
|
|
|
630
635
|
/**
|
|
631
636
|
* The largest pull-request number GitHub can issue: a signed 32-bit integer.
|
|
632
637
|
*
|
|
633
|
-
* Taken from the API contract rather than estimated, and shared
|
|
634
|
-
*
|
|
635
|
-
*
|
|
636
|
-
* negation vocabulary.
|
|
638
|
+
* Taken from the API contract rather than estimated, and shared with
|
|
639
|
+
* `hooks/git_command_classifier.ts` so the two cannot drift — the failure this
|
|
640
|
+
* file already learned once with its negation vocabulary.
|
|
637
641
|
*/
|
|
638
642
|
export const PR_NUMBER_MAX = 2147483647;
|
|
639
643
|
|
|
@@ -665,19 +669,50 @@ export function extractMergeTargets(prompt: string): number[] {
|
|
|
665
669
|
}
|
|
666
670
|
|
|
667
671
|
/**
|
|
668
|
-
* A
|
|
672
|
+
* A bare stop word — a withdrawal that names no operation at all.
|
|
669
673
|
*
|
|
670
674
|
* Revocation must be cheaper to express than authorization, so this matches a
|
|
671
|
-
* bare stop word on its own
|
|
672
|
-
*
|
|
673
|
-
*
|
|
675
|
+
* bare stop word on its own. It is deliberately over-inclusive in the safe
|
|
676
|
+
* direction: a false revocation costs one prompt, a missed revocation costs an
|
|
677
|
+
* unwanted merge. The alternation is orthogonal to negation and is unchanged.
|
|
674
678
|
*/
|
|
675
|
-
const
|
|
676
|
-
/\b(stop|stopp|halt|abbrechen|abbruch|cancel|revoke|widerruf(en)?|zur(ü|ue)ck(nehmen|ziehen)|hold\s+(everything|on|the\s+merge)|warte|wait)\b
|
|
679
|
+
const REVOKE_STOP_WORD =
|
|
680
|
+
/\b(stop|stopp|halt|abbrechen|abbruch|cancel|revoke|widerruf(en)?|zur(ü|ue)ck(nehmen|ziehen)|hold\s+(everything|on|the\s+merge)|warte|wait)\b/iu;
|
|
681
|
+
|
|
682
|
+
/** The merge verb itself, with no negation notion of its own. */
|
|
683
|
+
const MERGE_VERB = /\b(merg(e|en|ing)|zusammenf(ü|ue)hren)\b/giu;
|
|
677
684
|
|
|
678
685
|
/** Does this human turn withdraw standing merge grants? */
|
|
679
686
|
export function isRevocation(prompt: string): boolean {
|
|
680
|
-
|
|
687
|
+
if (REVOKE_STOP_WORD.test(prompt) || isBareRefusal(prompt)) {
|
|
688
|
+
return true;
|
|
689
|
+
}
|
|
690
|
+
// ONE negation implementation, both callers. Until 2026-09-04 this function
|
|
691
|
+
// carried its own inline vocabulary and a fixed `{0,30}` BACKWARD window,
|
|
692
|
+
// while `classifyAuthorization` reached the clause-scoped, abbreviation-aware
|
|
693
|
+
// `negatedBefore` about 240 lines below. The two disagreed on real prompts in
|
|
694
|
+
// both directions — measured at b75d7f7cb:
|
|
695
|
+
//
|
|
696
|
+
// "Merge PR #12 auf keinen Fall." isRevocation=false, a standing
|
|
697
|
+
// grant over #12 SURVIVED
|
|
698
|
+
// "Merge #12 under no circumstances." isRevocation=false, same
|
|
699
|
+
// "Please do not push, but merge PR #7." isRevocation=true while
|
|
700
|
+
// classifyAuthorization returned
|
|
701
|
+
// ["pr-merge"] — the two parsers
|
|
702
|
+
// contradicting each other on a
|
|
703
|
+
// corpus row asserted green
|
|
704
|
+
//
|
|
705
|
+
// `NEGATION_WORD`'s docblock already stated the rule this restores: one
|
|
706
|
+
// vocabulary for the whole file, because two drift invisibly until a prompt
|
|
707
|
+
// lands in the gap between them.
|
|
708
|
+
MERGE_VERB.lastIndex = 0;
|
|
709
|
+
let m: RegExpExecArray | null;
|
|
710
|
+
while ((m = MERGE_VERB.exec(prompt)) !== null) {
|
|
711
|
+
if (negatedBefore(prompt, m.index, m[0])) {
|
|
712
|
+
return true;
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
return false;
|
|
681
716
|
}
|
|
682
717
|
|
|
683
718
|
/** Mint a grant id that a replayed ledger cannot collide with. */
|
|
@@ -746,9 +781,53 @@ export function foldGrants(
|
|
|
746
781
|
* negation vocabularies in one tree drift, and the drift is invisible until a
|
|
747
782
|
* prompt lands in the gap between them" — so the list moved here rather than
|
|
748
783
|
* being copied fifteen times.
|
|
784
|
+
*
|
|
785
|
+
* BOTH DIRECTIONS READ IT, and since 2026-09-04 that is checkable rather than
|
|
786
|
+
* aspirational: `classifyAuthorization` reaches it through `negatedBefore`, and
|
|
787
|
+
* `isRevocation` reaches the same `negatedBefore` plus `isBareRefusal`. The
|
|
788
|
+
* revocation path was the copy the original consolidation missed — it kept a
|
|
789
|
+
* ten-form inline list behind a fixed 30-character backward window, and the two
|
|
790
|
+
* grammars disagreed on real prompts in both directions until they were merged.
|
|
791
|
+
* A THIRD caller adds itself here, not next to itself.
|
|
792
|
+
*
|
|
793
|
+
* THE APOSTROPHE IS PART OF THE VOCABULARY, not a typo tolerance. The list
|
|
794
|
+
* read `dont|don't` — ASCII only — while every macOS, iOS, Word and Slack
|
|
795
|
+
* input turns a typed apostrophe into U+2019 by default. Measured at
|
|
796
|
+
* b75d7f7cb, and it leaked in the DANGEROUS direction on the authorization
|
|
797
|
+
* path, not merely the revocation one:
|
|
798
|
+
*
|
|
799
|
+
* "don't merge PR #12" classifyAuthorization = [] (denied)
|
|
800
|
+
* "don\u2019t merge PR #12" classifyAuthorization = ["pr-merge"] (AUTHORIZED)
|
|
801
|
+
* "don\u2019t push" classifyAuthorization = ["push"] (AUTHORIZED)
|
|
802
|
+
*
|
|
803
|
+
* One character of smart-quote substitution turned a prohibition into a grant
|
|
804
|
+
* for an irreversible operation. `don['\u2019\u2018\u02bc]?t` covers the straight, the two
|
|
805
|
+
* typographic and the modifier-letter forms in the one shared list, so both
|
|
806
|
+
* callers gain it at once — which is the whole argument for one vocabulary.
|
|
807
|
+
*/
|
|
808
|
+
/**
|
|
809
|
+
* Every apostrophe a keyboard or an autocorrect can produce for one word.
|
|
810
|
+
*
|
|
811
|
+
* Named once and shared by the vocabulary AND the tokenizer below. Written out
|
|
812
|
+
* twice, `don\u2018t` matched the vocabulary and then split into TWO tokens in
|
|
813
|
+
* `isBareRefusal` — this file's own drift failure, one character wide, caught
|
|
814
|
+
* by the council-mandated token-policy test rather than in review.
|
|
815
|
+
*/
|
|
816
|
+
const APOSTROPHE = "'\u2019\u2018\u02bc";
|
|
817
|
+
|
|
818
|
+
const NEGATION_ALTERNATION =
|
|
819
|
+
`nicht|nichts|kein(?:e|en|em|er|es)?|niemals|nie|no|not|don[${APOSTROPHE}]?t|never|without|ohne`;
|
|
820
|
+
|
|
821
|
+
const NEGATION_WORD = new RegExp(`\\b(${NEGATION_ALTERNATION})\\b`, "i");
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* The same vocabulary, anchored to a whole token.
|
|
825
|
+
*
|
|
826
|
+
* Built from `NEGATION_ALTERNATION` rather than written out a second time —
|
|
827
|
+
* a copied list is the exact drift this file's `NEGATION_WORD` docblock warns
|
|
828
|
+
* about, and repairing one such copy is what this change is for.
|
|
749
829
|
*/
|
|
750
|
-
const
|
|
751
|
-
/\b(nicht|nichts|kein(e|en|em|er|es)?|niemals|nie|no|not|dont|don't|never|without|ohne)\b/i;
|
|
830
|
+
const NEGATION_TOKEN = new RegExp(`^(?:${NEGATION_ALTERNATION})$`, "i");
|
|
752
831
|
|
|
753
832
|
/**
|
|
754
833
|
* Is the match at `index` under a negation?
|
|
@@ -768,7 +847,9 @@ const NEGATION_WORD =
|
|
|
768
847
|
* says why. The 30-character window inside the sentence is inherited from the
|
|
769
848
|
* `pr-merge` lookbehind that this generalises.
|
|
770
849
|
*/
|
|
771
|
-
const
|
|
850
|
+
const CONTRAST_ALTERNATION = "aber|sondern|jedoch|but|however|instead";
|
|
851
|
+
|
|
852
|
+
const CONTRAST_CUE = new RegExp(`\\b(${CONTRAST_ALTERNATION})\\b`, "gi");
|
|
772
853
|
|
|
773
854
|
/**
|
|
774
855
|
* Abbreviation and decimal dots are NOT sentence boundaries.
|
|
@@ -926,6 +1007,61 @@ export function negatedBefore(text: string, index: number, matched = ""): boolea
|
|
|
926
1007
|
return NEGATION_WORD.test(before) || NEGATION_WORD.test(matched) || NEGATION_WORD.test(after);
|
|
927
1008
|
}
|
|
928
1009
|
|
|
1010
|
+
/**
|
|
1011
|
+
* Is any clause of this turn a BARE refusal — negation words and nothing else?
|
|
1012
|
+
*
|
|
1013
|
+
* `negatedBefore` answers "is this operation negated", which needs the
|
|
1014
|
+
* operation to be in the clause. A withdrawal does not have to name one:
|
|
1015
|
+
* `"Merge PR #12? Actually, don't."` puts the merge in a question sentence and
|
|
1016
|
+
* the refusal in the next one, so no clause anywhere holds both. Measured at
|
|
1017
|
+
* b75d7f7cb and again after the shared-parser change: `isRevocation` returned
|
|
1018
|
+
* false and a standing grant over #12 survived.
|
|
1019
|
+
*
|
|
1020
|
+
* The scope is a CLAUSE whose every token is a negation word, which is the
|
|
1021
|
+
* narrow half. `"Do not push."` is not a bare refusal — `push` is a content
|
|
1022
|
+
* word, so the clause names an operation and `negatedBefore` owns it. That
|
|
1023
|
+
* boundary is what keeps this from revoking `"Nicht pushen. Merge PR #12."`,
|
|
1024
|
+
* a corpus row whose merge must still be authorized.
|
|
1025
|
+
*
|
|
1026
|
+
* It reuses `NEGATION_TOKEN`, so the one vocabulary covers this reading too.
|
|
1027
|
+
*
|
|
1028
|
+
* WHAT IT REVOKES — every standing grant, and that is the PRE-EXISTING
|
|
1029
|
+
* contract rather than a new one. `foldGrants` returns `[]` for any revocation,
|
|
1030
|
+
* which is how a bare `"stop"` has always behaved; a bare refusal is the same
|
|
1031
|
+
* class of utterance and takes the same transition. Nothing here narrows or
|
|
1032
|
+
* widens grant selection, so the council's question about which grant a bare
|
|
1033
|
+
* `"don't"` targets is answered by the existing product semantics: all of them,
|
|
1034
|
+
* in the safe direction.
|
|
1035
|
+
*
|
|
1036
|
+
* WHAT IT DOES NOT FIRE ON — a negation carrying any content word, which is
|
|
1037
|
+
* what keeps a conversational aside from costing the user their authority.
|
|
1038
|
+
* Measured against the council's boundary set:
|
|
1039
|
+
*
|
|
1040
|
+
* "Merge #12? Actually, I don't think so." false — "think"/"so" are content
|
|
1041
|
+
* "Merge #12? Don't worry, I'll do it." false — "worry" is content
|
|
1042
|
+
* "Actually, don't worry about it." false — same
|
|
1043
|
+
* "Merge #12? Actually, don't." TRUE — the clause is only "don't"
|
|
1044
|
+
* "Merge #12. Don't." TRUE — a retraction one sentence later
|
|
1045
|
+
* "Merge #12? , ; ." false — no tokens at all
|
|
1046
|
+
*/
|
|
1047
|
+
/** A word token, apostrophes included, so `don't` stays ONE token. */
|
|
1048
|
+
const WORD_TOKEN = new RegExp(`[\\p{L}\\p{N}${APOSTROPHE}]+`, "gu");
|
|
1049
|
+
|
|
1050
|
+
/** Clause boundaries, built from the one contrast vocabulary above. */
|
|
1051
|
+
const CLAUSE_SPLIT = new RegExp(`[,;:]|\\b(?:${CONTRAST_ALTERNATION})\\b`, "iu");
|
|
1052
|
+
|
|
1053
|
+
export function isBareRefusal(text: string): boolean {
|
|
1054
|
+
for (const sentence of _sentences(text)) {
|
|
1055
|
+
for (const clause of sentence.split(CLAUSE_SPLIT)) {
|
|
1056
|
+
const tokens = (clause ?? "").match(WORD_TOKEN) ?? [];
|
|
1057
|
+
if (tokens.length > 0 && tokens.every((t) => NEGATION_TOKEN.test(t))) {
|
|
1058
|
+
return true;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
return false;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
929
1065
|
/** Classify which ops a prompt authorizes. Exported for direct testing. */
|
|
930
1066
|
export function classifyAuthorization(prompt: string): {
|
|
931
1067
|
authorized: GitOp[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"fingerprint":"877cc83a:82357","manifest":{"schema_version":1,"concerns":{"chat-history":{"script":"src/scripts/chat_history.ts","args":["hook-dispatch"],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["result"]},"hot-context":{"script":"src/scripts/hot_context_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"handoff-context":{"script":"src/scripts/handoff_context_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"roadmap-progress":{"script":"src/scripts/roadmap_progress_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"onboarding-gate":{"script":"src/scripts/onboarding_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"context-hygiene":{"script":"src/scripts/context_hygiene_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"verify-before-complete":{"script":"src/scripts/before_complete_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"ship-diff-volume":{"script":"src/scripts/hooks/ship_diff_volume_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"minimal-safe-diff":{"script":"src/scripts/minimal_safe_diff_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"injection-scan":{"script":"src/scripts/injection_scan_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"block-no-verify":{"script":"src/scripts/hooks/block_no_verify.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"block-kernel-rule-writes":{"script":"src/scripts/hooks/block_kernel_rule_writes.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"block-speaking-inbox-dir":{"script":"src/scripts/hooks/block_speaking_inbox_dir.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"block-config-weakening":{"script":"src/scripts/hooks/block_config_weakening.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"rtk-wrap":{"script":"src/scripts/hooks/rtk_wrap_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-slop":{"script":"src/scripts/hooks/design_slop_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-pass":{"script":"src/scripts/hooks/design_pass_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-pass-stop":{"script":"src/scripts/hooks/design_pass_hook.ts","args":["--slot","stop"],"fail_closed":false,"severity":"advisory"},"ui-route-nudge":{"script":"src/scripts/hooks/ui_route_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"suggestion-capture":{"script":"src/scripts/hooks/suggestion_capture_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"code-graph-nudge":{"script":"src/scripts/hooks/code_graph_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Grep","Glob","Read"],"needs_payload_bodies":["input"]},"memory-learn":{"script":"src/scripts/memory_learn_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"first-run-gate":{"script":"src/scripts/first_run_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"profile-staleness":{"script":"src/scripts/profile_staleness_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"wrapper-freshness":{"script":"src/scripts/wrapper_freshness_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"surface-probe":{"script":"src/scripts/surface_probe_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"team-review-gate":{"script":"src/scripts/team_review_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"pr-url-reminder":{"script":"src/scripts/pr_url_reminder_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"language-mirror":{"script":"src/scripts/language_mirror_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"git-authorization":{"script":"src/scripts/git_authorization_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"block-unauthorized-git":{"script":"src/scripts/hooks/block_unauthorized_git.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"evidence-independence":{"script":"src/scripts/hooks/evidence_independence.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"session-canary":{"script":"src/scripts/session_canary_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"council-availability":{"script":"src/scripts/council_availability_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"telemetry-disclosure":{"script":"src/scripts/telemetry_disclosure_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"telemetry-flush":{"script":"src/scripts/hooks/telemetry_flush_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"self-repair":{"script":"src/scripts/self_repair_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"session-register":{"script":"src/scripts/session_register_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"orchestration-record":{"script":"src/scripts/hooks/orchestration_record_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Agent","Task"],"needs_payload_bodies":["input","result"]},"telemetry-usage":{"script":"src/scripts/hooks/telemetry_usage_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Skill"],"needs_payload_bodies":["input"]},"delegation-nudge":{"script":"src/scripts/hooks/delegation_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","nudge_rank":1},"skill-route":{"script":"src/scripts/hooks/skill_route_hook.ts","args":[],"fail_closed":false,"severity":"advisory","nudge_rank":2},"rule-inject":{"script":"src/scripts/hooks/rule_inject_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"end-review-nudge":{"script":"src/scripts/hooks/end_review_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","skip_on_refusal_retry":true},"turn-end-gate":{"script":"src/scripts/hooks/turn_end_gate_hook.ts","args":[],"fail_closed":false,"severity":"blocking"},"comment-discipline":{"script":"src/scripts/hooks/comment_discipline_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Write","Edit"],"needs_payload_bodies":["input"]},"edit-shape":{"script":"src/scripts/hooks/edit_shape_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Write"],"needs_payload_bodies":["input"]},"reread-guard":{"script":"src/scripts/hooks/reread_guard_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Read","Edit","Write"],"needs_payload_bodies":["input"]},"session-eol":{"script":"src/scripts/hooks/session_eol_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"run-continuation":{"script":"src/scripts/hooks/run_continuation_hook.ts","args":[],"fail_closed":false,"severity":"blocking"},"interruption-ledger":{"script":"src/scripts/hooks/interruption_ledger_hook.ts","args":[],"fail_closed":false,"severity":"advisory","skip_on_refusal_retry":true},"subagent-ledger":{"script":"src/scripts/hooks/subagent_ledger_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"tool-result-bytes":{"script":"src/scripts/hooks/tool_result_bytes_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"spawn-guard-shadow":{"script":"src/scripts/hooks/spawn_guard_shadow_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Agent","Task"]},"source-first-gate":{"script":"src/scripts/hooks/source_first_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"journal-record":{"script":"src/scripts/hooks/journal_record_hook.ts","args":[],"fail_closed":false,"severity":"advisory"}},"roles":{"worker":{"drop":["delegation-nudge","skill-route","end-review-nudge","council-availability","team-review-gate","self-repair","session-eol","interruption-ledger"]}},"platforms":{"augment":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"claude":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register","journal-record"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush","journal-record"],"stop":["chat-history","hot-context","verify-before-complete","team-review-gate","end-review-nudge","turn-end-gate","self-repair","session-register","session-eol","interruption-ledger","roadmap-progress","design-pass-stop","suggestion-capture","journal-record","run-continuation"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","delegation-nudge","skill-route","git-authorization","session-canary","self-repair","session-register","rule-inject","suggestion-capture","journal-record"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate","rule-inject"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","language-mirror","design-pass","journal-record"],"pre_compact":["language-mirror","hot-context","rule-inject","journal-record"],"subagent_start":["subagent-ledger","journal-record"],"subagent_stop":["subagent-ledger","journal-record"]},"cowork":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"pre_tool_use":["block-no-verify","block-unauthorized-git","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"],"subagent_start":["subagent-ledger"],"subagent_stop":["subagent-ledger"]},"cursor":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"cline":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"windsurf":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","profile-staleness","wrapper-freshness","surface-probe","session-register"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","design-pass-stop"],"user_prompt_submit":["chat-history","verify-before-complete","language-mirror","git-authorization","session-canary","self-repair","session-register"]},"gemini":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"copilot":{"fallback_only":true}},"native_event_aliases":{"augment":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use"},"claude":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact","SubagentStart":"subagent_start","SubagentStop":"subagent_stop"},"cowork":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact","SubagentStart":"subagent_start","SubagentStop":"subagent_stop"},"cursor":{"sessionStart":"session_start","sessionEnd":"session_end","stop":"stop","beforeSubmitPrompt":"user_prompt_submit","postToolUse":"post_tool_use","preToolUse":"pre_tool_use","preCompact":"pre_compact"},"cline":{"TaskStart":"session_start","TaskResume":"session_start","TaskComplete":"session_end","TaskCancel":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact"},"windsurf":{"pre_user_prompt":"user_prompt_submit","post_cascade_response":"stop","post_setup_worktree":"session_start"},"gemini":{"SessionStart":"session_start","SessionEnd":"session_end","BeforeAgent":"user_prompt_submit","AfterAgent":"stop","BeforeTool":"pre_tool_use","AfterTool":"post_tool_use"}}}}
|
|
1
|
+
{"fingerprint":"40918412:83446","manifest":{"schema_version":1,"concerns":{"chat-history":{"script":"src/scripts/chat_history.ts","args":["hook-dispatch"],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["result"]},"hot-context":{"script":"src/scripts/hot_context_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"handoff-context":{"script":"src/scripts/handoff_context_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"roadmap-progress":{"script":"src/scripts/roadmap_progress_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"onboarding-gate":{"script":"src/scripts/onboarding_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"context-hygiene":{"script":"src/scripts/context_hygiene_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"verify-before-complete":{"script":"src/scripts/before_complete_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"ship-diff-volume":{"script":"src/scripts/hooks/ship_diff_volume_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"minimal-safe-diff":{"script":"src/scripts/minimal_safe_diff_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"injection-scan":{"script":"src/scripts/injection_scan_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"block-no-verify":{"script":"src/scripts/hooks/block_no_verify.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"block-kernel-rule-writes":{"script":"src/scripts/hooks/block_kernel_rule_writes.ts","args":[],"fail_closed":true,"severity":"blocking","needs_payload_bodies":["input"]},"block-speaking-inbox-dir":{"script":"src/scripts/hooks/block_speaking_inbox_dir.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"block-config-weakening":{"script":"src/scripts/hooks/block_config_weakening.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"rtk-wrap":{"script":"src/scripts/hooks/rtk_wrap_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-slop":{"script":"src/scripts/hooks/design_slop_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-pass":{"script":"src/scripts/hooks/design_pass_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"design-pass-stop":{"script":"src/scripts/hooks/design_pass_hook.ts","args":["--slot","stop"],"fail_closed":false,"severity":"advisory"},"ui-route-nudge":{"script":"src/scripts/hooks/ui_route_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"suggestion-capture":{"script":"src/scripts/hooks/suggestion_capture_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"code-graph-nudge":{"script":"src/scripts/hooks/code_graph_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Grep","Glob","Read"],"needs_payload_bodies":["input"]},"memory-learn":{"script":"src/scripts/memory_learn_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"first-run-gate":{"script":"src/scripts/first_run_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"profile-staleness":{"script":"src/scripts/profile_staleness_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"wrapper-freshness":{"script":"src/scripts/wrapper_freshness_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"surface-probe":{"script":"src/scripts/surface_probe_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"team-review-gate":{"script":"src/scripts/team_review_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"pr-url-reminder":{"script":"src/scripts/pr_url_reminder_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"push-settle":{"script":"src/scripts/hooks/push_settle_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input","result"]},"language-mirror":{"script":"src/scripts/language_mirror_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"git-authorization":{"script":"src/scripts/git_authorization_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"evidence-independence":{"script":"src/scripts/hooks/evidence_independence.ts","args":[],"fail_closed":false,"severity":"blocking","needs_payload_bodies":["input"]},"session-canary":{"script":"src/scripts/session_canary_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"council-availability":{"script":"src/scripts/council_availability_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"telemetry-disclosure":{"script":"src/scripts/telemetry_disclosure_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"telemetry-flush":{"script":"src/scripts/hooks/telemetry_flush_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"self-repair":{"script":"src/scripts/self_repair_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"session-register":{"script":"src/scripts/session_register_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"orchestration-record":{"script":"src/scripts/hooks/orchestration_record_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Agent","Task"],"needs_payload_bodies":["input","result"]},"telemetry-usage":{"script":"src/scripts/hooks/telemetry_usage_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Skill"],"needs_payload_bodies":["input"]},"delegation-nudge":{"script":"src/scripts/hooks/delegation_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","nudge_rank":1},"skill-route":{"script":"src/scripts/hooks/skill_route_hook.ts","args":[],"fail_closed":false,"severity":"advisory","nudge_rank":2},"rule-inject":{"script":"src/scripts/hooks/rule_inject_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"end-review-nudge":{"script":"src/scripts/hooks/end_review_nudge_hook.ts","args":[],"fail_closed":false,"severity":"advisory","skip_on_refusal_retry":true},"turn-end-gate":{"script":"src/scripts/hooks/turn_end_gate_hook.ts","args":[],"fail_closed":false,"severity":"blocking"},"comment-discipline":{"script":"src/scripts/hooks/comment_discipline_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Write","Edit"],"needs_payload_bodies":["input"]},"edit-shape":{"script":"src/scripts/hooks/edit_shape_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Write"],"needs_payload_bodies":["input"]},"reread-guard":{"script":"src/scripts/hooks/reread_guard_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Read","Edit","Write"],"needs_payload_bodies":["input"]},"session-eol":{"script":"src/scripts/hooks/session_eol_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"run-continuation":{"script":"src/scripts/hooks/run_continuation_hook.ts","args":[],"fail_closed":false,"severity":"blocking"},"interruption-ledger":{"script":"src/scripts/hooks/interruption_ledger_hook.ts","args":[],"fail_closed":false,"severity":"advisory","skip_on_refusal_retry":true},"subagent-ledger":{"script":"src/scripts/hooks/subagent_ledger_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"tool-result-bytes":{"script":"src/scripts/hooks/tool_result_bytes_hook.ts","args":[],"fail_closed":false,"severity":"advisory"},"spawn-guard-shadow":{"script":"src/scripts/hooks/spawn_guard_shadow_hook.ts","args":[],"fail_closed":false,"severity":"advisory","tools":["Agent","Task"]},"source-first-gate":{"script":"src/scripts/hooks/source_first_gate_hook.ts","args":[],"fail_closed":false,"severity":"advisory","needs_payload_bodies":["input"]},"journal-record":{"script":"src/scripts/hooks/journal_record_hook.ts","args":[],"fail_closed":false,"severity":"advisory"}},"roles":{"worker":{"drop":["delegation-nudge","skill-route","end-review-nudge","council-availability","team-review-gate","self-repair","session-eol","interruption-ledger"]}},"platforms":{"augment":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"pre_tool_use":["block-no-verify","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"claude":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register","journal-record"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush","journal-record"],"stop":["chat-history","hot-context","verify-before-complete","team-review-gate","end-review-nudge","turn-end-gate","self-repair","session-register","session-eol","interruption-ledger","roadmap-progress","design-pass-stop","suggestion-capture","journal-record","run-continuation"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","delegation-nudge","skill-route","git-authorization","session-canary","self-repair","session-register","rule-inject","suggestion-capture","journal-record"],"pre_tool_use":["block-no-verify","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate","rule-inject"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","language-mirror","design-pass","journal-record"],"pre_compact":["language-mirror","hot-context","rule-inject","journal-record"],"subagent_start":["subagent-ledger","journal-record"],"subagent_stop":["subagent-ledger","journal-record"]},"cowork":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"pre_tool_use":["block-no-verify","evidence-independence","block-kernel-rule-writes","block-config-weakening","block-speaking-inbox-dir","rtk-wrap","design-slop","ui-route-nudge","code-graph-nudge","ship-diff-volume","reread-guard","spawn-guard-shadow","source-first-gate"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"],"subagent_start":["subagent-ledger"],"subagent_stop":["subagent-ledger"]},"cursor":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"cline":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"windsurf":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","profile-staleness","wrapper-freshness","surface-probe","session-register"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","design-pass-stop"],"user_prompt_submit":["chat-history","verify-before-complete","language-mirror","git-authorization","session-canary","self-repair","session-register"]},"gemini":{"session_start":["chat-history","hot-context","handoff-context","session-canary","council-availability","telemetry-disclosure","first-run-gate","onboarding-gate","verify-before-complete","minimal-safe-diff","profile-staleness","wrapper-freshness","surface-probe","session-register"],"session_end":["chat-history","memory-learn","session-register","roadmap-progress","telemetry-flush"],"stop":["chat-history","hot-context","verify-before-complete","self-repair","session-register","roadmap-progress","design-pass-stop"],"user_prompt_submit":["chat-history","verify-before-complete","minimal-safe-diff","language-mirror","git-authorization","session-canary","self-repair","session-register"],"post_tool_use":["chat-history","roadmap-progress","context-hygiene","verify-before-complete","minimal-safe-diff","injection-scan","pr-url-reminder","push-settle","orchestration-record","telemetry-usage","tool-result-bytes","edit-shape","comment-discipline","design-pass"]},"copilot":{"fallback_only":true}},"native_event_aliases":{"augment":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use"},"claude":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact","SubagentStart":"subagent_start","SubagentStop":"subagent_stop"},"cowork":{"SessionStart":"session_start","SessionEnd":"session_end","Stop":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact","SubagentStart":"subagent_start","SubagentStop":"subagent_stop"},"cursor":{"sessionStart":"session_start","sessionEnd":"session_end","stop":"stop","beforeSubmitPrompt":"user_prompt_submit","postToolUse":"post_tool_use","preToolUse":"pre_tool_use","preCompact":"pre_compact"},"cline":{"TaskStart":"session_start","TaskResume":"session_start","TaskComplete":"session_end","TaskCancel":"stop","UserPromptSubmit":"user_prompt_submit","PostToolUse":"post_tool_use","PreToolUse":"pre_tool_use","PreCompact":"pre_compact"},"windsurf":{"pre_user_prompt":"user_prompt_submit","post_cascade_response":"stop","post_setup_worktree":"session_start"},"gemini":{"SessionStart":"session_start","SessionEnd":"session_end","BeforeAgent":"user_prompt_submit","AfterAgent":"stop","BeforeTool":"pre_tool_use","AfterTool":"post_tool_use"}}}}
|
|
@@ -453,6 +453,21 @@ concerns:
|
|
|
453
453
|
fail_closed: false
|
|
454
454
|
severity: advisory
|
|
455
455
|
needs_payload_bodies: [input, result]
|
|
456
|
+
# Push-settle reminder — the second half of "a push closes its own loop".
|
|
457
|
+
# The pre-push hook answers "is this push safe to make"; nothing answered "is
|
|
458
|
+
# this push finished". Measured over the 30 sessions / 50 PRs before
|
|
459
|
+
# 2026-09-04: 22 of 30 sessions ran `gh run view --log-failed`, 17 of 36
|
|
460
|
+
# readable PRs carried a failed run, and 20 of 50 PRs carried a follow-up
|
|
461
|
+
# `fix(ci|gates|budget)` commit. Every one of those pushes SUCCEEDED — what
|
|
462
|
+
# failed was the ending. Fires only when git's own report shows a ref actually
|
|
463
|
+
# ADVANCED (silent on up-to-date, rejected, dry-run, delete), so it cannot nag
|
|
464
|
+
# on a push that did not happen. Warn only. fail_closed: false.
|
|
465
|
+
push-settle:
|
|
466
|
+
script: src/scripts/hooks/push_settle_hook.ts
|
|
467
|
+
args: []
|
|
468
|
+
fail_closed: false
|
|
469
|
+
severity: advisory
|
|
470
|
+
needs_payload_bodies: [input, result]
|
|
456
471
|
# Language-mirror pin — carries the ONE fact the transcript cannot express:
|
|
457
472
|
# which language the human actually typed. 47 skill/slash-command bodies were
|
|
458
473
|
# measured arriving in the `user` role across 21 of 30 audited sessions, and
|
|
@@ -472,16 +487,15 @@ concerns:
|
|
|
472
487
|
args: []
|
|
473
488
|
fail_closed: false
|
|
474
489
|
severity: advisory
|
|
475
|
-
# The blocking half
|
|
476
|
-
#
|
|
477
|
-
#
|
|
478
|
-
#
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
needs_payload_bodies: [input]
|
|
490
|
+
# The blocking half was REMOVED by owner decision on 2026-09-04 (ADR-254).
|
|
491
|
+
# It refused authorizations the owner had in fact given: a guardrail sentence
|
|
492
|
+
# inside an authorization ("never merge empty PRs") read as a withdrawal and
|
|
493
|
+
# erased the ledger, and an answer given as an option number matched no
|
|
494
|
+
# authorizing pattern at all. `git-authorization` above still RECORDS what a
|
|
495
|
+
# turn authorized — `evidence_independence` reads its ledger as a per-turn
|
|
496
|
+
# stamp — and the command parser survives as `hooks/git_command_classifier.ts`
|
|
497
|
+
# for `block_no_verify` and `conformance_scan`. Nothing enforces git
|
|
498
|
+
# authorization any more; `non-destructive-by-default` is model-carried here.
|
|
485
499
|
# Evaluator independence. Gates EVALUATION dispatches only. Two branches with
|
|
486
500
|
# DIFFERENT severities, per the tier rule in
|
|
487
501
|
# docs/contracts/hook-architecture-v1.md (§ What a concern may block on):
|
|
@@ -1166,16 +1180,16 @@ platforms:
|
|
|
1166
1180
|
session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register]
|
|
1167
1181
|
session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
|
|
1168
1182
|
stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
|
|
1169
|
-
pre_tool_use: [block-no-verify,
|
|
1170
|
-
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
|
|
1183
|
+
pre_tool_use: [block-no-verify, evidence-independence, block-kernel-rule-writes, block-config-weakening, block-speaking-inbox-dir, rtk-wrap, design-slop, ui-route-nudge, code-graph-nudge, ship-diff-volume, reread-guard]
|
|
1184
|
+
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
|
|
1171
1185
|
|
|
1172
1186
|
claude:
|
|
1173
1187
|
session_start: [chat-history, hot-context, handoff-context, session-canary, council-availability, telemetry-disclosure, first-run-gate, onboarding-gate, verify-before-complete, minimal-safe-diff, profile-staleness, wrapper-freshness, surface-probe, session-register, journal-record]
|
|
1174
1188
|
session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush, journal-record]
|
|
1175
1189
|
stop: [chat-history, hot-context, verify-before-complete, team-review-gate, end-review-nudge, turn-end-gate, self-repair, session-register, session-eol, interruption-ledger, roadmap-progress, design-pass-stop, suggestion-capture, journal-record, run-continuation]
|
|
1176
1190
|
user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, delegation-nudge, skill-route, git-authorization, session-canary, self-repair, session-register, rule-inject, suggestion-capture, journal-record]
|
|
1177
|
-
pre_tool_use: [block-no-verify,
|
|
1178
|
-
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, language-mirror, design-pass, journal-record]
|
|
1191
|
+
pre_tool_use: [block-no-verify, evidence-independence, block-kernel-rule-writes, block-config-weakening, block-speaking-inbox-dir, rtk-wrap, design-slop, ui-route-nudge, code-graph-nudge, ship-diff-volume, reread-guard, spawn-guard-shadow, source-first-gate, rule-inject]
|
|
1192
|
+
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, language-mirror, design-pass, journal-record]
|
|
1179
1193
|
# `language-mirror` — round-5 § 6.1. `pre_compact` sets a pin-lost marker;
|
|
1180
1194
|
# the `post_tool_use` entry above re-emits the pin exactly once while that
|
|
1181
1195
|
# marker is set, then clears it. One extra injection per compaction EVENT —
|
|
@@ -1228,8 +1242,8 @@ platforms:
|
|
|
1228
1242
|
# still costs the dispatch, and its entire output is thrown away.
|
|
1229
1243
|
stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
|
|
1230
1244
|
user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
|
|
1231
|
-
pre_tool_use: [block-no-verify,
|
|
1232
|
-
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
|
|
1245
|
+
pre_tool_use: [block-no-verify, evidence-independence, block-kernel-rule-writes, block-config-weakening, block-speaking-inbox-dir, rtk-wrap, design-slop, ui-route-nudge, code-graph-nudge, ship-diff-volume, reread-guard, spawn-guard-shadow, source-first-gate]
|
|
1246
|
+
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
|
|
1233
1247
|
# subagent-ledger IS bound here, unlike the two nudges above, and the
|
|
1234
1248
|
# difference is the delivery channel rather than the platform: the nudges
|
|
1235
1249
|
# depend on stdout reaching the model, which this trampoline discards by
|
|
@@ -1252,7 +1266,7 @@ platforms:
|
|
|
1252
1266
|
session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
|
|
1253
1267
|
stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
|
|
1254
1268
|
user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
|
|
1255
|
-
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
|
|
1269
|
+
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
|
|
1256
1270
|
|
|
1257
1271
|
# Phase 7.6 — Cline. Hooks live under `.clinerules/hooks/<HookName>`
|
|
1258
1272
|
# (project, no file extension, must be executable per Cline docs) or
|
|
@@ -1267,7 +1281,7 @@ platforms:
|
|
|
1267
1281
|
session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
|
|
1268
1282
|
stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
|
|
1269
1283
|
user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
|
|
1270
|
-
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
|
|
1284
|
+
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
|
|
1271
1285
|
|
|
1272
1286
|
# Phase 7.7 — Windsurf (Cascade). Hooks live at `.windsurf/hooks.json`
|
|
1273
1287
|
# (project) or `~/.codeium/windsurf/hooks.json` (user). Cascade has
|
|
@@ -1303,7 +1317,7 @@ platforms:
|
|
|
1303
1317
|
session_end: [chat-history, memory-learn, session-register, roadmap-progress, telemetry-flush]
|
|
1304
1318
|
stop: [chat-history, hot-context, verify-before-complete, self-repair, session-register, roadmap-progress, design-pass-stop]
|
|
1305
1319
|
user_prompt_submit: [chat-history, verify-before-complete, minimal-safe-diff, language-mirror, git-authorization, session-canary, self-repair, session-register]
|
|
1306
|
-
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
|
|
1320
|
+
post_tool_use: [chat-history, roadmap-progress, context-hygiene, verify-before-complete, minimal-safe-diff, injection-scan, pr-url-reminder, push-settle, orchestration-record, telemetry-usage, tool-result-bytes, edit-shape, comment-discipline, design-pass]
|
|
1307
1321
|
|
|
1308
1322
|
# Phase 7.9 — Copilot has no hook surface. Concerns route through
|
|
1309
1323
|
# rule-only fallback; the dispatcher silently no-ops on --platform copilot.
|
|
@@ -34,7 +34,7 @@ import * as fs from 'node:fs';
|
|
|
34
34
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
35
35
|
import * as path from 'node:path';
|
|
36
36
|
import { readHookStdin } from './hook_stdin.js';
|
|
37
|
-
import { substitutionPayloads } from './
|
|
37
|
+
import { substitutionPayloads } from './git_command_classifier.js';
|
|
38
38
|
|
|
39
39
|
const _HERE = fileURLToPath(import.meta.url);
|
|
40
40
|
|
|
@@ -400,7 +400,7 @@ function _is_blocked(git_tokens: string[]): [boolean, string] {
|
|
|
400
400
|
* genuinely unparseable command that DOES invoke git. So the test moves from
|
|
401
401
|
* "the string contains git" to "some command position is git", with heredoc
|
|
402
402
|
* bodies removed first — the same data-not-command distinction
|
|
403
|
-
* `
|
|
403
|
+
* `git_command_classifier` already makes.
|
|
404
404
|
*
|
|
405
405
|
* Deliberately regex-shaped rather than tokenised: shlex has already failed by
|
|
406
406
|
* the time this runs, so no reliable token stream exists. It therefore stays
|
|
@@ -450,7 +450,7 @@ export function _looks_like_git_invocation(cmd: string, depth = 0): boolean {
|
|
|
450
450
|
* `_git_base` never sees git. The more parseable the command, the less it was
|
|
451
451
|
* protected. Classification inside the payload is by command position, so a
|
|
452
452
|
* substitution that INVOKES git is checked and one that merely names it in an
|
|
453
|
-
* argument is not — matching what `
|
|
453
|
+
* argument is not — matching what `git_command_classifier` does one level up.
|
|
454
454
|
*
|
|
455
455
|
* Heredoc bodies are removed before extraction: a backtick or `$(` inside a
|
|
456
456
|
* commit message being written to a file is data, and feeding it back through
|
|
@@ -41,6 +41,7 @@ import { main as wrapperFreshnessMain } from '../wrapper_freshness_hook.js';
|
|
|
41
41
|
import { main as surfaceProbeMain } from '../surface_probe_hook.js';
|
|
42
42
|
import { main as teamReviewGateMain } from '../team_review_gate_hook.js';
|
|
43
43
|
import { main as prUrlReminderMain } from '../pr_url_reminder_hook.js';
|
|
44
|
+
import { main as pushSettleMain } from './push_settle_hook.js';
|
|
44
45
|
import { main as sessionCanaryMain } from '../session_canary_hook.js';
|
|
45
46
|
import { main as councilAvailabilityMain } from '../council_availability_hook.js';
|
|
46
47
|
import { main as telemetryDisclosureMain } from '../telemetry_disclosure_hook.js';
|
|
@@ -48,7 +49,6 @@ import { main as selfRepairMain } from '../self_repair_hook.js';
|
|
|
48
49
|
import { main as sessionRegisterMain } from '../session_register_hook.js';
|
|
49
50
|
import { main as languageMirrorMain } from '../language_mirror_hook.js';
|
|
50
51
|
import { main as gitAuthorizationMain } from '../git_authorization_hook.js';
|
|
51
|
-
import { main as blockUnauthorizedGitMain } from './block_unauthorized_git.js';
|
|
52
52
|
import { main as evidenceIndependenceMain } from './evidence_independence.js';
|
|
53
53
|
import { main as blockNoVerifyMain } from './block_no_verify.js';
|
|
54
54
|
import { main as blockKernelRuleWritesMain } from './block_kernel_rule_writes.js';
|
|
@@ -102,6 +102,7 @@ export const CONCERN_REGISTRY: Readonly<Record<string, ConcernMain>> = {
|
|
|
102
102
|
'src/scripts/surface_probe_hook.ts': surfaceProbeMain as ConcernMain,
|
|
103
103
|
'src/scripts/team_review_gate_hook.ts': teamReviewGateMain as ConcernMain,
|
|
104
104
|
'src/scripts/pr_url_reminder_hook.ts': prUrlReminderMain as ConcernMain,
|
|
105
|
+
'src/scripts/hooks/push_settle_hook.ts': pushSettleMain as ConcernMain,
|
|
105
106
|
'src/scripts/session_canary_hook.ts': sessionCanaryMain as ConcernMain,
|
|
106
107
|
'src/scripts/council_availability_hook.ts': councilAvailabilityMain as ConcernMain,
|
|
107
108
|
'src/scripts/telemetry_disclosure_hook.ts': telemetryDisclosureMain as ConcernMain,
|
|
@@ -109,7 +110,6 @@ export const CONCERN_REGISTRY: Readonly<Record<string, ConcernMain>> = {
|
|
|
109
110
|
'src/scripts/session_register_hook.ts': sessionRegisterMain as ConcernMain,
|
|
110
111
|
'src/scripts/language_mirror_hook.ts': languageMirrorMain as ConcernMain,
|
|
111
112
|
'src/scripts/git_authorization_hook.ts': gitAuthorizationMain as ConcernMain,
|
|
112
|
-
'src/scripts/hooks/block_unauthorized_git.ts': blockUnauthorizedGitMain as ConcernMain,
|
|
113
113
|
'src/scripts/hooks/evidence_independence.ts': evidenceIndependenceMain as ConcernMain,
|
|
114
114
|
'src/scripts/hooks/block_no_verify.ts': blockNoVerifyMain as ConcernMain,
|
|
115
115
|
'src/scripts/hooks/block_kernel_rule_writes.ts': blockKernelRuleWritesMain as ConcernMain,
|
|
@@ -365,8 +365,21 @@ export function run(stdin_text: string, options: { consumer_root: string }): num
|
|
|
365
365
|
});
|
|
366
366
|
try {
|
|
367
367
|
atomic_write_json(target, state);
|
|
368
|
-
} catch {
|
|
369
|
-
/*
|
|
368
|
+
} catch (err) {
|
|
369
|
+
/* Unlike its two siblings in `git_authorization_hook`, this one fails
|
|
370
|
+
OPEN, which is why it gets a diagnostic rather than a shrug. The turn's
|
|
371
|
+
evaluation count lives only in this file: a failed write leaves
|
|
372
|
+
`evaluations` one short, so the NEXT self-commissioned evaluation in the
|
|
373
|
+
same turn reads `priorEvaluations === 0` and the verdict-shopping warn
|
|
374
|
+
does not fire. The item-1 pre-loaded-verdict BLOCK is unaffected — it
|
|
375
|
+
reads the prompt, not this state — so the degradation is bounded to the
|
|
376
|
+
advisory half. Silent was the wrong call for a guard that loses a check
|
|
377
|
+
when it fails. */
|
|
378
|
+
process.stderr.write(
|
|
379
|
+
`evidence-independence: evaluation-count write failed (${_errText(err)}) — ` +
|
|
380
|
+
"this turn's count did NOT advance, so a second self-scoped evaluation " +
|
|
381
|
+
"will not be warned about. The pre-loaded-verdict block is unaffected.\n",
|
|
382
|
+
);
|
|
370
383
|
}
|
|
371
384
|
}
|
|
372
385
|
|
|
@@ -379,6 +392,12 @@ export function run(stdin_text: string, options: { consumer_root: string }): num
|
|
|
379
392
|
return decision.exit;
|
|
380
393
|
}
|
|
381
394
|
|
|
395
|
+
/** One-line, bounded rendering of a caught value for a stderr diagnostic. */
|
|
396
|
+
function _errText(err: unknown): string {
|
|
397
|
+
const t = err instanceof Error ? err.message : String(err);
|
|
398
|
+
return t.replace(/\s+/g, " ").trim().slice(0, 200);
|
|
399
|
+
}
|
|
400
|
+
|
|
382
401
|
export function main(argv?: string[]): number {
|
|
383
402
|
const args = argv ?? process.argv.slice(2);
|
|
384
403
|
let consumer_root = process.cwd();
|