lithermes-ai 0.5.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/LICENSE +21 -0
- package/README.md +245 -0
- package/README_Ko-KR.md +245 -0
- package/assets/lithermes-plugin/NOTICE.md +37 -0
- package/assets/lithermes-plugin/README.md +40 -0
- package/assets/lithermes-plugin/__init__.py +179 -0
- package/assets/lithermes-plugin/core.py +853 -0
- package/assets/lithermes-plugin/litgoal/__init__.py +10 -0
- package/assets/lithermes-plugin/litgoal/cli.py +133 -0
- package/assets/lithermes-plugin/litgoal/hook.py +48 -0
- package/assets/lithermes-plugin/litgoal/model.py +171 -0
- package/assets/lithermes-plugin/litgoal/runtime.py +273 -0
- package/assets/lithermes-plugin/litgoal/store.py +93 -0
- package/assets/lithermes-plugin/litgoal/tools.py +228 -0
- package/assets/lithermes-plugin/payload-version.json +471 -0
- package/assets/lithermes-plugin/plugin.yaml +9 -0
- package/assets/lithermes-plugin/skills/ai-slop-remover/SKILL.md +142 -0
- package/assets/lithermes-plugin/skills/comment-checker/SKILL.md +50 -0
- package/assets/lithermes-plugin/skills/debugging/SKILL.md +116 -0
- package/assets/lithermes-plugin/skills/debugging/references/methodology/00-setup.md +108 -0
- package/assets/lithermes-plugin/skills/debugging/references/methodology/02-investigate.md +121 -0
- package/assets/lithermes-plugin/skills/debugging/references/methodology/04-oracle-triple.md +136 -0
- package/assets/lithermes-plugin/skills/debugging/references/methodology/05-escalate.md +69 -0
- package/assets/lithermes-plugin/skills/debugging/references/methodology/06-fix.md +116 -0
- package/assets/lithermes-plugin/skills/debugging/references/methodology/08-qa.md +94 -0
- package/assets/lithermes-plugin/skills/debugging/references/methodology/09-cleanup.md +164 -0
- package/assets/lithermes-plugin/skills/debugging/references/methodology/partial-runtime-evidence.md +229 -0
- package/assets/lithermes-plugin/skills/debugging/references/runtimes/bundled-js-binary.md +415 -0
- package/assets/lithermes-plugin/skills/debugging/references/runtimes/go.md +252 -0
- package/assets/lithermes-plugin/skills/debugging/references/runtimes/native-binary.md +484 -0
- package/assets/lithermes-plugin/skills/debugging/references/runtimes/node.md +260 -0
- package/assets/lithermes-plugin/skills/debugging/references/runtimes/python.md +248 -0
- package/assets/lithermes-plugin/skills/debugging/references/runtimes/rust.md +234 -0
- package/assets/lithermes-plugin/skills/debugging/references/tools/ghidra.md +212 -0
- package/assets/lithermes-plugin/skills/debugging/references/tools/playwright-cli.md +194 -0
- package/assets/lithermes-plugin/skills/debugging/references/tools/pwndbg.md +263 -0
- package/assets/lithermes-plugin/skills/debugging/references/tools/pwntools.md +265 -0
- package/assets/lithermes-plugin/skills/frontend-ui-ux/SKILL.md +77 -0
- package/assets/lithermes-plugin/skills/lit-plan/SKILL.md +374 -0
- package/assets/lithermes-plugin/skills/litgoal/.gitkeep +0 -0
- package/assets/lithermes-plugin/skills/litgoal/SKILL.md +207 -0
- package/assets/lithermes-plugin/skills/litwork/SKILL.md +262 -0
- package/assets/lithermes-plugin/skills/lsp/SKILL.md +53 -0
- package/assets/lithermes-plugin/skills/programming/SKILL.md +463 -0
- package/assets/lithermes-plugin/skills/programming/references/go/README.md +90 -0
- package/assets/lithermes-plugin/skills/programming/references/go/backend-stack.md +641 -0
- package/assets/lithermes-plugin/skills/programming/references/go/bootstrap.md +328 -0
- package/assets/lithermes-plugin/skills/programming/references/go/bubbletea-v2.md +360 -0
- package/assets/lithermes-plugin/skills/programming/references/go/cobra-stack.md +468 -0
- package/assets/lithermes-plugin/skills/programming/references/go/concurrency.md +362 -0
- package/assets/lithermes-plugin/skills/programming/references/go/data-modeling.md +329 -0
- package/assets/lithermes-plugin/skills/programming/references/go/error-handling.md +359 -0
- package/assets/lithermes-plugin/skills/programming/references/go/golangci-strict.md +236 -0
- package/assets/lithermes-plugin/skills/programming/references/go/grpc-connect.md +375 -0
- package/assets/lithermes-plugin/skills/programming/references/go/libraries.md +337 -0
- package/assets/lithermes-plugin/skills/programming/references/go/one-liners.md +202 -0
- package/assets/lithermes-plugin/skills/programming/references/go/sqlc-pgx.md +471 -0
- package/assets/lithermes-plugin/skills/programming/references/go/testing.md +467 -0
- package/assets/lithermes-plugin/skills/programming/references/go/type-patterns.md +298 -0
- package/assets/lithermes-plugin/skills/programming/references/python/README.md +314 -0
- package/assets/lithermes-plugin/skills/programming/references/python/async-anyio.md +442 -0
- package/assets/lithermes-plugin/skills/programming/references/python/data-modeling.md +233 -0
- package/assets/lithermes-plugin/skills/programming/references/python/data-processing.md +133 -0
- package/assets/lithermes-plugin/skills/programming/references/python/error-handling.md +218 -0
- package/assets/lithermes-plugin/skills/programming/references/python/fastapi-stack.md +316 -0
- package/assets/lithermes-plugin/skills/programming/references/python/httpx2-optimization.md +360 -0
- package/assets/lithermes-plugin/skills/programming/references/python/libraries.md +307 -0
- package/assets/lithermes-plugin/skills/programming/references/python/one-liners.md +268 -0
- package/assets/lithermes-plugin/skills/programming/references/python/orjson-stack.md +378 -0
- package/assets/lithermes-plugin/skills/programming/references/python/pydantic-ai.md +285 -0
- package/assets/lithermes-plugin/skills/programming/references/python/pyproject-strict.md +232 -0
- package/assets/lithermes-plugin/skills/programming/references/python/textual-tui.md +201 -0
- package/assets/lithermes-plugin/skills/programming/references/python/type-patterns.md +176 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/README.md +317 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/async-tokio.md +299 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/axum-stack.md +467 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/cargo-strict.md +317 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/clap-stack.md +409 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/concurrency.md +375 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/libraries.md +439 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/one-liners.md +291 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/proptest-insta.md +429 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/type-state.md +354 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/unsafe-discipline.md +250 -0
- package/assets/lithermes-plugin/skills/programming/references/rust/zero-cost-safety.md +527 -0
- package/assets/lithermes-plugin/skills/programming/references/rust-ub/README.md +289 -0
- package/assets/lithermes-plugin/skills/programming/references/rust-ub/miri-sanitizers-loom.md +411 -0
- package/assets/lithermes-plugin/skills/programming/references/rust-ub/ub-taxonomy.md +269 -0
- package/assets/lithermes-plugin/skills/programming/references/typescript/README.md +195 -0
- package/assets/lithermes-plugin/skills/programming/references/typescript/backend-hono.md +672 -0
- package/assets/lithermes-plugin/skills/programming/references/typescript/bootstrap.md +199 -0
- package/assets/lithermes-plugin/skills/programming/references/typescript/data-modeling.md +202 -0
- package/assets/lithermes-plugin/skills/programming/references/typescript/error-handling.md +169 -0
- package/assets/lithermes-plugin/skills/programming/references/typescript/tsconfig-strict.md +152 -0
- package/assets/lithermes-plugin/skills/programming/references/typescript/type-patterns.md +196 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/check-no-excuse-rules.sh +173 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/new-project.py +138 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/templates/.editorconfig +13 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/templates/.golangci.yml +95 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/templates/AGENTS.md.tmpl +24 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/templates/README.md.tmpl +12 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/templates/Taskfile.yml +40 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/templates/ci.yml +37 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/templates/config.go +24 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/templates/gitignore +15 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/templates/main.go.tmpl +22 -0
- package/assets/lithermes-plugin/skills/programming/scripts/go/templates/run.go +15 -0
- package/assets/lithermes-plugin/skills/programming/scripts/python/check-no-excuse-rules.py +687 -0
- package/assets/lithermes-plugin/skills/programming/scripts/python/new-project.py +172 -0
- package/assets/lithermes-plugin/skills/programming/scripts/python/new-script.py +116 -0
- package/assets/lithermes-plugin/skills/programming/scripts/rust/check-no-excuse-rules.py +296 -0
- package/assets/lithermes-plugin/skills/programming/scripts/rust/check-no-excuse-rules.sh +158 -0
- package/assets/lithermes-plugin/skills/programming/scripts/rust/new-project.py +175 -0
- package/assets/lithermes-plugin/skills/programming/scripts/typescript/check-no-excuse-rules.ts +282 -0
- package/assets/lithermes-plugin/skills/programming/scripts/typescript/new-project.ts +177 -0
- package/assets/lithermes-plugin/skills/refactor/SKILL.md +770 -0
- package/assets/lithermes-plugin/skills/remove-ai-slops/SKILL.md +335 -0
- package/assets/lithermes-plugin/skills/review-work/SKILL.md +562 -0
- package/assets/lithermes-plugin/skills/rules/SKILL.md +41 -0
- package/assets/lithermes-plugin/skills/start-work/SKILL.md +332 -0
- package/bin/lithermes.js +8 -0
- package/cover.png +0 -0
- package/package.json +39 -0
- package/src/cli.js +129 -0
- package/src/lib/check.js +94 -0
- package/src/lib/config.js +170 -0
- package/src/lib/files.js +65 -0
- package/src/lib/hermesDiscovery.js +50 -0
- package/src/lib/hud.js +121 -0
- package/src/lib/install.js +159 -0
- package/src/lib/patch.js +153 -0
- package/src/lib/skins.js +113 -0
- package/src/lib/spinner.js +104 -0
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Path resolution + atomic persistence for the litgoal durable runtime."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import os
|
|
7
|
+
import tempfile
|
|
8
|
+
from datetime import datetime, timezone
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from . import model
|
|
13
|
+
|
|
14
|
+
# Anchor every litgoal path under the constant declared in core (dual-context).
|
|
15
|
+
try: # installed as lithermes.litgoal.store
|
|
16
|
+
from ..core import LITGOAL_STATE_DIRNAME
|
|
17
|
+
except (ImportError, ModuleNotFoundError): # pragma: no cover - standalone import fallback
|
|
18
|
+
try:
|
|
19
|
+
from core import LITGOAL_STATE_DIRNAME # type: ignore
|
|
20
|
+
except (ImportError, ModuleNotFoundError):
|
|
21
|
+
LITGOAL_STATE_DIRNAME = "litgoal"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _utc_now() -> str:
|
|
25
|
+
return datetime.now(timezone.utc).isoformat()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def state_dir(workspace: Path) -> Path:
|
|
29
|
+
return Path(workspace) / ".hermes" / "lithermes" / LITGOAL_STATE_DIRNAME
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def goals_path(workspace: Path) -> Path:
|
|
33
|
+
return state_dir(workspace) / "goals.json"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def ledger_path(workspace: Path) -> Path:
|
|
37
|
+
return state_dir(workspace) / "ledger.jsonl"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def evidence_dir(workspace: Path) -> Path:
|
|
41
|
+
return state_dir(workspace) / "evidence"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def brief_path(workspace: Path) -> Path:
|
|
45
|
+
return state_dir(workspace) / "brief.md"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def load_or_create(workspace: Path) -> model.LitgoalState:
|
|
49
|
+
path = goals_path(workspace)
|
|
50
|
+
if path.exists():
|
|
51
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
52
|
+
return model.LitgoalState.from_dict(data)
|
|
53
|
+
return model.LitgoalState(created_at=_utc_now(), updated_at=_utc_now())
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def save(workspace: Path, state: model.LitgoalState) -> None:
|
|
57
|
+
state.updated_at = _utc_now()
|
|
58
|
+
if not state.created_at:
|
|
59
|
+
state.created_at = state.updated_at
|
|
60
|
+
target = goals_path(workspace)
|
|
61
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
62
|
+
payload = json.dumps(model.to_dict(state), indent=2, sort_keys=False, ensure_ascii=False)
|
|
63
|
+
# Atomic: write to a temp file in the same dir, fsync, then os.replace.
|
|
64
|
+
fd, tmp_name = tempfile.mkstemp(dir=str(target.parent), suffix=".tmp")
|
|
65
|
+
try:
|
|
66
|
+
with os.fdopen(fd, "w", encoding="utf-8") as handle:
|
|
67
|
+
handle.write(payload + "\n")
|
|
68
|
+
handle.flush()
|
|
69
|
+
os.fsync(handle.fileno())
|
|
70
|
+
os.replace(tmp_name, target)
|
|
71
|
+
# Best-effort: fsync the parent directory so the rename is durable.
|
|
72
|
+
try:
|
|
73
|
+
dir_fd = os.open(str(target.parent), os.O_RDONLY)
|
|
74
|
+
try:
|
|
75
|
+
os.fsync(dir_fd)
|
|
76
|
+
finally:
|
|
77
|
+
os.close(dir_fd)
|
|
78
|
+
except (OSError, PermissionError):
|
|
79
|
+
pass # platforms that disallow dir-fsync degrade silently
|
|
80
|
+
finally:
|
|
81
|
+
if os.path.exists(tmp_name):
|
|
82
|
+
os.remove(tmp_name)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def append_ledger(workspace: Path, event: dict[str, Any]) -> None:
|
|
86
|
+
path = ledger_path(workspace)
|
|
87
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
88
|
+
entry = {"at": _utc_now(), **event}
|
|
89
|
+
# NOTE: ledger appends are best-effort append-durable; no fsync here to keep
|
|
90
|
+
# high-frequency event writes cheap. Data loss on crash is limited to the
|
|
91
|
+
# last unflushed entry; goals.json (the source of truth) is fsync-durable.
|
|
92
|
+
with path.open("a", encoding="utf-8") as handle:
|
|
93
|
+
handle.write(json.dumps(entry, ensure_ascii=False) + "\n")
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
"""Model-facing litgoal tools (registered via ctx.register_tool).
|
|
2
|
+
|
|
3
|
+
These layer durable criteria/evidence/checkpoint/steering/gate tracking on top of
|
|
4
|
+
Hermes' native goal system. They operate on the current workspace (cwd). Each
|
|
5
|
+
returns a JSON string for the model.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any, Callable
|
|
13
|
+
|
|
14
|
+
from . import model, runtime, store
|
|
15
|
+
|
|
16
|
+
TOOLSET = "lithermes-goal"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _workspace() -> Path:
|
|
20
|
+
return Path.cwd()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _json(obj: Any) -> str:
|
|
24
|
+
return json.dumps(obj, ensure_ascii=False, indent=2)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _snapshot(workspace: Path) -> dict[str, Any]:
|
|
28
|
+
goal = runtime.get_active(workspace)
|
|
29
|
+
if goal is None:
|
|
30
|
+
return {"active_goal": None}
|
|
31
|
+
gate = runtime.quality_gate(workspace)
|
|
32
|
+
return {
|
|
33
|
+
"active_goal": {
|
|
34
|
+
"id": goal.id,
|
|
35
|
+
"objective": goal.objective,
|
|
36
|
+
"title": goal.title,
|
|
37
|
+
"status": goal.status,
|
|
38
|
+
"criteria": [
|
|
39
|
+
{
|
|
40
|
+
"id": c.id,
|
|
41
|
+
"scenario": c.scenario,
|
|
42
|
+
"qa_channel": c.qa_channel,
|
|
43
|
+
"test_ref": c.test_ref,
|
|
44
|
+
"status": c.status,
|
|
45
|
+
"evidence_kinds": sorted({e.kind for e in c.evidence}),
|
|
46
|
+
}
|
|
47
|
+
for c in goal.criteria
|
|
48
|
+
],
|
|
49
|
+
"unresolved_blockers": [b.id for b in goal.review_blockers if not b.resolved],
|
|
50
|
+
},
|
|
51
|
+
"quality_gate": gate,
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# -- tool handlers (args: dict) -> str --------------------------------------
|
|
56
|
+
|
|
57
|
+
def tool_goal_status(args: dict | None = None, **kwargs) -> str:
|
|
58
|
+
return _json(_snapshot(_workspace()))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def tool_goal_set(args: dict, **kwargs) -> str:
|
|
62
|
+
ws = _workspace()
|
|
63
|
+
objective = str((args or {}).get("objective", "")).strip()
|
|
64
|
+
title = str((args or {}).get("title", "")).strip()
|
|
65
|
+
criteria = (args or {}).get("criteria") or []
|
|
66
|
+
runtime.create_goal(ws, objective, title=title, criteria=criteria)
|
|
67
|
+
return _json(_snapshot(ws))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def tool_goal_add_criterion(args: dict, **kwargs) -> str:
|
|
71
|
+
ws = _workspace()
|
|
72
|
+
crit = runtime.add_criterion(
|
|
73
|
+
ws,
|
|
74
|
+
str((args or {}).get("scenario", "")),
|
|
75
|
+
qa_channel=str((args or {}).get("qa_channel", "")),
|
|
76
|
+
test_ref=str((args or {}).get("test_ref", "")),
|
|
77
|
+
)
|
|
78
|
+
return _json({"criterion_id": crit.id, **_snapshot(ws)})
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def tool_goal_evidence(args: dict, **kwargs) -> str:
|
|
82
|
+
ws = _workspace()
|
|
83
|
+
runtime.add_evidence(
|
|
84
|
+
ws,
|
|
85
|
+
str((args or {}).get("criterion_id", "")),
|
|
86
|
+
str((args or {}).get("kind", "note")),
|
|
87
|
+
str((args or {}).get("ref", "")),
|
|
88
|
+
str((args or {}).get("detail", "")),
|
|
89
|
+
)
|
|
90
|
+
return _json(_snapshot(ws))
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def tool_goal_criterion_status(args: dict, **kwargs) -> str:
|
|
94
|
+
ws = _workspace()
|
|
95
|
+
runtime.set_criterion_status(
|
|
96
|
+
ws, str((args or {}).get("criterion_id", "")), str((args or {}).get("status", ""))
|
|
97
|
+
)
|
|
98
|
+
return _json(_snapshot(ws))
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def tool_goal_steer(args: dict, **kwargs) -> str:
|
|
102
|
+
ws = _workspace()
|
|
103
|
+
try:
|
|
104
|
+
runtime.record_steering(
|
|
105
|
+
ws,
|
|
106
|
+
str((args or {}).get("directive", "")),
|
|
107
|
+
kind=str((args or {}).get("kind", "redirect")) or "redirect",
|
|
108
|
+
)
|
|
109
|
+
except ValueError as exc:
|
|
110
|
+
return _json({"rejected": True, "reason": str(exc), **_snapshot(ws)})
|
|
111
|
+
return _json(_snapshot(ws))
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def tool_goal_checkpoint(args: dict, **kwargs) -> str:
|
|
115
|
+
ws = _workspace()
|
|
116
|
+
runtime.record_checkpoint(
|
|
117
|
+
ws,
|
|
118
|
+
str((args or {}).get("summary", "")),
|
|
119
|
+
active_criterion=str((args or {}).get("active_criterion", "")),
|
|
120
|
+
)
|
|
121
|
+
return _json(_snapshot(ws))
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def tool_goal_complete(args: dict | None = None, **kwargs) -> str:
|
|
125
|
+
return _json(runtime.complete_goal(_workspace()))
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def _spec(name: str, description: str, handler: Callable, properties: dict, required: list[str]) -> dict:
|
|
129
|
+
return {
|
|
130
|
+
"name": name,
|
|
131
|
+
"toolset": TOOLSET,
|
|
132
|
+
"description": description,
|
|
133
|
+
"handler": handler,
|
|
134
|
+
"schema": {
|
|
135
|
+
"type": "object",
|
|
136
|
+
"properties": properties,
|
|
137
|
+
"required": required,
|
|
138
|
+
"additionalProperties": False,
|
|
139
|
+
},
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
TOOL_SPECS: list[dict] = [
|
|
144
|
+
_spec("goal_status", "Show the active LitHermes litgoal, its criteria, evidence, and quality gate.", tool_goal_status, {}, []),
|
|
145
|
+
_spec(
|
|
146
|
+
"goal_set",
|
|
147
|
+
"Create the active litgoal with an objective and optional upfront success criteria.",
|
|
148
|
+
tool_goal_set,
|
|
149
|
+
{
|
|
150
|
+
"objective": {"type": "string", "description": "the concrete user-visible objective"},
|
|
151
|
+
"title": {"type": "string"},
|
|
152
|
+
"criteria": {
|
|
153
|
+
"type": "array",
|
|
154
|
+
"items": {
|
|
155
|
+
"type": "object",
|
|
156
|
+
"properties": {
|
|
157
|
+
"scenario": {"type": "string"},
|
|
158
|
+
"qa_channel": {"type": "string", "enum": ["http", "tmux", "browser", "computer", "cli"]},
|
|
159
|
+
"test_ref": {"type": "string"},
|
|
160
|
+
},
|
|
161
|
+
"required": ["scenario"],
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
["objective"],
|
|
166
|
+
),
|
|
167
|
+
_spec(
|
|
168
|
+
"goal_add_criterion",
|
|
169
|
+
"Add one success criterion (scenario + QA channel + test reference) to the active goal.",
|
|
170
|
+
tool_goal_add_criterion,
|
|
171
|
+
{
|
|
172
|
+
"scenario": {"type": "string"},
|
|
173
|
+
"qa_channel": {"type": "string", "enum": ["http", "tmux", "browser", "computer", "cli"]},
|
|
174
|
+
"test_ref": {"type": "string"},
|
|
175
|
+
},
|
|
176
|
+
["scenario"],
|
|
177
|
+
),
|
|
178
|
+
_spec(
|
|
179
|
+
"goal_evidence",
|
|
180
|
+
"Attach evidence (red|green|scenario|cleanup|note) to a criterion.",
|
|
181
|
+
tool_goal_evidence,
|
|
182
|
+
{
|
|
183
|
+
"criterion_id": {"type": "string"},
|
|
184
|
+
"kind": {"type": "string", "enum": ["red", "green", "scenario", "cleanup", "note"]},
|
|
185
|
+
"ref": {"type": "string", "description": "test id or artifact path"},
|
|
186
|
+
"detail": {"type": "string"},
|
|
187
|
+
},
|
|
188
|
+
["criterion_id", "kind", "ref"],
|
|
189
|
+
),
|
|
190
|
+
_spec(
|
|
191
|
+
"goal_criterion_status",
|
|
192
|
+
"Set a criterion status (pending|in_progress|blocked|pass|fail).",
|
|
193
|
+
tool_goal_criterion_status,
|
|
194
|
+
{
|
|
195
|
+
"criterion_id": {"type": "string"},
|
|
196
|
+
"status": {"type": "string", "enum": list(model.CRITERION_STATUSES)},
|
|
197
|
+
},
|
|
198
|
+
["criterion_id", "status"],
|
|
199
|
+
),
|
|
200
|
+
_spec(
|
|
201
|
+
"goal_steer",
|
|
202
|
+
"Record a steering directive that redirects or extends the active goal mid-flight. "
|
|
203
|
+
"Refused if it tries to weaken the completion gate (skip tests/QA/review or auto-complete).",
|
|
204
|
+
tool_goal_steer,
|
|
205
|
+
{
|
|
206
|
+
"directive": {"type": "string"},
|
|
207
|
+
"kind": {"type": "string", "enum": list(model.STEERING_KINDS)},
|
|
208
|
+
},
|
|
209
|
+
["directive"],
|
|
210
|
+
),
|
|
211
|
+
_spec("goal_checkpoint", "Record a durable checkpoint snapshot for resume.", tool_goal_checkpoint, {"summary": {"type": "string"}, "active_criterion": {"type": "string"}}, ["summary"]),
|
|
212
|
+
_spec("goal_complete", "Attempt to complete the goal; refused with reasons unless the quality gate passes.", tool_goal_complete, {}, []),
|
|
213
|
+
]
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def register_tools(ctx) -> list[str]:
|
|
217
|
+
"""Register every litgoal tool on the plugin context. Returns the names."""
|
|
218
|
+
names: list[str] = []
|
|
219
|
+
for spec in TOOL_SPECS:
|
|
220
|
+
ctx.register_tool(
|
|
221
|
+
name=spec["name"],
|
|
222
|
+
toolset=spec["toolset"],
|
|
223
|
+
schema=spec["schema"],
|
|
224
|
+
handler=spec["handler"],
|
|
225
|
+
description=spec["description"],
|
|
226
|
+
)
|
|
227
|
+
names.append(spec["name"])
|
|
228
|
+
return names
|