@cratylus/canon 0.2.0 → 0.3.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/dist/dimensions/autonomy/human-on-the-loop.js +1 -1
- package/dist/dimensions/autonomy/human-on-the-loop.js.map +1 -1
- package/dist/hook-cells.js +5 -2
- package/dist/hook-cells.js.map +1 -1
- package/dist/hooks/deploy-drift-notice.js +1 -1
- package/dist/hooks/deploy-drift-notice.js.map +1 -1
- package/dist/hooks/stance-guardrail-pre.js +17 -22
- package/dist/hooks/stance-guardrail-pre.js.map +1 -1
- package/dist/hooks/stance-guardrail.js +84 -27
- package/dist/hooks/stance-guardrail.js.map +1 -1
- package/dist/plan-states.d.ts +3 -3
- package/dist/plan-states.js +3 -3
- package/dist/skills/carry-on/skill.js +2 -2
- package/dist/skills/carry-on/skill.js.map +1 -1
- package/package.json +3 -6
- package/dist/hooks/praxis-continuity.d.ts +0 -2
- package/dist/hooks/praxis-continuity.js +0 -132
- package/dist/hooks/praxis-continuity.js.map +0 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// phase-STATE, not a static value: the `⟨resting · phase-state⟩` residue declares
|
|
5
5
|
// this as the RESTING / initial position (a session opens in orientation, intent
|
|
6
6
|
// the operator's to set) while marking that the live position shifts —
|
|
7
|
-
// `carry-on` elevates it to out-of-the-loop, held until the bound
|
|
7
|
+
// `carry-on` elevates it to out-of-the-loop, held until the bound plan
|
|
8
8
|
// completes or an unresolvable fork re-enters on-the-loop. See skills/carry-on.
|
|
9
9
|
export const humanOnTheLoop = `human-on-the-loop ⟨resting · phase-state⟩`;
|
|
10
10
|
//# sourceMappingURL=human-on-the-loop.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"human-on-the-loop.js","sourceRoot":"","sources":["../../../src/dimensions/autonomy/human-on-the-loop.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,kFAAkF;AAClF,+EAA+E;AAC/E,kFAAkF;AAClF,iFAAiF;AACjF,uEAAuE;AACvE,
|
|
1
|
+
{"version":3,"file":"human-on-the-loop.js","sourceRoot":"","sources":["../../../src/dimensions/autonomy/human-on-the-loop.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,kFAAkF;AAClF,+EAA+E;AAC/E,kFAAkF;AAClF,iFAAiF;AACjF,uEAAuE;AACvE,uEAAuE;AACvE,gFAAgF;AAChF,MAAM,CAAC,MAAM,cAAc,GAAa,2CAA2C,CAAC"}
|
package/dist/hook-cells.js
CHANGED
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
// (claude adapter: `turn.end` → Stop, `subagent.end` → SubagentStop) and carries
|
|
7
7
|
// their VERBATIM worker payloads so the projector stages them under `hooks/<id>/`
|
|
8
8
|
// (no file copy — the bytes come from the cell). Only `harness`-substrate cells
|
|
9
|
-
// register in settings.json
|
|
10
|
-
// git
|
|
9
|
+
// register in settings.json, and every surviving cell is one: the corpus's single
|
|
10
|
+
// `git`-substrate cell, `praxis-continuity`, retired with the praxis plan mirror it
|
|
11
|
+
// nudged about. The routing for a non-harness substrate is not hypothetical — it is
|
|
12
|
+
// exercised the moment such a cell exists again — but nothing carries it today, and
|
|
13
|
+
// a header claiming a live example is a claim a reader cannot check.
|
|
11
14
|
//
|
|
12
15
|
// The cell shapes are the schema's type kernel (`@cratylus/schema`); this
|
|
13
16
|
// module is the composition root that NAMES the concrete cells and nothing more.
|
package/dist/hook-cells.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hook-cells.js","sourceRoot":"","sources":["../src/hook-cells.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,2EAA2E;AAC3E,kFAAkF;AAClF,mFAAmF;AACnF,4EAA4E;AAC5E,iFAAiF;AACjF,kFAAkF;AAClF,gFAAgF;AAChF,
|
|
1
|
+
{"version":3,"file":"hook-cells.js","sourceRoot":"","sources":["../src/hook-cells.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,2EAA2E;AAC3E,kFAAkF;AAClF,mFAAmF;AACnF,4EAA4E;AAC5E,iFAAiF;AACjF,kFAAkF;AAClF,gFAAgF;AAChF,kFAAkF;AAClF,oFAAoF;AACpF,oFAAoF;AACpF,oFAAoF;AACpF,qEAAqE;AACrE,EAAE;AACF,0EAA0E;AAC1E,iFAAiF;AACjF,oFAAoF;AACpF,iFAAiF;AACjF,+EAA+E;AAE/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAG9D,wFAAwF;AACxF,MAAM,CAAC,MAAM,gBAAgB,GAAwB;IACnD,eAAe;IACf,kBAAkB;IAClB,iBAAiB;CAClB,CAAC"}
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
// copy with nothing further to say. That is not hypothetical and it is not rare —
|
|
34
34
|
// it is the ORDINARY shape of work here, where a session edits a cell, projects it,
|
|
35
35
|
// and keeps going under the version it just replaced. The 16-hour-old projection of
|
|
36
|
-
// an agent's own governing cell was this; so was a `
|
|
36
|
+
// an agent's own governing cell was this; so was a `plan` edit that landed under a
|
|
37
37
|
// running session hours later.
|
|
38
38
|
//
|
|
39
39
|
// `prompt.submit` IS THE RE-ARM, and it is the same question at a finer grain rather
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deploy-drift-notice.js","sourceRoot":"","sources":["../../src/hooks/deploy-drift-notice.ts"],"names":[],"mappings":"AAEA,kFAAkF;AAClF,kEAAkE;AAClE,EAAE;AACF,oFAAoF;AACpF,qFAAqF;AACrF,gFAAgF;AAChF,sFAAsF;AACtF,0EAA0E;AAC1E,mFAAmF;AACnF,gFAAgF;AAChF,qFAAqF;AACrF,EAAE;AACF,sFAAsF;AACtF,sFAAsF;AACtF,qFAAqF;AACrF,iFAAiF;AACjF,8BAA8B;AAC9B,EAAE;AACF,qFAAqF;AACrF,sFAAsF;AACtF,oFAAoF;AACpF,uFAAuF;AACvF,kFAAkF;AAClF,2BAA2B;AAC3B,EAAE;AACF,sFAAsF;AACtF,oFAAoF;AACpF,kEAAkE;AAClE,EAAE;AACF,mFAAmF;AACnF,oFAAoF;AACpF,kFAAkF;AAClF,kFAAkF;AAClF,oFAAoF;AACpF,oFAAoF;AACpF,
|
|
1
|
+
{"version":3,"file":"deploy-drift-notice.js","sourceRoot":"","sources":["../../src/hooks/deploy-drift-notice.ts"],"names":[],"mappings":"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"}
|
|
@@ -46,9 +46,9 @@ export const stanceGuardrailPre = {
|
|
|
46
46
|
# ambiguity, a substantive intent-extracted dispatch.
|
|
47
47
|
#
|
|
48
48
|
# SAFETY MODEL (mirrors stance-guardrail):
|
|
49
|
-
# -
|
|
50
|
-
#
|
|
51
|
-
#
|
|
49
|
+
# - SCOPE-ENROLLED, exactly as its twin: a scope carrying a stance manifest is judged and
|
|
50
|
+
# every other scope is silent. No repo opt-in, no allowlist — the projection that places a
|
|
51
|
+
# persona also enrolls it, and declining the guard means declining the persona.
|
|
52
52
|
# - FAILS OPEN. Any error (no jq, judge failure, bad input) -> exit 0 (allow the call).
|
|
53
53
|
# - LOOP-SAFE. A re-entry cap: never deny an identical tool_input twice (there is no
|
|
54
54
|
# stop_hook_active analog for PreToolUse), so it can never wedge a call.
|
|
@@ -98,27 +98,22 @@ input="$(cat)"
|
|
|
98
98
|
[ -n "$input" ] || allow
|
|
99
99
|
command -v jq >/dev/null 2>&1 || allow # no jq -> cannot parse -> fail open
|
|
100
100
|
|
|
101
|
-
#
|
|
102
|
-
#
|
|
101
|
+
# The per-repo opt-in is GONE, for the reason its twin states: it asked whether a guard may run in
|
|
102
|
+
# a DIRECTORY, and a stance belongs to the agent, not the checkout. \`cwd\` survives it — the worker
|
|
103
|
+
# still runs where the session runs.
|
|
103
104
|
cwd="$(printf '%s' "$input" | jq -r '.cwd // empty' 2>/dev/null || true)"
|
|
104
105
|
[ -n "$cwd" ] && cd "$cwd" 2>/dev/null || true
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
#
|
|
109
|
-
#
|
|
110
|
-
#
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
in_scope=false
|
|
117
|
-
for a in $allowlist; do
|
|
118
|
-
[ "$a" = "$agent_type" ] && in_scope=true && break
|
|
119
|
-
done
|
|
120
|
-
[ "$in_scope" = true ] || allow
|
|
121
|
-
fi
|
|
106
|
+
|
|
107
|
+
# --- scope gate: the persona's OWN stance manifest -------------------------------------------
|
|
108
|
+
# The twin of the turn-end guard's gate, and inverted for the same reason: an allowlist here was
|
|
109
|
+
# a runtime self-filter over an enrollment the corpus already derives, and it had drifted the way
|
|
110
|
+
# such a list always drifts. Presence of a manifest in this persona's own scope IS enrollment.
|
|
111
|
+
# Absent → silence, never an error, so an unenrolled launch is untouched.
|
|
112
|
+
stance_scope="$(printf '%s' "$input" | jq -r '.stance_scope // empty' 2>/dev/null || true)"
|
|
113
|
+
[ -n "$stance_scope" ] || allow
|
|
114
|
+
manifest="$stance_scope/stance/manifest.json"
|
|
115
|
+
[ -f "$manifest" ] || allow
|
|
116
|
+
agent_type="$(jq -r '.agent // empty' "$manifest" 2>/dev/null || true)"
|
|
122
117
|
|
|
123
118
|
# --- extract the judged payload, branched by tool -------------------------------------------
|
|
124
119
|
tool_name="$(printf '%s' "$input" | jq -r '.tool_name // empty' 2>/dev/null || true)"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stance-guardrail-pre.js","sourceRoot":"","sources":["../../src/hooks/stance-guardrail-pre.ts"],"names":[],"mappings":"AAEA,sFAAsF;AACtF,mFAAmF;AACnF,uFAAuF;AACvF,SAAS;AACT,wFAAwF;AACxF,6FAA6F;AAC7F,0FAA0F;AAC1F,uFAAuF;AACvF,qEAAqE;AACrE,EAAE;AACF,wEAAwE;AACxE,sFAAsF;AACtF,iFAAiF;AACjF,mFAAmF;AACnF,sFAAsF;AACtF,qFAAqF;AACrF,sFAAsF;AACtF,sFAAsF;AACtF,mEAAmE;AACnE,2DAA2D;AAC3D,mDAAmD;AAEnD,MAAM,CAAC,MAAM,kBAAkB,GAAa;IAC1C,EAAE,EAAE,sBAAsB;IAC1B,OAAO,EACL,iWAAiW;IACnW,SAAS,EAAE,SAAS;IACpB,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;IACzD,KAAK,EAAE,yBAAyB;IAChC,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,EAAE;IACR,OAAO,EAAE;QACP;YACE,QAAQ,EAAE,yBAAyB;YACnC,UAAU,EAAE,0DAA0D;YACtE,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE
|
|
1
|
+
{"version":3,"file":"stance-guardrail-pre.js","sourceRoot":"","sources":["../../src/hooks/stance-guardrail-pre.ts"],"names":[],"mappings":"AAEA,sFAAsF;AACtF,mFAAmF;AACnF,uFAAuF;AACvF,SAAS;AACT,wFAAwF;AACxF,6FAA6F;AAC7F,0FAA0F;AAC1F,uFAAuF;AACvF,qEAAqE;AACrE,EAAE;AACF,wEAAwE;AACxE,sFAAsF;AACtF,iFAAiF;AACjF,mFAAmF;AACnF,sFAAsF;AACtF,qFAAqF;AACrF,sFAAsF;AACtF,sFAAsF;AACtF,mEAAmE;AACnE,2DAA2D;AAC3D,mDAAmD;AAEnD,MAAM,CAAC,MAAM,kBAAkB,GAAa;IAC1C,EAAE,EAAE,sBAAsB;IAC1B,OAAO,EACL,iWAAiW;IACnW,SAAS,EAAE,SAAS;IACpB,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC,sBAAsB,EAAE,uBAAuB,CAAC;IACzD,KAAK,EAAE,yBAAyB;IAChC,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,EAAE;IACR,OAAO,EAAE;QACP;YACE,QAAQ,EAAE,yBAAyB;YACnC,UAAU,EAAE,0DAA0D;YACtE,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4Jd;SACI;KACF;CACF,CAAC"}
|
|
@@ -49,8 +49,13 @@ export const stanceGuardrail = {
|
|
|
49
49
|
# electing the session's objective is supplying intent, not sequencing — the operator's to own
|
|
50
50
|
#
|
|
51
51
|
# SAFETY MODEL:
|
|
52
|
-
# -
|
|
53
|
-
#
|
|
52
|
+
# - SCOPE-ENROLLED. Fires for a scope carrying a stance manifest, and for no other. Enrollment
|
|
53
|
+
# is PRESENCE: the projection places a manifest in each persona's own scope, so composing the
|
|
54
|
+
# cell enrolls the persona and nothing central lists anybody. A bare launch carries the
|
|
55
|
+
# dispatcher and no manifest, and is therefore silent by placement.
|
|
56
|
+
# - NO REPO OPT-IN. There was one, per-repo in .git/config, and it asked the wrong question:
|
|
57
|
+
# whether a guard may run in a DIRECTORY. The off switch is launching \`omp\` rather than a
|
|
58
|
+
# persona — declining to BE the agent, instead of being it unjudged.
|
|
54
59
|
# - FAILS OPEN, BUT NEVER SILENTLY-CLEAN. Any error → exit 0 (allow stop): a guardrail that
|
|
55
60
|
# wedges work on its own flakiness is worse than a missed block. But once the guard is
|
|
56
61
|
# ENABLED and in scope, a failure that prevents judging (no transcript, judge unreachable)
|
|
@@ -85,6 +90,9 @@ JUDGE_CMD="\${STANCE_JUDGE_CMD:-sh $SELF_DIR/stance-judge.sh}"
|
|
|
85
90
|
# a host and point outside a sandboxed deploy, which is the class of bug that put
|
|
86
91
|
# \`\$HOME/.claude\` in the sibling worker and made it read another harness's tree.
|
|
87
92
|
NEUTRAL_ROOT="$(dirname -- "$(dirname -- "$(dirname -- "$SELF_DIR")")")/.agents"
|
|
93
|
+
# The DEFAULT rubric. A persona's own manifest may name another — that is the
|
|
94
|
+
# strategy seam: one opinionated implementation, each persona free to bind a
|
|
95
|
+
# different contract without the dispatcher learning anything about either.
|
|
88
96
|
RUBRIC="\${STANCE_RUBRIC:-$NEUTRAL_ROOT/stance-guardrail/stance-judge-prompt.md}"
|
|
89
97
|
|
|
90
98
|
# A Stop hook must never break a session. Trap any unexpected error → allow the stop.
|
|
@@ -102,6 +110,15 @@ allow_stop() { exit 0; } # emit nothing; the agent is permitted to stop.
|
|
|
102
110
|
# turn. Reached only AFTER the opt-in and allowlist checks, so a repo that never enabled
|
|
103
111
|
# the guard stays silent.
|
|
104
112
|
dark() {
|
|
113
|
+
# THE HEARTBEAT, and the reason the log is worth keeping. A VERDICT row and a
|
|
114
|
+
# DARK row are both evidence the guard RAN; only an EMPTY log means it never
|
|
115
|
+
# did. Recording judged turns alone made "not judged" and "no session" read
|
|
116
|
+
# identically — measured on a live host: an endpoint behind the advisor role
|
|
117
|
+
# accepted connections and never answered, and five hours of one session were
|
|
118
|
+
# unjudged while leaving no trace whatsoever to notice it by.
|
|
119
|
+
if [ -n "\${verdict_log:-}" ]; then
|
|
120
|
+
printf 'DARK\\t\\t%s\\n' "\$1" >> "\$verdict_log" 2>/dev/null || true
|
|
121
|
+
fi
|
|
105
122
|
printf 'STANCE GUARDRAIL — DARK: %s. This turn was NOT judged; the absence of a block is an absence of a verdict, not a clean one.\\n' "\$1"
|
|
106
123
|
exit 0
|
|
107
124
|
}
|
|
@@ -138,32 +155,55 @@ verdict_log="$state_dir/$session.verdicts"
|
|
|
138
155
|
block_count="$(cat "$count_file" 2>/dev/null || echo 0)"
|
|
139
156
|
case "$block_count" in *[!0-9]*) block_count=0 ;; esac
|
|
140
157
|
|
|
141
|
-
#
|
|
142
|
-
#
|
|
143
|
-
#
|
|
158
|
+
# The per-repo opt-in is GONE, and its absence is the point. It answered "may a guard run in this
|
|
159
|
+
# DIRECTORY", which is a category error: a stance is a property of the agent, not of the checkout
|
|
160
|
+
# it happens to be standing in. Worse, it made the stance OPTIONAL AT RUNTIME for an agent already
|
|
161
|
+
# launched as itself — the ambient form, when the whole reason this harness half exists is that
|
|
162
|
+
# identity alone erodes. The off switch is launching \`omp\` instead of \`mav\`: declining to be the
|
|
163
|
+
# persona, rather than being it unjudged.
|
|
144
164
|
cwd="$(printf '%s' "$input" | jq -r '.cwd // empty' 2>/dev/null || true)"
|
|
145
165
|
[ -n "$cwd" ] && cd "$cwd" 2>/dev/null || true
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
#
|
|
152
|
-
#
|
|
153
|
-
#
|
|
154
|
-
#
|
|
155
|
-
#
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
166
|
+
|
|
167
|
+
# --- scope gate: the persona's OWN stance manifest -------------------------------------------
|
|
168
|
+
# COMPOSITION IS THE SCOPE, NOT A RUNTIME SELF-FILTER — MODEL.md's ENFORCED clause, and this
|
|
169
|
+
# gate used to violate it outright. It read an allowlist, \`nico mav\` by default and overridable
|
|
170
|
+
# by \`STANCE_GUARD_AGENTS\`, which is precisely the runtime self-filter that clause forbids: a
|
|
171
|
+
# module asking WHO IS RUNNING rather than being placed where only the right launch reaches it.
|
|
172
|
+
#
|
|
173
|
+
# It had already drifted, in the direction such a list always drifts. Every agent in the corpus
|
|
174
|
+
# composes \`handoff\`, so \`Binding.agents\` DERIVES all six as bound, and six persona scopes are
|
|
175
|
+
# deployed to prove it — while the list enforced two. \`architect\` and \`kino\` held principal
|
|
176
|
+
# authority and were never once judged, and nothing surfaced the gap because the two facts were
|
|
177
|
+
# written in different languages in different files.
|
|
178
|
+
#
|
|
179
|
+
# Enrollment is now PRESENCE. Each bound persona's projection lands a manifest in that persona's
|
|
180
|
+
# own scope, and the dispatcher — which lives in that same scope and therefore already knows it
|
|
181
|
+
# — passes it in the envelope. A manifest means enrolled, and carries THIS agent's contract: its
|
|
182
|
+
# rubric, its moments, its handoff laws. No manifest means not enrolled, which is silence rather
|
|
183
|
+
# than an error, so a plain session that never declared itself anything stays untouched exactly
|
|
184
|
+
# as it was. Adding a persona enrolls it; adding a gated dimension edits one persona's manifest;
|
|
185
|
+
# neither is a line in this file.
|
|
186
|
+
stance_scope="$(printf '%s' "$input" | jq -r '.stance_scope // empty' 2>/dev/null || true)"
|
|
187
|
+
[ -n "$stance_scope" ] || allow_stop
|
|
188
|
+
manifest="$stance_scope/stance/manifest.json"
|
|
189
|
+
[ -f "$manifest" ] || allow_stop
|
|
190
|
+
|
|
191
|
+
# The persona's own contract, each field falling back to the shipped default. A manifest that
|
|
192
|
+
# names nothing still enrolls: presence is the assertion, the fields are the refinement.
|
|
193
|
+
agent_type="$(jq -r '.agent // empty' "$manifest" 2>/dev/null || true)"
|
|
194
|
+
manifest_rubric="$(jq -r '.rubric // empty' "$manifest" 2>/dev/null || true)"
|
|
195
|
+
# An OVERRIDE that does not resolve is a defect and goes DARK — a persona that asked to be judged
|
|
196
|
+
# against its own contract and is silently judged against someone else's has been mis-scored, not
|
|
197
|
+
# spared. The DEFAULT is not checked here: a judge backend need not read the file at all (the
|
|
198
|
+
# fixture judge does not), and refusing to run because a path the manifest never named is absent
|
|
199
|
+
# would fail closed on a case the manifest made no claim about.
|
|
200
|
+
case "$manifest_rubric" in
|
|
201
|
+
'') ;;
|
|
202
|
+
/*) RUBRIC="$manifest_rubric" ;;
|
|
203
|
+
*) RUBRIC="$stance_scope/stance/$manifest_rubric" ;;
|
|
204
|
+
esac
|
|
205
|
+
[ -z "$manifest_rubric" ] || [ -f "$RUBRIC" ] || \\
|
|
206
|
+
dark "the rubric named by $manifest is not readable at '\$RUBRIC'"
|
|
167
207
|
|
|
168
208
|
# --- extract the last assistant turn from the transcript ------------------------------------
|
|
169
209
|
transcript="$(printf '%s' "$input" | jq -r '.transcript_path // empty' 2>/dev/null || true)"
|
|
@@ -500,7 +540,24 @@ if [ -n "$evidence" ] && [ "\${#evidence}" -ge 12 ]; then
|
|
|
500
540
|
# 3/5 on identical payloads — i.e. the record of WHY a turn was blocked was reconstructible only
|
|
501
541
|
# by a non-deterministic process. Appended, never rotated by this hook; the state dir is tmp.
|
|
502
542
|
printf '%s\\t%s\\t%s\\n' "$decision" "$evidence" "$reason" >> "$verdict_log" 2>/dev/null || true
|
|
503
|
-
|
|
543
|
+
# NORMALIZED ON BOTH SIDES, and with \`--\`, because this check had two ways to
|
|
544
|
+
# throw away a correct block — and both of them fired on the SAME shape, which is
|
|
545
|
+
# the one shape this guard most exists to catch.
|
|
546
|
+
#
|
|
547
|
+
# 1. \`grep -qF "$evidence"\` with no \`--\`: an evidence span opening with a markdown
|
|
548
|
+
# bullet is read as an OPTION. \`grep: invalid option -- ' '\`, non-zero, block
|
|
549
|
+
# discarded. A tail-enumeration collapse IS a bullet list, so its evidence always
|
|
550
|
+
# begins \`- \`, and the rule could never convict the shape it was written for.
|
|
551
|
+
# 2. A judge quoting several bullets joins them with spaces and drops the markers,
|
|
552
|
+
# so a verbatim-substring test fails on punctuation while every word is present.
|
|
553
|
+
#
|
|
554
|
+
# The proposition worth authenticating is that the judge quoted THIS TURN'S WORDS,
|
|
555
|
+
# not that it reproduced its list syntax. So both sides are flattened the same way:
|
|
556
|
+
# newlines to spaces, runs of whitespace to one, list markers dropped. Symmetric, so
|
|
557
|
+
# nothing is accepted on one side that would be rejected on the other.
|
|
558
|
+
ev_norm="$(printf '%s' "$evidence" | tr '\\n' ' ' | sed -e 's/[[:space:]][[:space:]]*/ /g' -e 's/^[-*][[:space:]]//' -e 's/ [-*] / /g')"
|
|
559
|
+
close_norm="$(printf '%s' "$asst_close" | tr '\\n' ' ' | sed -e 's/[[:space:]][[:space:]]*/ /g' -e 's/^[-*][[:space:]]//' -e 's/ [-*] / /g')"
|
|
560
|
+
if ! printf '%s' "$close_norm" | grep -qF -- "$ev_norm"; then
|
|
504
561
|
printf 'stance-guardrail: DISCARDING block — judge quoted a span that is not in the turn'"'"'s CLOSE (mid-turn preamble, or confabulated): %s\\n' "$evidence" >&2
|
|
505
562
|
allow_stop
|
|
506
563
|
fi
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stance-guardrail.js","sourceRoot":"","sources":["../../src/hooks/stance-guardrail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAC;AAG5D,wEAAwE;AACxE,8EAA8E;AAC9E,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,gFAAgF;AAEhF,MAAM,CAAC,MAAM,eAAe,GAAa;IACvC,EAAE,EAAE,kBAAkB;IACtB,OAAO,EACL,8UAA8U;IAChV,SAAS,EAAE,SAAS;IACpB,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,KAAK,EAAE,qBAAqB;IAC5B,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,EAAE;IACR,OAAO,EAAE;QACP;YACE,QAAQ,EAAE,qBAAqB;YAC/B,UAAU,EAAE,sDAAsD;YAClE,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE
|
|
1
|
+
{"version":3,"file":"stance-guardrail.js","sourceRoot":"","sources":["../../src/hooks/stance-guardrail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,mCAAmC,CAAC;AAG5D,wEAAwE;AACxE,8EAA8E;AAC9E,2EAA2E;AAC3E,2EAA2E;AAC3E,8EAA8E;AAC9E,gFAAgF;AAEhF,MAAM,CAAC,MAAM,eAAe,GAAa;IACvC,EAAE,EAAE,kBAAkB;IACtB,OAAO,EACL,8UAA8U;IAChV,SAAS,EAAE,SAAS;IACpB,KAAK,EAAE,CAAC;IACR,MAAM,EAAE,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,KAAK,EAAE,qBAAqB;IAC5B,OAAO,EAAE,EAAE;IACX,IAAI,EAAE,EAAE;IACR,OAAO,EAAE;QACP;YACE,QAAQ,EAAE,qBAAqB;YAC/B,UAAU,EAAE,sDAAsD;YAClE,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwnBd;SACI;QACD;YACE,QAAQ,EAAE,iBAAiB;YAC3B,UAAU,EAAE,kDAAkD;YAC9D,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmFd;SACI;QACD;YACE,QAAQ,EAAE,wBAAwB;YAClC,UAAU,EAAE,yDAAyD;YACrE,UAAU,EAAE,KAAK;YACjB,yEAAyE;YACzE,sEAAsE;YACtE,0EAA0E;YAC1E,2EAA2E;YAC3E,yEAAyE;YACzE,yEAAyE;YACzE,MAAM,EAAE,IAAI;YACZ,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAsNX,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyLV;SACI;KACF;CACF,CAAC"}
|
package/dist/plan-states.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/** The plan-layout state folders, in task-file lifecycle order. */
|
|
2
2
|
export declare const PLAN_STATES: readonly ["pending", "ready", "active", "completed"];
|
|
3
3
|
/** `frontier(P)` — the states a shard sits in when the plan is workable AT it
|
|
4
|
-
* (
|
|
4
|
+
* (`{ t | state(t) ∈ { ready, active } }`, where the plan IS, not merely
|
|
5
5
|
* what is dispatchable). A subset of {@link PLAN_STATES} and not derivable from
|
|
6
6
|
* their ORDER: `pending` is open too, and is not frontier. */
|
|
7
7
|
export declare const PLAN_FRONTIER: readonly ["ready", "active"];
|
|
8
8
|
/**
|
|
9
9
|
* The plan-tier dotfile MARKERS whose only home is here.
|
|
10
10
|
*
|
|
11
|
-
* A relation with no on-disk carrier is not readable — the reading `
|
|
11
|
+
* A relation with no on-disk carrier is not readable — the reading `plan-set.sh`
|
|
12
12
|
* states in its own words when it explains why `.landed` exists ("exactly parallel
|
|
13
13
|
* to `.superseded-by`"). These are the two markers a reader of the plan set needs
|
|
14
14
|
* that have no other TypeScript home: `.superseded-by` already has one
|
|
@@ -16,7 +16,7 @@ export declare const PLAN_FRONTIER: readonly ["ready", "active"];
|
|
|
16
16
|
*
|
|
17
17
|
* `.ruling-owed` is the third carrier this corpus has minted on that reading, and
|
|
18
18
|
* it carries the concept the corpus ALREADY signifies as a ruling owed — "a
|
|
19
|
-
* decision nobody has taken", which the
|
|
19
|
+
* decision nobody has taken", which the retired praxis cell distinguished from a
|
|
20
20
|
* dependency ("a dep waits itself out, a ruling needs a human"). At the SHARD tier
|
|
21
21
|
* that concept is `ruling-owed(t)`, and it gates `ready`; at the
|
|
22
22
|
* PLAN tier it had no carrier at all, so a fork the principal cannot resolve —
|
package/dist/plan-states.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
/** The plan-layout state folders, in task-file lifecycle order. */
|
|
13
13
|
export const PLAN_STATES = ['pending', 'ready', 'active', 'completed'];
|
|
14
14
|
/** `frontier(P)` — the states a shard sits in when the plan is workable AT it
|
|
15
|
-
* (
|
|
15
|
+
* (`{ t | state(t) ∈ { ready, active } }`, where the plan IS, not merely
|
|
16
16
|
* what is dispatchable). A subset of {@link PLAN_STATES} and not derivable from
|
|
17
17
|
* their ORDER: `pending` is open too, and is not frontier. */
|
|
18
18
|
export const PLAN_FRONTIER = [
|
|
@@ -22,7 +22,7 @@ export const PLAN_FRONTIER = [
|
|
|
22
22
|
/**
|
|
23
23
|
* The plan-tier dotfile MARKERS whose only home is here.
|
|
24
24
|
*
|
|
25
|
-
* A relation with no on-disk carrier is not readable — the reading `
|
|
25
|
+
* A relation with no on-disk carrier is not readable — the reading `plan-set.sh`
|
|
26
26
|
* states in its own words when it explains why `.landed` exists ("exactly parallel
|
|
27
27
|
* to `.superseded-by`"). These are the two markers a reader of the plan set needs
|
|
28
28
|
* that have no other TypeScript home: `.superseded-by` already has one
|
|
@@ -30,7 +30,7 @@ export const PLAN_FRONTIER = [
|
|
|
30
30
|
*
|
|
31
31
|
* `.ruling-owed` is the third carrier this corpus has minted on that reading, and
|
|
32
32
|
* it carries the concept the corpus ALREADY signifies as a ruling owed — "a
|
|
33
|
-
* decision nobody has taken", which the
|
|
33
|
+
* decision nobody has taken", which the retired praxis cell distinguished from a
|
|
34
34
|
* dependency ("a dep waits itself out, a ruling needs a human"). At the SHARD tier
|
|
35
35
|
* that concept is `ruling-owed(t)`, and it gates `ready`; at the
|
|
36
36
|
* PLAN tier it had no carrier at all, so a fork the principal cannot resolve —
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
// plan. "Carry on with what we just discussed" is the same utterance doing the same
|
|
9
9
|
// work over a discussion, and a cell bound to `praxis` cannot serve it.
|
|
10
10
|
//
|
|
11
|
-
// The COMPOSITION is the operator's, at the utterance: "carry on with the
|
|
12
|
-
// execution" is carry-on ∘
|
|
11
|
+
// The COMPOSITION is the operator's, at the utterance: "carry on with the plan
|
|
12
|
+
// execution" is carry-on ∘ plan, and the pairing lives in what was said, not in
|
|
13
13
|
// this module's import list. A cell that names one context forecloses the rest.
|
|
14
14
|
//
|
|
15
15
|
// THE MECHANISM WENT WITH THE COUPLING, and that is a real loss recorded rather than
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../../../src/skills/carry-on/skill.ts"],"names":[],"mappings":"AAEA,mEAAmE;AACnE,EAAE;AACF,6EAA6E;AAC7E,oFAAoF;AACpF,kFAAkF;AAClF,qFAAqF;AACrF,mFAAmF;AACnF,oFAAoF;AACpF,wEAAwE;AACxE,EAAE;AACF
|
|
1
|
+
{"version":3,"file":"skill.js","sourceRoot":"","sources":["../../../src/skills/carry-on/skill.ts"],"names":[],"mappings":"AAEA,mEAAmE;AACnE,EAAE;AACF,6EAA6E;AAC7E,oFAAoF;AACpF,kFAAkF;AAClF,qFAAqF;AACrF,mFAAmF;AACnF,oFAAoF;AACpF,wEAAwE;AACxE,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,gFAAgF;AAChF,EAAE;AACF,qFAAqF;AACrF,qFAAqF;AACrF,kFAAkF;AAClF,sFAAsF;AACtF,kFAAkF;AAClF,oFAAoF;AACpF,mFAAmF;AACnF,2CAA2C;AAE3C,MAAM,eAAe,GACnB;;;;;;;;;;;;;;;;;;;;;CAqBkB,CAAC;AAErB,MAAM,CAAC,MAAM,OAAO,GAAU;IAC5B,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,woBAAwoB;IACrpB,WAAW,EAAE,eAAe;IAC5B,WAAW,EAAE,GAAG,EAAE,CAAC,EAAE;CACtB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cratylus/canon",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "The canonical corpus of discovered optimal-signifiers — agents, skills, dimensions and rules as typed TS source. Markdown is a projection of these modules.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"engines": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@cratylus/schema": "0.2.0"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
|
-
"@cratylus/forge": "0.
|
|
24
|
+
"@cratylus/forge": "0.6.0",
|
|
25
25
|
"@cratylus/runtime": "0.2.0",
|
|
26
26
|
"@cratylus/tooling": "0.0.0",
|
|
27
27
|
"@types/node": "^22.0.0",
|
|
@@ -55,13 +55,10 @@
|
|
|
55
55
|
"scripts": {
|
|
56
56
|
"build": "pnpm run clean && tsc -p tsconfig.build.json",
|
|
57
57
|
"clean": "rm -rf dist",
|
|
58
|
-
"continuity": "sh targets/continuity/continuity-hook.sh",
|
|
59
58
|
"dev": "tsc -p tsconfig.build.json --watch --preserveWatchOutput",
|
|
60
|
-
"oracle": "sh tooling/render-oracle/render-oracle.sh check",
|
|
61
|
-
"oracle:update": "sh tooling/render-oracle/render-oracle.sh update",
|
|
62
59
|
"pack:smoke": "tsx tooling/pack-smoke/pack-smoke-cli.ts",
|
|
63
60
|
"plan-set": "tsx tooling/plan-set-cli.ts",
|
|
64
|
-
"
|
|
61
|
+
"plan": "sh tooling/plan-set/plan-set.sh",
|
|
65
62
|
"project:targets": "tsx tooling/project-targets-cli.ts",
|
|
66
63
|
"scaffold": "tsx tooling/scaffold-cli.ts",
|
|
67
64
|
"stance-guard:test": "sh test/support/guardrail/test-stance-guardrail.sh",
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
// praxis-continuity — the repo-level post-commit reminder. A scope-activated source
|
|
2
|
-
// cell on the GIT substrate: `vcs.commit.post` is an ordinary member of this
|
|
3
|
-
// corpus's `CANONICAL_EVENTS` carrying `substrate: 'git'`, so it is routed rather
|
|
4
|
-
// than refused — the `.husky/post-commit` dispatcher runs the committed worker
|
|
5
|
-
// directly and nothing reaches `settings.json`. Its `workers[].content` are the
|
|
6
|
-
// byte-anchors the committed `targets/continuity/` workers regenerate from
|
|
7
|
-
// (byte-locked).
|
|
8
|
-
//
|
|
9
|
-
// THE REVIEW THIS CELL WAS FLAGGED FOR IS CLOSED. The note read "not in FORGE's
|
|
10
|
-
// `CanonicalEvent` taxonomy" — stale by one package before it was stale by two, and
|
|
11
|
-
// it asked for either an addition to the taxonomy or a named exception. Neither was
|
|
12
|
-
// owed: the event was never exceptional, only unliterable, because the taxonomy was
|
|
13
|
-
// a closed union in `schema` that a git moment had no member to be. The vocabulary
|
|
14
|
-
// now lives where signification lives, `EventName` is open, and this cell names its
|
|
15
|
-
// moment exactly as a harness cell names its own.
|
|
16
|
-
export const praxisContinuity = {
|
|
17
|
-
id: 'praxis-continuity',
|
|
18
|
-
residue: 'post-commit detector ⟨task-file crosses state-folder ⇒ plan-mirror stale⟩ · nudge re-mirror · ¬edit · opt-in ↾ clone · exit-0 ⟨reminder ¬fail-commit⟩',
|
|
19
|
-
substrate: 'git',
|
|
20
|
-
events: ['vcs.commit.post'],
|
|
21
|
-
// git substrate: the entry is still named, never spelled as a path. Which
|
|
22
|
-
// directory git invokes it from is git's projection to make, not this cell's.
|
|
23
|
-
entry: 'praxis-advance-nudge.sh',
|
|
24
|
-
refs: [],
|
|
25
|
-
workers: [
|
|
26
|
-
{
|
|
27
|
-
filename: 'continuity-hook.sh',
|
|
28
|
-
targetPath: 'packages/canon/targets/continuity/continuity-hook.sh',
|
|
29
|
-
executable: true,
|
|
30
|
-
content: `#!/usr/bin/env sh
|
|
31
|
-
# continuity-hook — opt this repo in/out of the post-commit continuity ritual.
|
|
32
|
-
#
|
|
33
|
-
# The opt-in flag is a per-repo git config (agentfactory.continuity) living in .git/config,
|
|
34
|
-
# which is NOT checked in — so opting in is local to your clone and a fresh clone is
|
|
35
|
-
# opted out by default. The .husky/post-commit dispatcher reads this flag.
|
|
36
|
-
#
|
|
37
|
-
# pnpm run continuity:install → set agentfactory.continuity true
|
|
38
|
-
# pnpm run continuity:uninstall → unset (back to default off)
|
|
39
|
-
# pnpm run continuity:status → show current state
|
|
40
|
-
#
|
|
41
|
-
# Usage: continuity-hook.sh {install|uninstall|status}
|
|
42
|
-
|
|
43
|
-
set -e
|
|
44
|
-
|
|
45
|
-
cmd="\${1:-status}"
|
|
46
|
-
|
|
47
|
-
case "$cmd" in
|
|
48
|
-
install | on | true)
|
|
49
|
-
git config --bool agentfactory.continuity true
|
|
50
|
-
printf 'continuity: ENABLED for this repo (agentfactory.continuity=true).\\n'
|
|
51
|
-
printf ' Commits touching plans/**/{pending,ready,active,completed}/ now print a /praxis re-mirror reminder.\\n'
|
|
52
|
-
;;
|
|
53
|
-
uninstall | off | false)
|
|
54
|
-
git config --unset agentfactory.continuity 2>/dev/null || true
|
|
55
|
-
printf 'continuity: DISABLED for this repo (agentfactory.continuity unset → default off).\\n'
|
|
56
|
-
;;
|
|
57
|
-
status)
|
|
58
|
-
state=$(git config --bool agentfactory.continuity 2>/dev/null || echo "false")
|
|
59
|
-
printf 'continuity: %s (agentfactory.continuity=%s)\\n' \\
|
|
60
|
-
"$([ "$state" = "true" ] && echo ENABLED || echo "disabled (default)")" "$state"
|
|
61
|
-
;;
|
|
62
|
-
*)
|
|
63
|
-
printf 'usage: continuity-hook.sh {install|uninstall|status}\\n' >&2
|
|
64
|
-
exit 2
|
|
65
|
-
;;
|
|
66
|
-
esac
|
|
67
|
-
`,
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
filename: 'praxis-advance-nudge.sh',
|
|
71
|
-
targetPath: 'packages/canon/targets/continuity/praxis-advance-nudge.sh',
|
|
72
|
-
executable: true,
|
|
73
|
-
content: `#!/usr/bin/env sh
|
|
74
|
-
# praxis-advance-nudge — the repo-level continuity ritual, as a post-commit reminder.
|
|
75
|
-
#
|
|
76
|
-
# WHAT IT DOES (and deliberately does NOT do):
|
|
77
|
-
# When a commit moves plan task-files between their state folders
|
|
78
|
-
# (plans/**/{pending,ready,active,completed}/), PLAN.md — the hand-authored
|
|
79
|
-
# mirror of that folder-state — may now be stale. This script DETECTS that and
|
|
80
|
-
# PRINTS A REMINDER to re-mirror via /praxis. It never edits PLAN.md: the mirror
|
|
81
|
-
# is hand-authored prose; auto-rewriting it is out of scope (a future "mechanized
|
|
82
|
-
# PLAN.md generation" task). Detect → remind, never edit. (doc-mirrors-runtime-truth:
|
|
83
|
-
# the folders are the truth; this only flags that the mirror lagged.)
|
|
84
|
-
#
|
|
85
|
-
# SCOPE: praxis-advance is the ONE repo-level continuity ritual. Per-agent memory
|
|
86
|
-
# operations (the \`memory\` runtime capability's sidecar state under
|
|
87
|
-
# ~/.claude/agents/<name>/*) are not repo state — a git hook can't meaningfully
|
|
88
|
-
# fire them — so they are out of this hook's scope.
|
|
89
|
-
#
|
|
90
|
-
# OPT-IN: this runs only when \`git config --bool agentfactory.continuity\` is true. A fresh
|
|
91
|
-
# clone is opted out, so default commit behavior is unchanged. See continuity-hook.sh.
|
|
92
|
-
#
|
|
93
|
-
# POSIX sh; no deps beyond git. Exits 0 always — a reminder must never fail a commit.
|
|
94
|
-
|
|
95
|
-
set -e
|
|
96
|
-
|
|
97
|
-
# The commit just made (post-commit runs after HEAD has advanced).
|
|
98
|
-
git rev-parse HEAD >/dev/null 2>&1 || exit 0
|
|
99
|
-
|
|
100
|
-
# Files changed by HEAD. For a root commit (no parent) diff against the root.
|
|
101
|
-
if git rev-parse --verify --quiet HEAD^ >/dev/null 2>&1; then
|
|
102
|
-
changed=$(git diff-tree --no-commit-id --name-only -r HEAD 2>/dev/null) || exit 0
|
|
103
|
-
else
|
|
104
|
-
changed=$(git diff-tree --no-commit-id --name-only -r --root HEAD 2>/dev/null) || exit 0
|
|
105
|
-
fi
|
|
106
|
-
|
|
107
|
-
# Did this commit touch any plan state-folder? Match the four canonical states under
|
|
108
|
-
# any plans/ subtree (works whether or not a tasks/ or {concern} wrapper is present).
|
|
109
|
-
touched=$(printf '%s\\n' "$changed" \\
|
|
110
|
-
| grep -E '^plans/.*/(pending|ready|active|completed)/' || true)
|
|
111
|
-
|
|
112
|
-
[ -z "$touched" ] && exit 0
|
|
113
|
-
|
|
114
|
-
# Which plan dirs were touched (dedup to the plan root: plans/<plan>/).
|
|
115
|
-
plans=$(printf '%s\\n' "$touched" \\
|
|
116
|
-
| sed -E 's#^(plans/[^/]+)/.*#\\1#' | sort -u)
|
|
117
|
-
|
|
118
|
-
printf '\\n'
|
|
119
|
-
printf 'continuity · praxis-advance — plan state changed in this commit:\\n'
|
|
120
|
-
printf '%s\\n' "$plans" | sed 's/^/ /'
|
|
121
|
-
printf '\\n'
|
|
122
|
-
printf ' PLAN.md mirrors the task-folder state; it may now be stale.\\n'
|
|
123
|
-
printf ' Re-mirror with /praxis (advance the task, re-sync PLAN.md), then amend or follow-up commit.\\n'
|
|
124
|
-
printf ' (This is a reminder only — nothing was edited. Disable: pnpm run continuity:uninstall)\\n'
|
|
125
|
-
printf '\\n'
|
|
126
|
-
|
|
127
|
-
exit 0
|
|
128
|
-
`,
|
|
129
|
-
},
|
|
130
|
-
],
|
|
131
|
-
};
|
|
132
|
-
//# sourceMappingURL=praxis-continuity.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"praxis-continuity.js","sourceRoot":"","sources":["../../src/hooks/praxis-continuity.ts"],"names":[],"mappings":"AAEA,oFAAoF;AACpF,6EAA6E;AAC7E,kFAAkF;AAClF,+EAA+E;AAC/E,gFAAgF;AAChF,2EAA2E;AAC3E,iBAAiB;AACjB,EAAE;AACF,gFAAgF;AAChF,oFAAoF;AACpF,oFAAoF;AACpF,oFAAoF;AACpF,mFAAmF;AACnF,oFAAoF;AACpF,kDAAkD;AAElD,MAAM,CAAC,MAAM,gBAAgB,GAAa;IACxC,EAAE,EAAE,mBAAmB;IACvB,OAAO,EACL,uJAAuJ;IACzJ,SAAS,EAAE,KAAK;IAChB,MAAM,EAAE,CAAC,iBAAiB,CAAC;IAC3B,0EAA0E;IAC1E,8EAA8E;IAC9E,KAAK,EAAE,yBAAyB;IAChC,IAAI,EAAE,EAAE;IACR,OAAO,EAAE;QACP;YACE,QAAQ,EAAE,oBAAoB;YAC9B,UAAU,EAAE,sDAAsD;YAClE,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqCd;SACI;QACD;YACE,QAAQ,EAAE,yBAAyB;YACnC,UAAU,EAAE,2DAA2D;YACvE,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuDd;SACI;KACF;CACF,CAAC"}
|