@cleocode/core 2026.10.6 → 2026.10.7-rc.ci.674
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/dist/build-provenance.json +2 -2
- package/dist/cloud/http.d.ts +8 -0
- package/dist/cloud/http.d.ts.map +1 -1
- package/dist/cloud/http.js +11 -0
- package/dist/cloud/http.js.map +1 -1
- package/dist/cloud/journal.d.ts +6 -0
- package/dist/cloud/journal.d.ts.map +1 -1
- package/dist/cloud/journal.js +1 -1
- package/dist/cloud/journal.js.map +1 -1
- package/dist/cloud/nexus-cloud-status.d.ts.map +1 -1
- package/dist/cloud/nexus-cloud-status.js +3 -1
- package/dist/cloud/nexus-cloud-status.js.map +1 -1
- package/dist/cloud/nexus-vault.d.ts +86 -1
- package/dist/cloud/nexus-vault.d.ts.map +1 -1
- package/dist/cloud/nexus-vault.js +875 -98
- package/dist/cloud/nexus-vault.js.map +1 -1
- package/dist/docs/doctor.d.ts +183 -0
- package/dist/docs/doctor.d.ts.map +1 -0
- package/dist/docs/doctor.js +537 -0
- package/dist/docs/doctor.js.map +1 -0
- package/dist/doctor/system-health.d.ts +189 -0
- package/dist/doctor/system-health.d.ts.map +1 -0
- package/dist/doctor/system-health.js +783 -0
- package/dist/doctor/system-health.js.map +1 -0
- package/dist/git/hooks-install.d.ts +17 -34
- package/dist/git/hooks-install.d.ts.map +1 -1
- package/dist/git/hooks-install.js +173 -70
- package/dist/git/hooks-install.js.map +1 -1
- package/dist/harness/ask-enforce.d.ts +43 -0
- package/dist/harness/ask-enforce.d.ts.map +1 -0
- package/dist/harness/ask-enforce.js +165 -0
- package/dist/harness/ask-enforce.js.map +1 -0
- package/dist/hooks.d.ts +8 -30
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +36 -116
- package/dist/hooks.js.map +1 -1
- package/dist/init.d.ts +2 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +5 -14
- package/dist/init.js.map +1 -1
- package/dist/injection.d.ts +2 -2
- package/dist/injection.d.ts.map +1 -1
- package/dist/injection.js +108 -10
- package/dist/injection.js.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -1
- package/dist/internal.js.map +1 -1
- package/dist/issue/create.d.ts +4 -0
- package/dist/issue/create.d.ts.map +1 -1
- package/dist/issue/create.js +12 -0
- package/dist/issue/create.js.map +1 -1
- package/dist/issue/index.d.ts +1 -1
- package/dist/issue/index.d.ts.map +1 -1
- package/dist/issue/index.js +1 -1
- package/dist/issue/index.js.map +1 -1
- package/dist/orchestrate/spawn-ops.d.ts.map +1 -1
- package/dist/orchestrate/spawn-ops.js +8 -2
- package/dist/orchestrate/spawn-ops.js.map +1 -1
- package/dist/orchestration/lean-change.d.ts +15 -0
- package/dist/orchestration/lean-change.d.ts.map +1 -0
- package/dist/orchestration/lean-change.js +17 -0
- package/dist/orchestration/lean-change.js.map +1 -0
- package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
- package/dist/orchestration/spawn-prompt.js +6 -4
- package/dist/orchestration/spawn-prompt.js.map +1 -1
- package/dist/release/ci-evidence.d.ts +59 -0
- package/dist/release/ci-evidence.d.ts.map +1 -1
- package/dist/release/ci-evidence.js +150 -5
- package/dist/release/ci-evidence.js.map +1 -1
- package/dist/release/plan.d.ts.map +1 -1
- package/dist/release/plan.js +11 -2
- package/dist/release/plan.js.map +1 -1
- package/dist/release/pr-evidence.d.ts +15 -0
- package/dist/release/pr-evidence.d.ts.map +1 -1
- package/dist/release/pr-evidence.js +42 -1
- package/dist/release/pr-evidence.js.map +1 -1
- package/dist/release/reconcile.js +2 -2
- package/dist/release/reconcile.js.map +1 -1
- package/dist/release/verify-provenance.js +2 -2
- package/dist/release/verify-provenance.js.map +1 -1
- package/dist/resources/admission-ledger.d.ts +8 -0
- package/dist/resources/admission-ledger.d.ts.map +1 -1
- package/dist/resources/admission-ledger.js +5 -0
- package/dist/resources/admission-ledger.js.map +1 -1
- package/dist/resources/claim-keepalive.d.ts +34 -0
- package/dist/resources/claim-keepalive.d.ts.map +1 -0
- package/dist/resources/claim-keepalive.js +49 -0
- package/dist/resources/claim-keepalive.js.map +1 -0
- package/dist/resources/governor.d.ts.map +1 -1
- package/dist/resources/governor.js +3 -0
- package/dist/resources/governor.js.map +1 -1
- package/dist/scaffold/ensure-config.js +1 -1
- package/dist/scaffold/ensure-config.js.map +1 -1
- package/dist/store/attachment-store.d.ts.map +1 -1
- package/dist/store/attachment-store.js +2 -1
- package/dist/store/attachment-store.js.map +1 -1
- package/dist/store/restore-marker.d.ts +50 -7
- package/dist/store/restore-marker.d.ts.map +1 -1
- package/dist/store/restore-marker.js +77 -25
- package/dist/store/restore-marker.js.map +1 -1
- package/dist/store/row-identity-registry.d.ts +6 -4
- package/dist/store/row-identity-registry.d.ts.map +1 -1
- package/dist/store/row-identity-registry.js +156 -33
- package/dist/store/row-identity-registry.js.map +1 -1
- package/dist/store/schema/cleo-project/provenance-orphans.d.ts +16 -0
- package/dist/store/schema/cleo-project/provenance-orphans.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/provenance-orphans.js +4 -1
- package/dist/store/schema/cleo-project/provenance-orphans.js.map +1 -1
- package/dist/store/schema/cleo-shared/brain.d.ts +240 -0
- package/dist/store/schema/cleo-shared/brain.d.ts.map +1 -1
- package/dist/store/schema/cleo-shared/brain.js +69 -0
- package/dist/store/schema/cleo-shared/brain.js.map +1 -1
- package/dist/store/schema/tasks.d.ts +1 -1
- package/dist/store/schema/tasks.d.ts.map +1 -1
- package/dist/store/schema/tasks.js +9 -1
- package/dist/store/schema/tasks.js.map +1 -1
- package/dist/store/sync/apply/applier.d.ts.map +1 -1
- package/dist/store/sync/apply/applier.js +85 -3
- package/dist/store/sync/apply/applier.js.map +1 -1
- package/dist/store/sync/apply/parent-delete.d.ts.map +1 -1
- package/dist/store/sync/apply/parent-delete.js +4 -0
- package/dist/store/sync/apply/parent-delete.js.map +1 -1
- package/dist/store/sync/capture.d.ts +8 -0
- package/dist/store/sync/capture.d.ts.map +1 -1
- package/dist/store/sync/capture.js +20 -0
- package/dist/store/sync/capture.js.map +1 -1
- package/dist/store/sync/clock-store.d.ts +21 -0
- package/dist/store/sync/clock-store.d.ts.map +1 -1
- package/dist/store/sync/clock-store.js +47 -0
- package/dist/store/sync/clock-store.js.map +1 -1
- package/dist/store/sync/conflicts.d.ts +13 -0
- package/dist/store/sync/conflicts.d.ts.map +1 -1
- package/dist/store/sync/conflicts.js +22 -0
- package/dist/store/sync/conflicts.js.map +1 -1
- package/dist/store/sync/genesis.d.ts +113 -12
- package/dist/store/sync/genesis.d.ts.map +1 -1
- package/dist/store/sync/genesis.js +325 -27
- package/dist/store/sync/genesis.js.map +1 -1
- package/dist/store/sync/merge/types.d.ts +8 -2
- package/dist/store/sync/merge/types.d.ts.map +1 -1
- package/dist/store/sync/pull.d.ts +192 -0
- package/dist/store/sync/pull.d.ts.map +1 -0
- package/dist/store/sync/pull.js +429 -0
- package/dist/store/sync/pull.js.map +1 -0
- package/dist/store/sync/push.d.ts +110 -0
- package/dist/store/sync/push.d.ts.map +1 -0
- package/dist/store/sync/push.js +172 -0
- package/dist/store/sync/push.js.map +1 -0
- package/dist/store/sync/replay-pin.d.ts +70 -0
- package/dist/store/sync/replay-pin.d.ts.map +1 -0
- package/dist/store/sync/replay-pin.js +172 -0
- package/dist/store/sync/replay-pin.js.map +1 -0
- package/dist/store/sync/sealer.d.ts.map +1 -1
- package/dist/store/sync/sealer.js +6 -2
- package/dist/store/sync/sealer.js.map +1 -1
- package/dist/store/sync/timestamp-canon.d.ts.map +1 -1
- package/dist/store/sync/timestamp-canon.js +15 -0
- package/dist/store/sync/timestamp-canon.js.map +1 -1
- package/dist/store/table-classification.d.ts.map +1 -1
- package/dist/store/table-classification.js +51 -15
- package/dist/store/table-classification.js.map +1 -1
- package/dist/store/tasks-schema.d.ts +1 -1
- package/dist/store/tasks-schema.d.ts.map +1 -1
- package/dist/store/tasks-schema.js +1 -1
- package/dist/store/tasks-schema.js.map +1 -1
- package/dist/store/twin-collapse.d.ts.map +1 -1
- package/dist/store/twin-collapse.js +5 -0
- package/dist/store/twin-collapse.js.map +1 -1
- package/dist/store/vault-manifest.d.ts +7 -0
- package/dist/store/vault-manifest.d.ts.map +1 -1
- package/dist/store/vault-manifest.js +4 -0
- package/dist/store/vault-manifest.js.map +1 -1
- package/dist/tasks/ac-table.d.ts +17 -0
- package/dist/tasks/ac-table.d.ts.map +1 -1
- package/dist/tasks/ac-table.js +49 -0
- package/dist/tasks/ac-table.js.map +1 -1
- package/dist/tasks/affected-scope.d.ts +52 -3
- package/dist/tasks/affected-scope.d.ts.map +1 -1
- package/dist/tasks/affected-scope.js +94 -3
- package/dist/tasks/affected-scope.js.map +1 -1
- package/dist/tasks/change-set.d.ts.map +1 -1
- package/dist/tasks/change-set.js +9 -5
- package/dist/tasks/change-set.js.map +1 -1
- package/dist/tasks/complete-ci.d.ts +2 -0
- package/dist/tasks/complete-ci.d.ts.map +1 -1
- package/dist/tasks/complete-ci.js +26 -7
- package/dist/tasks/complete-ci.js.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +10 -0
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/done-plan.d.ts.map +1 -1
- package/dist/tasks/done-plan.js +63 -6
- package/dist/tasks/done-plan.js.map +1 -1
- package/dist/tasks/evidence.d.ts +3 -0
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js +106 -2
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/tasks/gate-preview.d.ts +19 -1
- package/dist/tasks/gate-preview.d.ts.map +1 -1
- package/dist/tasks/gate-preview.js +44 -2
- package/dist/tasks/gate-preview.js.map +1 -1
- package/dist/tasks/gate-runner.d.ts +16 -0
- package/dist/tasks/gate-runner.d.ts.map +1 -1
- package/dist/tasks/gate-runner.js +25 -2
- package/dist/tasks/gate-runner.js.map +1 -1
- package/dist/tasks/qa-run-binding.d.ts +88 -0
- package/dist/tasks/qa-run-binding.d.ts.map +1 -0
- package/dist/tasks/qa-run-binding.js +188 -0
- package/dist/tasks/qa-run-binding.js.map +1 -0
- package/dist/tasks/req.d.ts +50 -0
- package/dist/tasks/req.d.ts.map +1 -1
- package/dist/tasks/req.js +99 -1
- package/dist/tasks/req.js.map +1 -1
- package/dist/tasks/test-run-binding.d.ts +29 -0
- package/dist/tasks/test-run-binding.d.ts.map +1 -1
- package/dist/tasks/test-run-binding.js +47 -23
- package/dist/tasks/test-run-binding.js.map +1 -1
- package/dist/tasks/tool-resolver.d.ts +9 -0
- package/dist/tasks/tool-resolver.d.ts.map +1 -1
- package/dist/tasks/tool-resolver.js +14 -3
- package/dist/tasks/tool-resolver.js.map +1 -1
- package/dist/tasks/tool-semaphore.d.ts.map +1 -1
- package/dist/tasks/tool-semaphore.js +3 -0
- package/dist/tasks/tool-semaphore.js.map +1 -1
- package/dist/upgrade.d.ts.map +1 -1
- package/dist/upgrade.js +10 -1
- package/dist/upgrade.js.map +1 -1
- package/dist/validation/engine-ops.d.ts.map +1 -1
- package/dist/validation/engine-ops.js +14 -3
- package/dist/validation/engine-ops.js.map +1 -1
- package/migrations/drizzle-cleo-global/20261010130000_t12895-brain-natural-uids/migration.sql +28 -0
- package/migrations/drizzle-cleo-global/20261010140000_t12896-brain-autoinc-uids/migration.sql +54 -0
- package/migrations/drizzle-cleo-project/20261010130000_t12895-brain-natural-uids/migration.sql +36 -0
- package/migrations/drizzle-cleo-project/20261010140000_t12896-brain-autoinc-uids/migration.sql +58 -0
- package/migrations/sync-journal/20261008120000_t12343-pull-cursor/migration.sql +28 -0
- package/migrations/sync-journal/20261009120000_t13318-seen-floor/migration.sql +41 -0
- package/package.json +18 -18
- package/templates/CLEO-INJECTION.md +5 -3
- package/templates/CLEO-REFERENCE.md +1 -1
- package/templates/git-hooks/legacy-hashes.json +20 -0
- package/templates/git-hooks/pre-commit +1 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ask-enforce classifier: does an ended turn ask the owner something in prose?
|
|
3
|
+
*
|
|
4
|
+
* Pure and deterministic, run by the `cleo hook ask-enforce` Stop hook on every
|
|
5
|
+
* turn end, so it is regex-only with no I/O and no model call. It is tuned
|
|
6
|
+
* against false positives: anything that is not the agent's own closing prose
|
|
7
|
+
* (code, quotes, headings, tables, URLs, a research report's open-questions
|
|
8
|
+
* list) is removed first, only the reply's tail is read, and a question
|
|
9
|
+
* attributed to someone else or answered on the spot does not count. Every
|
|
10
|
+
* doubt resolves to `allow`; a corpus test pins the false-positive rate at 0.
|
|
11
|
+
*
|
|
12
|
+
* Design: `cleo docs fetch t13420-ask-enforce-stop-hook-design`.
|
|
13
|
+
*
|
|
14
|
+
* @task T13420
|
|
15
|
+
* @epic T13418
|
|
16
|
+
*/
|
|
17
|
+
/** Longest excerpt quoted back to the agent in the block reason. */
|
|
18
|
+
const EXCERPT_MAX = 160;
|
|
19
|
+
/** The tail read is the last two paragraphs, or this many characters if longer. */
|
|
20
|
+
const TAIL_MIN_CHARS = 600;
|
|
21
|
+
/**
|
|
22
|
+
* A question addressed to the reader: second person, or asking leave to act.
|
|
23
|
+
* Bare verbs (`proceed`, `confirm`) do not count: "Did CI confirm the fix?" is not an ask.
|
|
24
|
+
*/
|
|
25
|
+
const READER_DIRECTED = /\b(you|your|yours|should i|shall i|can i|may i|do i|should we|shall we|want me|would you|could you|which (?:option|approach|one|path|way|of these)|ok(?:ay)? (?:to|if|with)|is (?:it|that) ok(?:ay)?|good to go)\b/i;
|
|
26
|
+
/** A question reported, not asked ("team-lead asked whether …?"). */
|
|
27
|
+
const ATTRIBUTED = /\b(asked|asks|wondered|wonders|wants to know|question (?:was|is) whether)\b/i;
|
|
28
|
+
/** An immediate answer that makes the question before it rhetorical. */
|
|
29
|
+
const SELF_ANSWER = /^(because|since|it(?:'s| is| was)?|that(?:'s| is)?|this|the answer|answer:|short answer|yes|no|nope|not|none|never)\b/i;
|
|
30
|
+
/** A question that opens rhetorically ("Did you know …?", "Wondering if …?"). */
|
|
31
|
+
const RHETORICAL_OPENER = /^(?:did you know|ever wonder(?:ed)?|wondering (?:if|whether|why))\b/i;
|
|
32
|
+
/** Requests for an owner choice or approval written without a question mark. */
|
|
33
|
+
const WRITTEN_DECISION = [
|
|
34
|
+
/\b(?:let me know|tell me) (?:which|whether|if|what|how)\b/i,
|
|
35
|
+
/\bplease (?:confirm|choose|pick|approve|decide|select|advise)\b/i,
|
|
36
|
+
/\b(?:awaiting|waiting (?:for|on)) your (?:approval|decision|go-ahead|confirmation|input|call|answer)\b/i,
|
|
37
|
+
/\byour call\b/i,
|
|
38
|
+
/\b(?:decision needed|needs? (?:a|your) decision|needs? your (?:approval|input|go-ahead|sign-off))\b/i,
|
|
39
|
+
/\breply with (?:a|b|yes|no|1|2|the option)\b/i,
|
|
40
|
+
];
|
|
41
|
+
/** A written request reported from someone else ("the owner said please confirm"). */
|
|
42
|
+
const REPORTED_SPEECH = /\b(said|wrote|told|requested|asked)\b/i;
|
|
43
|
+
/** A heading that introduces task-output questions, not questions to the reader. */
|
|
44
|
+
const OPEN_QUESTIONS_HEADING = /^#{1,6}\s+(?:open questions|unresolved questions|questions for (?:later|follow-?up)|future questions|faq)\b/i;
|
|
45
|
+
/**
|
|
46
|
+
* Remove everything that is not the agent's own prose: fenced and inline code,
|
|
47
|
+
* blockquotes, open-questions sections, headings, table rows, URLs and quoted
|
|
48
|
+
* spans.
|
|
49
|
+
*/
|
|
50
|
+
function neutralise(text) {
|
|
51
|
+
const withoutFences = text.replace(/^(```|~~~)[^\n]*\n[\s\S]*?(?:^\1[^\n]*$|(?![\s\S]))/gm, '');
|
|
52
|
+
const kept = [];
|
|
53
|
+
let inOpenQuestions = false;
|
|
54
|
+
for (const line of withoutFences.split('\n')) {
|
|
55
|
+
if (/^#{1,6}\s/.test(line)) {
|
|
56
|
+
inOpenQuestions = OPEN_QUESTIONS_HEADING.test(line);
|
|
57
|
+
kept.push('');
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (inOpenQuestions)
|
|
61
|
+
continue;
|
|
62
|
+
if (/^\s*>/.test(line) || /^\s*\|/.test(line)) {
|
|
63
|
+
kept.push('');
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
kept.push(line);
|
|
67
|
+
}
|
|
68
|
+
return kept
|
|
69
|
+
.join('\n')
|
|
70
|
+
.replace(/`[^`\n]*`/g, ' ')
|
|
71
|
+
.replace(/https?:\/\/\S+/g, ' ')
|
|
72
|
+
.replace(/"[^"\n]{0,300}"|“[^”\n]{0,300}”/g, ' ');
|
|
73
|
+
}
|
|
74
|
+
/** The reply's tail: its last two paragraphs, or its last {@link TAIL_MIN_CHARS} characters if longer. */
|
|
75
|
+
function tailParagraphs(text) {
|
|
76
|
+
const paragraphs = text
|
|
77
|
+
.split(/\n\s*\n/)
|
|
78
|
+
.map((p) => p.trim())
|
|
79
|
+
.filter((p) => p.length > 0);
|
|
80
|
+
const tail = paragraphs.slice(-2);
|
|
81
|
+
let size = tail.reduce((n, p) => n + p.length, 0);
|
|
82
|
+
for (let i = paragraphs.length - 3; i >= 0 && size < TAIL_MIN_CHARS; i--) {
|
|
83
|
+
const p = paragraphs[i];
|
|
84
|
+
tail.unshift(p);
|
|
85
|
+
size += p.length;
|
|
86
|
+
}
|
|
87
|
+
return tail;
|
|
88
|
+
}
|
|
89
|
+
/** Split a paragraph into sentences; list items and lines count as their own. */
|
|
90
|
+
function sentences(paragraph) {
|
|
91
|
+
return paragraph
|
|
92
|
+
.split(/\n+/)
|
|
93
|
+
.flatMap((line) => line.replace(/^\s*(?:[-*+]|\d+[.)])\s+/, '').split(/(?<=[.?!])\s+/))
|
|
94
|
+
.map((s) => s.replace(/[*_]+/g, '').trim())
|
|
95
|
+
.filter((s) => s.length > 0);
|
|
96
|
+
}
|
|
97
|
+
function excerpt(sentence) {
|
|
98
|
+
return sentence.length <= EXCERPT_MAX ? sentence : `${sentence.slice(0, EXCERPT_MAX - 1)}…`;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Classify one ended turn.
|
|
102
|
+
*
|
|
103
|
+
* @param input - The final reply, the turn's tool calls and the ask-tool names.
|
|
104
|
+
* @returns `block` when the reply's tail asks the owner something in prose and
|
|
105
|
+
* the turn made no ask-tool call; `allow` otherwise, including on any doubt.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* ```typescript
|
|
109
|
+
* classifyOwnerAsk({
|
|
110
|
+
* lastAssistantText: 'Tests pass. Should I merge it?',
|
|
111
|
+
* turnToolCalls: [],
|
|
112
|
+
* askToolNames: ['AskUserQuestion'],
|
|
113
|
+
* }).verdict; // "block"
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export function classifyOwnerAsk(input) {
|
|
117
|
+
const text = input.lastAssistantText?.trim();
|
|
118
|
+
if (!text)
|
|
119
|
+
return { verdict: 'allow', signal: 'no-text', excerpt: null };
|
|
120
|
+
const askNames = new Set(input.askToolNames);
|
|
121
|
+
if (input.turnToolCalls.some((name) => askNames.has(name))) {
|
|
122
|
+
return { verdict: 'allow', signal: 'asked', excerpt: null };
|
|
123
|
+
}
|
|
124
|
+
if (input.stopHookActive === true || (input.blocksThisTurn ?? 0) >= 1) {
|
|
125
|
+
return { verdict: 'allow', signal: 'loop-guard', excerpt: null };
|
|
126
|
+
}
|
|
127
|
+
if (/\bhitl\.request\b/.test(text) && /"question"\s*:/.test(text)) {
|
|
128
|
+
return { verdict: 'allow', signal: 'hitl-request', excerpt: null };
|
|
129
|
+
}
|
|
130
|
+
for (const paragraph of tailParagraphs(neutralise(text))) {
|
|
131
|
+
const list = sentences(paragraph);
|
|
132
|
+
for (let i = 0; i < list.length; i++) {
|
|
133
|
+
const sentence = list[i];
|
|
134
|
+
if (/\?["')\]]*$/.test(sentence)) {
|
|
135
|
+
if (!READER_DIRECTED.test(sentence) || ATTRIBUTED.test(sentence))
|
|
136
|
+
continue;
|
|
137
|
+
if (RHETORICAL_OPENER.test(sentence))
|
|
138
|
+
continue;
|
|
139
|
+
const next = list[i + 1];
|
|
140
|
+
if (next !== undefined && !next.endsWith('?') && SELF_ANSWER.test(next))
|
|
141
|
+
continue;
|
|
142
|
+
return { verdict: 'block', signal: 'prose-question', excerpt: excerpt(sentence) };
|
|
143
|
+
}
|
|
144
|
+
if (WRITTEN_DECISION.some((re) => re.test(sentence)) && !REPORTED_SPEECH.test(sentence)) {
|
|
145
|
+
return { verdict: 'block', signal: 'written-decision', excerpt: excerpt(sentence) };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return { verdict: 'allow', signal: 'clean', excerpt: null };
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The block reason the agent reads: re-ask with the harness ask tool.
|
|
153
|
+
*
|
|
154
|
+
* @param verdict - A `block` verdict from {@link classifyOwnerAsk}.
|
|
155
|
+
* @param askToolName - The provider's ask tool, or `null` for the `hitl.request` fallback.
|
|
156
|
+
* @returns One paragraph telling the agent how to re-ask.
|
|
157
|
+
*/
|
|
158
|
+
export function askEnforceReason(verdict, askToolName) {
|
|
159
|
+
const quoted = verdict.excerpt ? ` ("${verdict.excerpt}")` : '';
|
|
160
|
+
const how = askToolName
|
|
161
|
+
? `Re-ask it with the \`${askToolName}\` tool`
|
|
162
|
+
: 'Re-ask it as one LAFS `hitl.request` envelope `{question, options[{label, description}], recommended}`';
|
|
163
|
+
return `CLEO ask-enforce: your reply ends with an owner question or decision in prose${quoted}. ${how}: 2-4 options, recommended first, each with a label and a description of what happens and its trade-offs. Keep the rest of your reply. If the question was rhetorical, restate it without asking.`;
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=ask-enforce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ask-enforce.js","sourceRoot":"","sources":["../../src/harness/ask-enforce.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,36 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
* Git hook management utilities.
|
|
3
|
-
*
|
|
4
|
-
* Extracted from init.ts to enable shared use across init, upgrade, and
|
|
5
|
-
* doctor/health-check workflows.
|
|
6
|
-
*
|
|
7
|
-
* Handles installation, update, and verification of managed git hooks
|
|
8
|
-
* from the package's templates/git-hooks/ directory.
|
|
9
|
-
*/
|
|
1
|
+
import type { GitHookInstallOptions } from '@cleocode/contracts/git-hooks.js';
|
|
10
2
|
import type { HookCheckResult, ScaffoldResult } from '@cleocode/contracts/scaffold-diagnostics';
|
|
11
|
-
export type { HookCheckResult, ScaffoldResult
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
/** Git hooks managed by CLEO. */
|
|
3
|
+
export type { HookCheckResult, ScaffoldResult } from '@cleocode/contracts/scaffold-diagnostics';
|
|
4
|
+
/** Compatibility options; force never permits replacing foreign/customized hooks. */
|
|
5
|
+
export type EnsureGitHooksOptions = GitHookInstallOptions;
|
|
6
|
+
/** Canonical shipped hook set shared with the installer. */
|
|
16
7
|
export declare const MANAGED_HOOKS: readonly ["commit-msg", "pre-commit", "pre-push"];
|
|
8
|
+
/** One shipped Git hook name. */
|
|
17
9
|
export type ManagedHook = (typeof MANAGED_HOOKS)[number];
|
|
18
|
-
/**
|
|
19
|
-
* Install or update managed git hooks from templates/git-hooks/ into .git/hooks/.
|
|
20
|
-
*
|
|
21
|
-
* Handles:
|
|
22
|
-
* - No .git directory (skips gracefully)
|
|
23
|
-
* - No source templates directory (skips gracefully)
|
|
24
|
-
* - Hooks already installed (skips unless force)
|
|
25
|
-
* - Sets executable permissions on installed hooks
|
|
26
|
-
*/
|
|
10
|
+
/** Install all managed hooks through the canonical ownership-aware installer. */
|
|
27
11
|
export declare function ensureGitHooks(projectRoot: string, opts?: EnsureGitHooksOptions): Promise<ScaffoldResult>;
|
|
28
|
-
/**
|
|
29
|
-
* Verify managed hooks are installed and current.
|
|
30
|
-
*
|
|
31
|
-
* Compares installed hooks in .git/hooks/ against source templates in the
|
|
32
|
-
* package's templates/git-hooks/ directory. Returns per-hook status including
|
|
33
|
-
* whether the hook is installed and whether its content matches the source.
|
|
34
|
-
*/
|
|
12
|
+
/** Inspect all hooks at the location Git actually executes, including worktrees. */
|
|
35
13
|
export declare function checkGitHooks(projectRoot: string): Promise<HookCheckResult[]>;
|
|
36
14
|
//# sourceMappingURL=hooks.d.ts.map
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAShG,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAChG,qFAAqF;AACrF,MAAM,MAAM,qBAAqB,GAAG,qBAAqB,CAAC;AAC1D,4DAA4D;AAC5D,eAAO,MAAM,aAAa,mDAAkB,CAAC;AAC7C,iCAAiC;AACjC,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,iFAAiF;AACjF,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,qBAAqB,GAC3B,OAAO,CAAC,cAAc,CAAC,CAwBzB;AAED,oFAAoF;AACpF,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAmBnF"}
|
package/dist/hooks.js
CHANGED
|
@@ -1,136 +1,56 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* Extracted from init.ts to enable shared use across init, upgrade, and
|
|
5
|
-
* doctor/health-check workflows.
|
|
6
|
-
*
|
|
7
|
-
* Handles installation, update, and verification of managed git hooks
|
|
8
|
-
* from the package's templates/git-hooks/ directory.
|
|
9
|
-
*/
|
|
10
|
-
import { existsSync } from 'node:fs';
|
|
11
|
-
import { chmod, copyFile, mkdir, readFile } from 'node:fs/promises';
|
|
1
|
+
/** Shared Git hook management wrappers for init, upgrade and health. */
|
|
2
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
12
3
|
import { join } from 'node:path';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
// ── ensureGitHooks ───────────────────────────────────────────────────
|
|
18
|
-
/**
|
|
19
|
-
* Install or update managed git hooks from templates/git-hooks/ into .git/hooks/.
|
|
20
|
-
*
|
|
21
|
-
* Handles:
|
|
22
|
-
* - No .git directory (skips gracefully)
|
|
23
|
-
* - No source templates directory (skips gracefully)
|
|
24
|
-
* - Hooks already installed (skips unless force)
|
|
25
|
-
* - Sets executable permissions on installed hooks
|
|
26
|
-
*/
|
|
4
|
+
import { CLEO_HOOK_NAMES, defaultTemplatesDir, installCleoHooks, resolveGitDir, resolveHooksDir, } from './git/hooks-install.js';
|
|
5
|
+
/** Canonical shipped hook set shared with the installer. */
|
|
6
|
+
export const MANAGED_HOOKS = CLEO_HOOK_NAMES;
|
|
7
|
+
/** Install all managed hooks through the canonical ownership-aware installer. */
|
|
27
8
|
export async function ensureGitHooks(projectRoot, opts) {
|
|
28
|
-
|
|
29
|
-
const gitHooksDir = join(gitDir, 'hooks');
|
|
30
|
-
if (!existsSync(gitDir)) {
|
|
9
|
+
if (!resolveGitDir(projectRoot))
|
|
31
10
|
return {
|
|
32
11
|
action: 'skipped',
|
|
33
|
-
path:
|
|
34
|
-
details: 'No
|
|
12
|
+
path: projectRoot,
|
|
13
|
+
details: 'No git repository found, skipping git hook installation',
|
|
35
14
|
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
15
|
+
try {
|
|
16
|
+
const result = await installCleoHooks(projectRoot, opts);
|
|
17
|
+
const conflicts = result.skipped
|
|
18
|
+
.map((name) => `${name}: ${result.skipReasons[name]}`)
|
|
19
|
+
.join('; ');
|
|
40
20
|
return {
|
|
41
|
-
action: 'skipped',
|
|
42
|
-
path:
|
|
43
|
-
details:
|
|
21
|
+
action: result.installed.length ? 'created' : 'skipped',
|
|
22
|
+
path: result.hooksDir,
|
|
23
|
+
details: `Installed ${result.installed.length} git hooks${conflicts ? `; ${conflicts}` : ''}`,
|
|
44
24
|
};
|
|
45
25
|
}
|
|
46
|
-
|
|
47
|
-
const force = opts?.force ?? false;
|
|
48
|
-
let installedCount = 0;
|
|
49
|
-
const errors = [];
|
|
50
|
-
for (const hook of MANAGED_HOOKS) {
|
|
51
|
-
const sourcePath = join(sourceDir, hook);
|
|
52
|
-
const destPath = join(gitHooksDir, hook);
|
|
53
|
-
if (!existsSync(sourcePath)) {
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
if (existsSync(destPath) && !force) {
|
|
57
|
-
continue;
|
|
58
|
-
}
|
|
59
|
-
try {
|
|
60
|
-
await copyFile(sourcePath, destPath);
|
|
61
|
-
await chmod(destPath, 0o755);
|
|
62
|
-
installedCount++;
|
|
63
|
-
}
|
|
64
|
-
catch (err) {
|
|
65
|
-
errors.push(`Failed to install git hook ${hook}: ${err instanceof Error ? err.message : String(err)}`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (errors.length > 0) {
|
|
69
|
-
return {
|
|
70
|
-
action: 'repaired',
|
|
71
|
-
path: gitHooksDir,
|
|
72
|
-
details: `Installed ${installedCount} hook(s) with ${errors.length} error(s): ${errors.join('; ')}`,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
if (installedCount === 0) {
|
|
26
|
+
catch (err) {
|
|
76
27
|
return {
|
|
77
28
|
action: 'skipped',
|
|
78
|
-
path:
|
|
79
|
-
details:
|
|
29
|
+
path: projectRoot,
|
|
30
|
+
details: `Git hook installation failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
80
31
|
};
|
|
81
32
|
}
|
|
82
|
-
return {
|
|
83
|
-
action: 'created',
|
|
84
|
-
path: gitHooksDir,
|
|
85
|
-
details: `Installed ${installedCount} git hooks`,
|
|
86
|
-
};
|
|
87
33
|
}
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Verify managed hooks are installed and current.
|
|
91
|
-
*
|
|
92
|
-
* Compares installed hooks in .git/hooks/ against source templates in the
|
|
93
|
-
* package's templates/git-hooks/ directory. Returns per-hook status including
|
|
94
|
-
* whether the hook is installed and whether its content matches the source.
|
|
95
|
-
*/
|
|
34
|
+
/** Inspect all hooks at the location Git actually executes, including worktrees. */
|
|
96
35
|
export async function checkGitHooks(projectRoot) {
|
|
97
|
-
const
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
const
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
current: false,
|
|
108
|
-
sourcePath,
|
|
109
|
-
installedPath,
|
|
110
|
-
};
|
|
111
|
-
if (!existsSync(sourcePath)) {
|
|
112
|
-
// No source template — nothing to compare against
|
|
113
|
-
results.push(result);
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
if (!existsSync(installedPath)) {
|
|
117
|
-
results.push(result);
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
result.installed = true;
|
|
36
|
+
const gitDir = resolveGitDir(projectRoot);
|
|
37
|
+
const hooksDir = gitDir
|
|
38
|
+
? resolveHooksDir(projectRoot, gitDir)
|
|
39
|
+
: join(projectRoot, '.git', 'hooks');
|
|
40
|
+
const templates = defaultTemplatesDir();
|
|
41
|
+
return MANAGED_HOOKS.map((hook) => {
|
|
42
|
+
const sourcePath = join(templates, hook);
|
|
43
|
+
const installedPath = join(hooksDir, hook);
|
|
44
|
+
const installed = existsSync(installedPath);
|
|
45
|
+
let current = false;
|
|
121
46
|
try {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
readFile(installedPath, 'utf-8'),
|
|
125
|
-
]);
|
|
126
|
-
result.current = sourceContent === installedContent;
|
|
47
|
+
current =
|
|
48
|
+
installed && readFileSync(sourcePath, 'utf8') === readFileSync(installedPath, 'utf8');
|
|
127
49
|
}
|
|
128
50
|
catch {
|
|
129
|
-
|
|
130
|
-
result.current = false;
|
|
51
|
+
/* Report unreadable hooks as not current. */
|
|
131
52
|
}
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
return results;
|
|
53
|
+
return { hook, installed, current, sourcePath, installedPath };
|
|
54
|
+
});
|
|
135
55
|
}
|
|
136
56
|
//# sourceMappingURL=hooks.js.map
|
package/dist/hooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,aAAa,EACb,eAAe,GAChB,MAAM,wBAAwB,CAAC;AAKhC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC;AAI7C,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,WAAmB,EACnB,IAA4B;IAE5B,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC;QAC7B,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,yDAAyD;SACnE,CAAC;IACJ,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACzD,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO;aAC7B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;aACrD,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;YACvD,IAAI,EAAE,MAAM,CAAC,QAAQ;YACrB,OAAO,EAAE,aAAa,MAAM,CAAC,SAAS,CAAC,MAAM,aAAa,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;SAC9F,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,IAAI,EAAE,WAAW;YACjB,OAAO,EAAE,iCAAiC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SAC7F,CAAC;IACJ,CAAC;AACH,CAAC;AAED,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB;IACrD,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,MAAM;QACrB,CAAC,CAAC,eAAe,CAAC,WAAW,EAAE,MAAM,CAAC;QACtC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,mBAAmB,EAAE,CAAC;IACxC,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAChC,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACzC,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;QAC5C,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,CAAC;YACH,OAAO;gBACL,SAAS,IAAI,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,KAAK,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAC1F,CAAC;QAAC,MAAM,CAAC;YACP,6CAA6C;QAC/C,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/init.d.ts
CHANGED
|
@@ -30,8 +30,9 @@
|
|
|
30
30
|
* @task T4707
|
|
31
31
|
* @epic T4663
|
|
32
32
|
*/
|
|
33
|
+
import type { GitHookInstallOptions } from '@cleocode/contracts/git-hooks.js';
|
|
33
34
|
/** Options for the init operation. */
|
|
34
|
-
export interface InitOptions {
|
|
35
|
+
export interface InitOptions extends Pick<GitHookInstallOptions, 'allowTrackedHooksPath'> {
|
|
35
36
|
/** Project name override. */
|
|
36
37
|
name?: string;
|
|
37
38
|
/** Overwrite existing files. */
|
package/dist/init.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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"}
|
package/dist/init.js
CHANGED
|
@@ -1311,23 +1311,14 @@ async function scaffoldInitTarget(opts, target) {
|
|
|
1311
1311
|
}
|
|
1312
1312
|
// Git hooks (commit-msg, pre-commit, pre-push)
|
|
1313
1313
|
try {
|
|
1314
|
-
const hooksResult = await ensureGitHooks(projRoot, {
|
|
1314
|
+
const hooksResult = await ensureGitHooks(projRoot, {
|
|
1315
|
+
force,
|
|
1316
|
+
allowTrackedHooksPath: opts.allowTrackedHooksPath,
|
|
1317
|
+
});
|
|
1315
1318
|
if (hooksResult.action === 'created') {
|
|
1316
1319
|
created.push(hooksResult.details ?? 'git hooks installed');
|
|
1317
1320
|
}
|
|
1318
|
-
else if (hooksResult.
|
|
1319
|
-
warnings.push(hooksResult.details);
|
|
1320
|
-
}
|
|
1321
|
-
else if (hooksResult.action === 'skipped' &&
|
|
1322
|
-
hooksResult.details?.includes('not found in package root')) {
|
|
1323
|
-
warnings.push(hooksResult.details);
|
|
1324
|
-
}
|
|
1325
|
-
else if (hooksResult.action === 'repaired' && hooksResult.details?.includes('error')) {
|
|
1326
|
-
// Hook errors reported via details in 'repaired' action
|
|
1327
|
-
const match = hooksResult.details.match(/Installed (\d+)/);
|
|
1328
|
-
if (match && parseInt(match[1], 10) > 0) {
|
|
1329
|
-
created.push(`git hooks (${match[1]} installed)`);
|
|
1330
|
-
}
|
|
1321
|
+
else if (hooksResult.details) {
|
|
1331
1322
|
warnings.push(hooksResult.details);
|
|
1332
1323
|
}
|
|
1333
1324
|
}
|