arkaos 2.75.0 → 2.76.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/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.76.0
|
package/config/hooks/stop.sh
CHANGED
|
@@ -219,6 +219,38 @@ try:
|
|
|
219
219
|
except Exception:
|
|
220
220
|
pass
|
|
221
221
|
|
|
222
|
+
# PR59 v2.76.0 — Closing-marker soft block. Telemetry analysis showed
|
|
223
|
+
# 0% [arka:phase:13]/[arka:trivial] rate on flow-required turns. Persist
|
|
224
|
+
# result to /tmp/arkaos-closing/<session>.json so the next
|
|
225
|
+
# UserPromptSubmit can surface a nudge if missing.
|
|
226
|
+
closing_check_passed = True
|
|
227
|
+
closing_check_reason = "trivial"
|
|
228
|
+
closing_check_suggestion: str | None = None
|
|
229
|
+
try:
|
|
230
|
+
from core.governance.closing_marker_check import check_closing_marker
|
|
231
|
+
cmr = check_closing_marker(last)
|
|
232
|
+
closing_check_passed = cmr.passed
|
|
233
|
+
closing_check_reason = cmr.reason
|
|
234
|
+
closing_check_suggestion = cmr.suggestion
|
|
235
|
+
if safe_sid:
|
|
236
|
+
prev_umask = os.umask(0o077)
|
|
237
|
+
try:
|
|
238
|
+
closing_dir = Path("/tmp/arkaos-closing")
|
|
239
|
+
closing_dir.mkdir(parents=True, exist_ok=True)
|
|
240
|
+
closing_path = closing_dir / f"{safe_sid}.json"
|
|
241
|
+
closing_path.write_text(
|
|
242
|
+
json.dumps({
|
|
243
|
+
"passed": cmr.passed,
|
|
244
|
+
"reason": cmr.reason,
|
|
245
|
+
"suggestion": cmr.suggestion,
|
|
246
|
+
}),
|
|
247
|
+
encoding="utf-8",
|
|
248
|
+
)
|
|
249
|
+
finally:
|
|
250
|
+
os.umask(prev_umask)
|
|
251
|
+
except Exception:
|
|
252
|
+
pass
|
|
253
|
+
|
|
222
254
|
entry = {
|
|
223
255
|
"ts": datetime.now(timezone.utc).isoformat(),
|
|
224
256
|
"session_id": session_id,
|
|
@@ -237,6 +269,9 @@ entry = {
|
|
|
237
269
|
"kb_cite_topic_score": cite_topic_score,
|
|
238
270
|
"meta_tag_check_passed": meta_passed,
|
|
239
271
|
"meta_tag_check_reason": meta_reason,
|
|
272
|
+
# PR59 v2.76.0 — Closing-marker soft-block telemetry.
|
|
273
|
+
"closing_marker_check_passed": closing_check_passed,
|
|
274
|
+
"closing_marker_check_reason": closing_check_reason,
|
|
240
275
|
# PR46 v2.65.0 — Claude Code effort level captured for later analysis
|
|
241
276
|
# of nudge-suppression rates. Unset / unknown values land as "".
|
|
242
277
|
"effort_level": os.environ.get("EFFORT_LEVEL_VAL", ""),
|
|
@@ -426,6 +426,24 @@ if [ -n "$SESSION_ID" ] && [ "$_ARKA_SURFACE_NUDGES" = "true" ]; then
|
|
|
426
426
|
fi
|
|
427
427
|
fi
|
|
428
428
|
|
|
429
|
+
# ─── Closing-marker nudge (PR59 v2.76.0) ─────────────────────────────────
|
|
430
|
+
# Mirror of meta-tag nudge but for [arka:phase:13] / [arka:trivial]
|
|
431
|
+
# closing markers. One-shot; deleted after read.
|
|
432
|
+
_CLOSING_MARKER_NUDGE=""
|
|
433
|
+
if [ -n "$SESSION_ID" ] && [ "$_ARKA_SURFACE_NUDGES" = "true" ]; then
|
|
434
|
+
_CLOSING_FILE="/tmp/arkaos-closing/${SESSION_ID}.json"
|
|
435
|
+
if [ -f "$_CLOSING_FILE" ]; then
|
|
436
|
+
if command -v jq &>/dev/null; then
|
|
437
|
+
_CLOSING_PASSED=$(jq -r '.passed' "$_CLOSING_FILE" 2>/dev/null)
|
|
438
|
+
_CLOSING_SUGGEST=$(jq -r '.suggestion // ""' "$_CLOSING_FILE" 2>/dev/null)
|
|
439
|
+
if [ "$_CLOSING_PASSED" = "false" ] && [ -n "$_CLOSING_SUGGEST" ] && [ "$_CLOSING_SUGGEST" != "null" ]; then
|
|
440
|
+
_CLOSING_MARKER_NUDGE="[arka:suggest] ${_CLOSING_SUGGEST}"
|
|
441
|
+
fi
|
|
442
|
+
fi
|
|
443
|
+
rm -f "$_CLOSING_FILE" 2>/dev/null
|
|
444
|
+
fi
|
|
445
|
+
fi
|
|
446
|
+
|
|
429
447
|
# ─── Output ──────────────────────────────────────────────────────────────
|
|
430
448
|
_OUT_CONTEXT="${_ARKA_GREETING:-}${_SYNC_NOTICE:-}${_ROUTE_REMINDER}${_WORKFLOW_DIRECTIVE} $python_result"
|
|
431
449
|
[ -n "$_HYGIENE" ] && _OUT_CONTEXT="$_OUT_CONTEXT $_HYGIENE"
|
|
@@ -433,6 +451,8 @@ _OUT_CONTEXT="${_ARKA_GREETING:-}${_SYNC_NOTICE:-}${_ROUTE_REMINDER}${_WORKFLOW_
|
|
|
433
451
|
$_KB_CITE_NUDGE"
|
|
434
452
|
[ -n "$_META_TAG_NUDGE" ] && _OUT_CONTEXT="$_OUT_CONTEXT
|
|
435
453
|
$_META_TAG_NUDGE"
|
|
454
|
+
[ -n "$_CLOSING_MARKER_NUDGE" ] && _OUT_CONTEXT="$_OUT_CONTEXT
|
|
455
|
+
$_CLOSING_MARKER_NUDGE"
|
|
436
456
|
[ -n "$_ARKA_CONTEXT_HITS" ] && _OUT_CONTEXT="$_OUT_CONTEXT
|
|
437
457
|
$_ARKA_CONTEXT_HITS"
|
|
438
458
|
# Escape for JSON
|
|
Binary file
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""[arka:phase:13] / [arka:trivial] closing-marker soft-block (PR59 v2.76.0).
|
|
2
|
+
|
|
3
|
+
Response-side classifier. Inspects the closing assistant message of a
|
|
4
|
+
flow-required turn for the mandatory closure marker — either
|
|
5
|
+
``[arka:phase:13]`` (full flow completed) or ``[arka:trivial]``
|
|
6
|
+
(trivial bypass). Mirrors the contract of
|
|
7
|
+
``core.governance.meta_tag_check`` (PR30 v2.49.0) and
|
|
8
|
+
``core.governance.kb_cite_check`` (PR18 v2.40.0).
|
|
9
|
+
|
|
10
|
+
Telemetry analysis from the May 24-25 continuous-build session showed
|
|
11
|
+
**0% closing-marker rate** on every flow-required turn (5/5 rows
|
|
12
|
+
without ``[arka:phase:13]`` or ``[arka:trivial]``). PR59 surfaces the
|
|
13
|
+
gap to the next-turn nudge layer so the model is reminded to close
|
|
14
|
+
each flow-required turn with an explicit marker.
|
|
15
|
+
|
|
16
|
+
Soft-block contract — never raises. Hooks consume ClosingMarkerResult
|
|
17
|
+
and decide whether to surface a suggestion.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import re
|
|
23
|
+
from dataclasses import dataclass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
_PHASE13_RE: re.Pattern[str] = re.compile(r"\[arka:phase:13\]", re.IGNORECASE)
|
|
27
|
+
_TRIVIAL_RE: re.Pattern[str] = re.compile(r"\[arka:trivial\]", re.IGNORECASE)
|
|
28
|
+
_TRIVIAL_WORD_THRESHOLD: int = 15
|
|
29
|
+
_SUGGESTION_TEXT: str = (
|
|
30
|
+
"Closing marker missing — end every flow-required turn with "
|
|
31
|
+
"`[arka:phase:13] <label>` (full canonical flow) or "
|
|
32
|
+
"`[arka:trivial] <reason>` (single-file edit < 10 lines, "
|
|
33
|
+
"imperative verb). Without the marker, telemetry can't confirm "
|
|
34
|
+
"the turn closed cleanly."
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class ClosingMarkerResult:
|
|
40
|
+
"""Verdict of a closing-marker check. Immutable; safe to log as JSON."""
|
|
41
|
+
|
|
42
|
+
passed: bool
|
|
43
|
+
reason: str
|
|
44
|
+
suggestion: str | None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def check_closing_marker(response_text: str) -> ClosingMarkerResult:
|
|
48
|
+
"""Classify whether a response carries a closing flow marker.
|
|
49
|
+
|
|
50
|
+
Order matters: a SHORT response *with* a marker still counts as
|
|
51
|
+
`present` — the trivial-length bypass only short-circuits when no
|
|
52
|
+
marker is found.
|
|
53
|
+
"""
|
|
54
|
+
text = response_text or ""
|
|
55
|
+
if _PHASE13_RE.search(text):
|
|
56
|
+
return ClosingMarkerResult(True, "phase13", None)
|
|
57
|
+
if _TRIVIAL_RE.search(text):
|
|
58
|
+
return ClosingMarkerResult(True, "trivial", None)
|
|
59
|
+
if _is_trivial_length(text):
|
|
60
|
+
return ClosingMarkerResult(True, "trivial-length", None)
|
|
61
|
+
return ClosingMarkerResult(False, "missing", _SUGGESTION_TEXT)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _is_trivial_length(text: str) -> bool:
|
|
65
|
+
return len(text.split()) < _TRIVIAL_WORD_THRESHOLD
|
package/package.json
CHANGED