fix(6470): a moment proposal counts only opens no hook explained, and asks the reader to judge it
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 35s
CI & Build / integration (push) Successful in 1m4s
CI & Build / Python tests (push) Successful in 1m46s
CI & Build / Build & push image (push) Successful in 37s
CI & Build / Python lint (push) Successful in 3s
CI & Build / Plugin hooks (push) Successful in 12s
CI & Build / TypeScript typecheck (push) Successful in 35s
CI & Build / integration (push) Successful in 1m4s
CI & Build / Python tests (push) Successful in 1m46s
CI & Build / Build & push image (push) Successful in 37s
The signal counted every get_rule open against every moment from the previous three minutes, so a rule a search arm had just shown was proposed for whatever moment happened to fire. All nine pending signal proposals were wrong. - The hook skips an open of a rule a hook named this session, and sends the last three acts from 90 seconds instead of 30 from 180. - A rule already mounted anywhere gathers no signal evidence. - A signal pair keeps the actions that reached its moment and shows them as its why. - The proposal line says it is co-occurrence, not a recommendation, and asks the reader to check the rule against the moment before offering it; moments.md says the same. Plugin 2026.10.26.2029. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "grimoire",
|
||||
"description": "Grimoire for Claude Code: connects the grimoire MCP server, adds the hooks that deliver live project state and relevant records at the right moment, ships the shared client-neutral Grimoire skills (using-grimoire, writing-plans, reporting-back, systematic-debugging, verification, brainstorming, reusing-code, shape-accounting, family-canon), and syncs your saved Grimoire Processes as skills (/grimoire:sync).",
|
||||
"version": "2026.10.22.1945",
|
||||
"version": "2026.10.26.2029",
|
||||
"author": {
|
||||
"name": "Bryan Van Deusen"
|
||||
},
|
||||
|
||||
@@ -72,19 +72,29 @@ printf '%s\n' "$rule_id" | grimoire_rules_append "$state_dir/${safe_sid}.opened.
|
||||
|
||||
# ── What came just before the open ───────────────────────────────────────
|
||||
#
|
||||
# grimoire_moment.sh writes every call to `grimoire-moment/<sid>.acts`. The ones
|
||||
# from the last three minutes go to the server with this rule's id: a rule
|
||||
# opened just after a moment fired is evidence it belongs on that moment, and
|
||||
# once that repeats across sessions the server answers with one line asking
|
||||
# the reader to offer the operator the mount. Nothing is mounted by this.
|
||||
# grimoire_moment.sh writes every call to `grimoire-moment/<sid>.acts`. The
|
||||
# last three, from the last ninety seconds, go to the server with this rule's
|
||||
# id: a rule the agent went and opened right after a moment fired is evidence
|
||||
# it belongs on that moment, and once that repeats across sessions the server
|
||||
# answers with one line putting the question to the reader. Nothing is
|
||||
# mounted by this.
|
||||
#
|
||||
# An open of a rule a hook has just NAMED is not reported. A ranked arm or a
|
||||
# moment line put it in front of the reader, and that explains the open; the
|
||||
# moment beside it did not, so counting it would propose mounts on whatever
|
||||
# moment happened to fire while search was surfacing the rule. The window is
|
||||
# short for the same reason: a few minutes of agent work reaches many moments.
|
||||
command -v curl >/dev/null 2>&1 || exit 0
|
||||
grimoire_config || exit 0
|
||||
case ",$(grimoire_rules_live "$state_dir/${safe_sid}.rules.ids")," in
|
||||
*",${rule_id},"*) exit 0 ;;
|
||||
esac
|
||||
acts_file="${TMPDIR:-/tmp}/grimoire-moment/${safe_sid}.acts"
|
||||
[ -f "$acts_file" ] || exit 0
|
||||
now=$(date +%s 2>/dev/null) || exit 0
|
||||
acts=$(awk -F '\t' -v since=$((now - 180)) \
|
||||
acts=$(awk -F '\t' -v since=$((now - 90)) \
|
||||
'$1 + 0 >= since { sub(/^[^\t]*\t/, ""); print }' "$acts_file" 2>/dev/null \
|
||||
| tail -n 30 | paste -sd ',' - 2>/dev/null)
|
||||
| tail -n 3 | paste -sd ',' - 2>/dev/null)
|
||||
[ -n "$acts" ] || exit 0
|
||||
|
||||
sid_esc=$(printf '%s' "$session_id" | grimoire_json_escape) || exit 0
|
||||
|
||||
@@ -73,12 +73,16 @@ than a mount is fixed through its trigger instead.
|
||||
|
||||
## When a line proposes a mount
|
||||
|
||||
A rule that keeps being opened just after the same moment, across several
|
||||
sessions, probably belongs on that moment. A line says so, naming the rule,
|
||||
the moment and how often. It is a question for the operator, not a change you
|
||||
make: offer it in one line, and record their answer with
|
||||
`judge_rule_moments` — `confirm` mounts the rule, `reject` with their reason
|
||||
stops the question being asked again.
|
||||
A rule that sessions keep going and opening just after the same moment —
|
||||
without a hook having shown it to them first — may belong on that moment. A
|
||||
line says so, naming the rule, the moment, the action that reached it and how
|
||||
often. That is co-occurrence, not a recommendation, so judge it before it
|
||||
reaches the operator: read the rule's trigger against what the moment means
|
||||
(`list_moments`). Offer it only when the rule governs that point in the work
|
||||
whatever the work is about, as a question with your reason; a rule about a
|
||||
subject (a library, a file, a style) is reached by meaning, and the line is
|
||||
left alone. Record their answer with `judge_rule_moments` — `confirm` mounts
|
||||
the rule, `reject` with their reason stops the question being asked again.
|
||||
|
||||
The same tool answers proposals from a pass over the rules
|
||||
(`rules_to_mount`, `propose_rule_moments`, `rule_moment_proposals`): a pass
|
||||
|
||||
Reference in New Issue
Block a user