arkaos 2.74.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.74.0
1
+ 2.76.0
@@ -33,7 +33,14 @@ arka_wf_safe_session_id() {
33
33
 
34
34
  # Verb + noun patterns shared with the original inline classifier in
35
35
  # user-prompt-submit.sh. Keep in sync when adding new intent verbs.
36
- ARKA_WF_VERB_PATTERN='(criar?|crie[ms]?|cria[mr]?|adicionar?|adiciona[mr]?|implementar?|implementa[mr]?|desenvolver?|desenvolve[mr]?|construir?|constru[ií]a?[mr]?|fazer?|faz[ae][mr]?|refactor(izar?)?|corrigir?|corrige[mr]?|consertar?|conserta[mr]?|create[sd]?|creating|build(s|ing)?|add(s|ed|ing)?|implement(s|ed|ing)?|develop(s|ed|ing)?|fix(es|ed|ing)?|refactor(s|ed|ing)?|make[sd]?|making)'
36
+ #
37
+ # PR58 v2.75.0 — pattern widened with continuation + ship verbs after
38
+ # telemetry analysis showed 97% of prompts in a 30h continuous-build
39
+ # session were classified "classifier-did-not-match". Most of the
40
+ # missed prompts were short continuations ("continua", "força") or
41
+ # ship-tier verbs ("ship", "publish", "merge", "release", "deploy")
42
+ # that prolong existing flow-required activity.
43
+ ARKA_WF_VERB_PATTERN='(criar?|crie[ms]?|cria[mr]?|adicionar?|adiciona[mr]?|implementar?|implementa[mr]?|desenvolver?|desenvolve[mr]?|construir?|constru[ií]a?[mr]?|fazer?|faz[ae]?[mr]?|refactor(izar?)?|corrigir?|corrige[mr]?|consertar?|conserta[mr]?|continuar?|continua[mr]?|forçar?|força[mr]?|colocar?|coloca[mr]?|p[oô]r|melhorar?|melhora[mr]?|terminar?|termina[mr]?|acabar?|acaba[mr]?|publicar?|publica[mr]?|lançar?|lança[mr]?|create[sd]?|creating|build(s|ing)?|add(s|ed|ing)?|implement(s|ed|ing)?|develop(s|ed|ing)?|fix(es|ed|ing)?|refactor(s|ed|ing)?|make[sd]?|making|continue[sd]?|continuing|ship(s|ped|ping)?|merge[sd]?|merging|publish(es|ed|ing)?|release[sd]?|releasing|deploy(s|ed|ing)?|finish(es|ed|ing)?|improve[sd]?|improving)'
37
44
 
38
45
  # Classify: returns "true" if the prompt looks like a creation/
39
46
  # implementation/modification request, "false" otherwise.
@@ -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
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "arkaos",
3
- "version": "2.74.0",
3
+ "version": "2.76.0",
4
4
  "description": "The Operating System for AI Agent Teams",
5
5
  "type": "module",
6
6
  "bin": {
package/pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "arkaos-core"
3
- version = "2.74.0"
3
+ version = "2.76.0"
4
4
  description = "Core engine for ArkaOS — The Operating System for AI Agent Teams"
5
5
  readme = "README.md"
6
6
  license = {text = "MIT"}