@tachikomagundam/abathur 0.1.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/.github/workflows/ci.yml +29 -0
- package/.github/workflows/publish.yml +74 -0
- package/LICENSE +21 -0
- package/README.md +461 -0
- package/config/abathur.jsonc +17 -0
- package/config/genomes/historian.example.jsonc +124 -0
- package/dist/bench/adapter.js +201 -0
- package/dist/bench/fixture-probe.js +92 -0
- package/dist/bench/fixture-support.js +173 -0
- package/dist/bench/fixture.js +236 -0
- package/dist/bench/toy.js +152 -0
- package/dist/cli.js +110 -0
- package/dist/commands/bundle.js +79 -0
- package/dist/commands/genome.js +94 -0
- package/dist/commands/graft.js +71 -0
- package/dist/commands/kernel.js +47 -0
- package/dist/commands/promote.js +25 -0
- package/dist/commands/run.js +145 -0
- package/dist/commands/self-eval.js +240 -0
- package/dist/commands/status.js +186 -0
- package/dist/commands/tombstone.js +72 -0
- package/dist/config.js +161 -0
- package/dist/core/bundle-common.js +119 -0
- package/dist/core/bundle-export.js +212 -0
- package/dist/core/bundle-inspect.js +143 -0
- package/dist/core/bundle-manifest.js +105 -0
- package/dist/core/bundle-mask.js +75 -0
- package/dist/core/bundle-tar.js +240 -0
- package/dist/core/bundle.js +9 -0
- package/dist/core/evolve/brief.js +45 -0
- package/dist/core/evolve/candidate.js +140 -0
- package/dist/core/evolve/child-track.js +197 -0
- package/dist/core/evolve/friction.js +150 -0
- package/dist/core/evolve/reflect.js +191 -0
- package/dist/core/evolve/run-bench.js +170 -0
- package/dist/core/evolve/run-friction.js +63 -0
- package/dist/core/evolve/run-loop.js +282 -0
- package/dist/core/evolve/run-plan.js +39 -0
- package/dist/core/evolve/run-rows.js +145 -0
- package/dist/core/evolve/self-overlay.js +213 -0
- package/dist/core/evolve/self-snapshot.js +170 -0
- package/dist/core/evolve/stub-mutators.mjs +105 -0
- package/dist/core/evolve/udiff.js +189 -0
- package/dist/core/genome-paths.js +76 -0
- package/dist/core/genome.js +176 -0
- package/dist/core/glob.js +106 -0
- package/dist/core/graft-gates.js +184 -0
- package/dist/core/graft-rebench.js +187 -0
- package/dist/core/graft-support.js +181 -0
- package/dist/core/graft.js +218 -0
- package/dist/core/ids.js +154 -0
- package/dist/core/incumbent.js +46 -0
- package/dist/core/kernel.js +112 -0
- package/dist/core/ledger.js +198 -0
- package/dist/core/locks.js +172 -0
- package/dist/core/promote.js +119 -0
- package/dist/core/snapshot.js +61 -0
- package/dist/core/spec.js +178 -0
- package/dist/core/stats-math.js +102 -0
- package/dist/core/stats-pareto.js +57 -0
- package/dist/core/stats.js +184 -0
- package/dist/core/worktree.js +190 -0
- package/dist/exit.js +32 -0
- package/dist/genomes/toy-smoke/genome.jsonc +30 -0
- package/dist/genomes/toy-smoke/grader.mjs +61 -0
- package/dist/genomes/toy-smoke/init.mjs +63 -0
- package/dist/genomes/toy-smoke/units/add.mjs +17 -0
- package/dist/genomes/toy-smoke/units/explode.mjs +4 -0
- package/dist/genomes/toy-smoke/units/hang.mjs +16 -0
- package/dist/genomes/toy-smoke/units/mul.mjs +16 -0
- package/dist/genomes/toy-smoke/units/mutate.mjs +18 -0
- package/dist/genomes/toy-smoke/units/sub.mjs +16 -0
- package/dist/jsonc.js +77 -0
- package/dist/out.js +5 -0
- package/dist/test/bench-adapter.test.js +33 -0
- package/dist/test/bench-fixture.test.js +407 -0
- package/dist/test/bench-toy.test.js +251 -0
- package/dist/test/bundle.test.js +659 -0
- package/dist/test/config.test.js +185 -0
- package/dist/test/d7-gate.test.js +56 -0
- package/dist/test/fixture-loop.test.js +267 -0
- package/dist/test/fixtures/friction-writer.js +16 -0
- package/dist/test/fixtures-historian.js +82 -0
- package/dist/test/fixtures-self.js +143 -0
- package/dist/test/fixtures-wt.js +64 -0
- package/dist/test/friction.test.js +398 -0
- package/dist/test/genome.test.js +453 -0
- package/dist/test/git.test.js +69 -0
- package/dist/test/graft.test.js +567 -0
- package/dist/test/historian-genome.test.js +134 -0
- package/dist/test/historian-grader-io.test.js +148 -0
- package/dist/test/historian-grader.test.js +209 -0
- package/dist/test/ids.test.js +116 -0
- package/dist/test/include-val.test.js +120 -0
- package/dist/test/ledger-lock.test.js +99 -0
- package/dist/test/ledger.test.js +102 -0
- package/dist/test/promote.test.js +394 -0
- package/dist/test/reflect.test.js +410 -0
- package/dist/test/run-loop.test.js +433 -0
- package/dist/test/self-snapshot.test.js +328 -0
- package/dist/test/snapshot.test.js +86 -0
- package/dist/test/stats.test.js +423 -0
- package/dist/test/stub-mutators.test.js +17 -0
- package/dist/test/testutil.js +30 -0
- package/dist/test/worktree.test.js +198 -0
- package/dist/util/freeze.js +30 -0
- package/dist/util/git.js +85 -0
- package/docs/federation.md +184 -0
- package/docs/immutable-kernel.md +87 -0
- package/graders/historian/grader-core.d.mts +53 -0
- package/graders/historian/grader-core.mjs +276 -0
- package/graders/historian/grader-support.d.mts +57 -0
- package/graders/historian/grader-support.mjs +137 -0
- package/graders/historian/grader.mjs +113 -0
- package/graders/historian/mutate.sh +114 -0
- package/graders/historian/reset-sandbox.sh +60 -0
- package/graders/historian/run-scenario.sh +49 -0
- package/graders/historian/seed-wrapped.sh +32 -0
- package/package.json +42 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Mutator wrapper for the historian live run (task 14). Invoked by the run-loop
|
|
3
|
+
# as `bash mutate.sh <brief-file> <worktree> <model>` with cwd = the throwaway
|
|
4
|
+
# launch worktree (reflect.ts contract). The REAL candidate source is a headless
|
|
5
|
+
# `opencode run` child: it reads the reflection brief and proposes exactly one
|
|
6
|
+
# mutation — a new markdown note under abathur-notes/ (never a sealed path;
|
|
7
|
+
# kernel.immutableGlobs is enforced independently by the driver's PathPolicy).
|
|
8
|
+
# The wrapper deterministically packages the model's note as a unified CREATE
|
|
9
|
+
# diff (creation diffs have no context to drift) and appends a genome.jsonc
|
|
10
|
+
# create-diff carrying the resolved spec bytes (plan 184: every sealed tree
|
|
11
|
+
# must contain genome.jsonc so bundle export self-describes; plan 181 requires
|
|
12
|
+
# it for the lineage). On unparseable model output the wrapper degrades to a
|
|
13
|
+
# packaging-only candidate — honest, logged, never a fabricated mutation.
|
|
14
|
+
set -uo pipefail
|
|
15
|
+
brief_file="${1:?usage: mutate.sh <brief-file> <worktree> <model>}"
|
|
16
|
+
worktree="${2:?usage: mutate.sh <brief-file> <worktree> <model>}"
|
|
17
|
+
model="${3:?usage: mutate.sh <brief-file> <worktree> <model>}"
|
|
18
|
+
canonical="${ABATHUR_GENOME_CANONICAL:?mutate.sh requires ABATHUR_GENOME_CANONICAL (resolved spec, canonical JSON)}"
|
|
19
|
+
[ -f "$brief_file" ] || { echo "mutate: missing brief $brief_file" >&2; exit 1; }
|
|
20
|
+
cp -f "$brief_file" "${ABATHUR_MUTATOR_RAW:-/tmp/abathur-mutate-raw.jsonl}.brief" 2>/dev/null || true
|
|
21
|
+
[ -f "$canonical" ] || { echo "mutate: missing canonical spec $canonical" >&2; exit 1; }
|
|
22
|
+
bin="${ABATHUR_OPENCODE_BIN:-opencode}"
|
|
23
|
+
|
|
24
|
+
prompt="You are the genome mutator of the Abathur evolution harness. Read the reflection brief below (evidence from the incumbent bench of the historian wiki-skill genome). Propose exactly ONE improvement the genome owner can act on: create a NEW file under the path prefix abathur-notes/ (slug .md). Output ONLY a single JSON object, no prose, shape:
|
|
25
|
+
{\"rationale\": \"<one sentence, <=400 chars>\", \"path\": \"abathur-notes/<slug>.md\", \"content\": \"<full markdown file contents>\"}
|
|
26
|
+
Do not modify any other path. Scenarios, rubric.md, seed_sandbox.sh, baseline/ and README.md are immutable.
|
|
27
|
+
|
|
28
|
+
BRIEF:
|
|
29
|
+
$(cat "$brief_file")"
|
|
30
|
+
|
|
31
|
+
raw="${ABATHUR_MUTATOR_RAW:-/tmp/abathur-mutate-raw.jsonl}"
|
|
32
|
+
"$bin" run --model "$model" --format json --message "$prompt" >"$raw" 2>/dev/null
|
|
33
|
+
rc=$?
|
|
34
|
+
echo "mutate: opencode rc=$rc raw=$raw" >&2
|
|
35
|
+
|
|
36
|
+
python3 - "$raw" "$canonical" "$rc" <<'PY'
|
|
37
|
+
import json, re, sys
|
|
38
|
+
|
|
39
|
+
raw, canonical_path, rc = sys.argv[1], sys.argv[2], int(sys.argv[3])
|
|
40
|
+
|
|
41
|
+
def create_diff(path, text):
|
|
42
|
+
lines = text.split("\n")
|
|
43
|
+
if lines and lines[-1] == "":
|
|
44
|
+
lines.pop()
|
|
45
|
+
body = "".join("+" + ln + "\n" for ln in lines)
|
|
46
|
+
return f"--- /dev/null\n+++ b/{path}\n@@ -0,0 +1,{len(lines)} @@\n{body}"
|
|
47
|
+
|
|
48
|
+
def last_text_events(path):
|
|
49
|
+
texts = []
|
|
50
|
+
try:
|
|
51
|
+
with open(path, encoding="utf-8", errors="replace") as fh:
|
|
52
|
+
for line in fh:
|
|
53
|
+
line = line.strip()
|
|
54
|
+
if not line:
|
|
55
|
+
continue
|
|
56
|
+
try:
|
|
57
|
+
ev = json.loads(line)
|
|
58
|
+
except ValueError:
|
|
59
|
+
continue
|
|
60
|
+
part = ev.get("part") or {}
|
|
61
|
+
if ev.get("type") == "text" and isinstance(part.get("text"), str):
|
|
62
|
+
texts.append(part["text"])
|
|
63
|
+
except FileNotFoundError:
|
|
64
|
+
pass
|
|
65
|
+
return texts
|
|
66
|
+
|
|
67
|
+
proposal = None
|
|
68
|
+
for text in reversed(last_text_events(raw)):
|
|
69
|
+
candidate = text.strip()
|
|
70
|
+
fence = re.search(r"```(?:json)?\s*(\{.*\})\s*```", candidate, re.S)
|
|
71
|
+
if fence:
|
|
72
|
+
candidate = fence.group(1)
|
|
73
|
+
start, end = candidate.find("{"), candidate.rfind("}")
|
|
74
|
+
if start < 0 or end <= start:
|
|
75
|
+
continue
|
|
76
|
+
try:
|
|
77
|
+
doc = json.loads(candidate[start : end + 1])
|
|
78
|
+
except ValueError:
|
|
79
|
+
continue
|
|
80
|
+
if isinstance(doc, dict):
|
|
81
|
+
proposal = doc
|
|
82
|
+
break
|
|
83
|
+
|
|
84
|
+
spec_text = open(canonical_path, encoding="utf-8").read()
|
|
85
|
+
packaging = create_diff("genome.jsonc", spec_text if spec_text.endswith("\n") else spec_text + "\n")
|
|
86
|
+
|
|
87
|
+
if isinstance(proposal, dict):
|
|
88
|
+
path = proposal.get("path")
|
|
89
|
+
content = proposal.get("content")
|
|
90
|
+
rationale = proposal.get("rationale")
|
|
91
|
+
if (
|
|
92
|
+
isinstance(path, str)
|
|
93
|
+
and re.fullmatch(r"abathur-notes/[a-z0-9][a-z0-9._-]{0,63}\.md", path)
|
|
94
|
+
and isinstance(content, str)
|
|
95
|
+
and 0 < len(content) < 200000
|
|
96
|
+
and isinstance(rationale, str)
|
|
97
|
+
and 0 < len(rationale) <= 4000
|
|
98
|
+
and "\x00" not in content
|
|
99
|
+
):
|
|
100
|
+
content = content.replace("\r", "")
|
|
101
|
+
if not content.endswith("\n"):
|
|
102
|
+
content += "\n"
|
|
103
|
+
candidate = {"id": "mutate-live", "rationale": rationale, "diffs": [create_diff(path, content), packaging]}
|
|
104
|
+
print(json.dumps({"candidates": [candidate]}))
|
|
105
|
+
sys.exit(0)
|
|
106
|
+
|
|
107
|
+
print(json.dumps({
|
|
108
|
+
"candidates": [{
|
|
109
|
+
"id": "mutate-package-only",
|
|
110
|
+
"rationale": "packaging-only candidate: model output unparseable or path rejected (opencode rc=%d); lineage genome.jsonc added, no skill mutation proposed" % rc,
|
|
111
|
+
"diffs": [packaging],
|
|
112
|
+
}]
|
|
113
|
+
}))
|
|
114
|
+
PY
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Reset hook (task 14, closes Metis #3): historian's seed_sandbox.sh SKIPs
|
|
3
|
+
# existing pages, so a mutated/consumed _sandbox fixture never self-restores.
|
|
4
|
+
# resetCommand deletes EVERY _sandbox/* page by id (wiki-ops hard delete) and
|
|
5
|
+
# refreshes the wiki cache, making back-to-back generations state-equal.
|
|
6
|
+
# Runs with cwd = the unit sandbox, HOME = sandbox home (key installed by the
|
|
7
|
+
# seed wrapper; mirrorSandboxHome rebuilds the home on reset too, so ensure it).
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
base="${ABATHUR_WIKI_BASE:?reset-sandbox.sh requires ABATHUR_WIKI_BASE in env}"
|
|
10
|
+
ops="${ABATHUR_WIKI_OPS:?reset-sandbox.sh requires ABATHUR_WIKI_OPS in env}"
|
|
11
|
+
key="${ABATHUR_WIKI_KEY_FILE:-}"
|
|
12
|
+
if [ -n "$key" ] && [ -f "$key" ] && [ ! -f "$HOME/.wikijs-api-key" ]; then
|
|
13
|
+
mkdir -p "$HOME"
|
|
14
|
+
install -m 600 "$key" "$HOME/.wikijs-api-key"
|
|
15
|
+
fi
|
|
16
|
+
[ -f "$HOME/.wikijs-api-key" ] || { echo "reset-sandbox: no wiki key at $HOME/.wikijs-api-key" >&2; exit 1; }
|
|
17
|
+
n=0
|
|
18
|
+
while read -r id; do
|
|
19
|
+
[ -n "$id" ] || continue
|
|
20
|
+
if ! python3 "$ops" delete "$id" --confirm >/dev/null 2>&1; then
|
|
21
|
+
# A parent delete cascades to its children: tolerate iff the row is really gone.
|
|
22
|
+
if python3 - "$base" "$id" <<'GONE'
|
|
23
|
+
import json, pathlib, sys, urllib.request
|
|
24
|
+
base, pid = sys.argv[1].rstrip("/"), int(sys.argv[2])
|
|
25
|
+
token = open(pathlib.Path.home() / ".wikijs-api-key").read().strip()
|
|
26
|
+
req = urllib.request.Request(
|
|
27
|
+
base + "/graphql",
|
|
28
|
+
data=json.dumps({"query": "{ pages { single(id: %d) { id } } }" % pid}).encode(),
|
|
29
|
+
headers={"Content-Type": "application/json", "Authorization": "Bearer " + token},
|
|
30
|
+
)
|
|
31
|
+
doc = json.load(urllib.request.urlopen(req, timeout=20))
|
|
32
|
+
single = (doc.get("data") or {}).get("pages") or {}
|
|
33
|
+
raise SystemExit(0 if single.get("single") is None else 1)
|
|
34
|
+
GONE
|
|
35
|
+
then
|
|
36
|
+
echo "reset-sandbox: page $id already gone (cascade)" >&2
|
|
37
|
+
else
|
|
38
|
+
echo "reset-sandbox: delete $id failed" >&2
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
fi
|
|
42
|
+
n=$((n + 1))
|
|
43
|
+
done < <(python3 - "$base" <<'PY'
|
|
44
|
+
import json, pathlib, sys, urllib.request
|
|
45
|
+
base, token = sys.argv[1].rstrip("/"), open(pathlib.Path.home() / ".wikijs-api-key").read().strip()
|
|
46
|
+
req = urllib.request.Request(
|
|
47
|
+
base + "/graphql",
|
|
48
|
+
data=json.dumps({"query": "{ pages { list { id path } } }"}).encode(),
|
|
49
|
+
headers={"Content-Type": "application/json", "Authorization": "Bearer " + token},
|
|
50
|
+
)
|
|
51
|
+
doc = json.load(urllib.request.urlopen(req, timeout=20))
|
|
52
|
+
if "errors" in doc:
|
|
53
|
+
raise SystemExit("reset-sandbox: graphql %s" % json.dumps(doc["errors"])[:200])
|
|
54
|
+
for r in doc["data"]["pages"]["list"]:
|
|
55
|
+
if r["path"] == "_sandbox" or r["path"].startswith("_sandbox/"):
|
|
56
|
+
print(r["id"])
|
|
57
|
+
PY
|
|
58
|
+
)
|
|
59
|
+
python3 "$ops" cache-refresh >/dev/null 2>&1 || true
|
|
60
|
+
echo "reset-sandbox: deleted $n _sandbox page(s), cache refreshed"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Run hook (task 14): spawn the scenario agent headless, record the transcript
|
|
3
|
+
# at $ABATHUR_TRANSCRIPT (adapter contract, plan line 120), and print the last
|
|
4
|
+
# stdout line {tokensEst, turns} for parseRunMeta. opencode is invoked exactly
|
|
5
|
+
# as historian's README prescribes: `opencode run --command historian --message
|
|
6
|
+
# "<scenario Brief>"` — the Brief section of the scenario file is the prompt.
|
|
7
|
+
# --auto auto-approves the plugin tools (the wiki sandbox is the blast radius;
|
|
8
|
+
# kernel seals + _sandbox-only writes bound it, plan todo 14).
|
|
9
|
+
set -euo pipefail
|
|
10
|
+
unit_id="${1:?usage: run-scenario.sh <unitId> <scenario-file>}"
|
|
11
|
+
scenario_file="${2:?usage: run-scenario.sh <unitId> <scenario-file>}"
|
|
12
|
+
[ -f "$scenario_file" ] || { echo "run-scenario: missing scenario file $scenario_file" >&2; exit 2; }
|
|
13
|
+
[ -n "${ABATHUR_TRANSCRIPT:-}" ] || { echo "run-scenario: ABATHUR_TRANSCRIPT not set" >&2; exit 2; }
|
|
14
|
+
key="${ABATHUR_WIKI_KEY_FILE:-}"
|
|
15
|
+
if [ -n "$key" ] && [ -f "$key" ] && [ ! -f "$HOME/.wikijs-api-key" ]; then
|
|
16
|
+
mkdir -p "$HOME"
|
|
17
|
+
install -m 600 "$key" "$HOME/.wikijs-api-key"
|
|
18
|
+
fi
|
|
19
|
+
bin="${opencodeBin:-opencode}"
|
|
20
|
+
brief="$(awk '/^##[[:space:]]*Brief/{f=1;next} f && /^## /{exit} f' "$scenario_file")"
|
|
21
|
+
[ -n "$brief" ] || { echo "run-scenario: empty Brief section in $scenario_file" >&2; exit 2; }
|
|
22
|
+
mkdir -p "$(dirname "$ABATHUR_TRANSCRIPT")"
|
|
23
|
+
status=0
|
|
24
|
+
"$bin" run --command historian --auto --format json --message "$brief" >"$ABATHUR_TRANSCRIPT" 2>/dev/null || status=$?
|
|
25
|
+
python3 - "$ABATHUR_TRANSCRIPT" "$unit_id" "$status" <<'PY'
|
|
26
|
+
import json, sys
|
|
27
|
+
path, unit, status = sys.argv[1], sys.argv[2], int(sys.argv[3])
|
|
28
|
+
tokens = turns = 0
|
|
29
|
+
try:
|
|
30
|
+
with open(path, encoding="utf-8", errors="replace") as fh:
|
|
31
|
+
for line in fh:
|
|
32
|
+
line = line.strip()
|
|
33
|
+
if not line:
|
|
34
|
+
continue
|
|
35
|
+
try:
|
|
36
|
+
ev = json.loads(line)
|
|
37
|
+
except ValueError:
|
|
38
|
+
continue
|
|
39
|
+
part = ev.get("part") or {}
|
|
40
|
+
if ev.get("type") == "step_finish" or part.get("type") == "step-finish":
|
|
41
|
+
turns += 1
|
|
42
|
+
total = (part.get("tokens") or {}).get("total")
|
|
43
|
+
if isinstance(total, (int, float)):
|
|
44
|
+
tokens += int(total)
|
|
45
|
+
except FileNotFoundError:
|
|
46
|
+
pass
|
|
47
|
+
print(json.dumps({"unit": unit, "tokensEst": tokens, "turns": turns, "opencodeExit": status}))
|
|
48
|
+
PY
|
|
49
|
+
exit 0
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Seed hook wrapper (task 14). The fixture adapter runs hooks with
|
|
3
|
+
# HOME=<sandbox>/.sandbox-home; wiki-ops and historian's seed_sandbox.sh read
|
|
4
|
+
# ~/.wikijs-api-key, so the key must land in the sandbox home first. Then the
|
|
5
|
+
# genome repo's own seed_sandbox.sh runs unchanged (plan: seedCommand →
|
|
6
|
+
# seed_sandbox.sh), and the post-seed wiki snapshot is recorded to
|
|
7
|
+
# .bench/wiki-pre.json — the grader diffs created/updated/deleted against it.
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
real_seed="${1:?usage: seed-wrapped.sh <path-to-seed_sandbox.sh>}"
|
|
10
|
+
[ -f "$real_seed" ] || { echo "seed-wrapped: missing $real_seed" >&2; exit 1; }
|
|
11
|
+
base="${ABATHUR_WIKI_BASE:?seed-wrapped.sh requires ABATHUR_WIKI_BASE in env}"
|
|
12
|
+
key="${ABATHUR_WIKI_KEY_FILE:-}"
|
|
13
|
+
if [ -n "$key" ] && [ -f "$key" ] && [ ! -f "$HOME/.wikijs-api-key" ]; then
|
|
14
|
+
mkdir -p "$HOME"
|
|
15
|
+
install -m 600 "$key" "$HOME/.wikijs-api-key"
|
|
16
|
+
fi
|
|
17
|
+
bash "$real_seed"
|
|
18
|
+
mkdir -p .bench
|
|
19
|
+
python3 - "$base" > .bench/wiki-pre.json <<'PY'
|
|
20
|
+
import json, os, pathlib, sys, urllib.request
|
|
21
|
+
base, token = sys.argv[1].rstrip("/"), open(pathlib.Path.home() / ".wikijs-api-key").read().strip()
|
|
22
|
+
req = urllib.request.Request(
|
|
23
|
+
base + "/graphql",
|
|
24
|
+
data=json.dumps({"query": "{ pages { list { id path locale updatedAt } } }"}).encode(),
|
|
25
|
+
headers={"Content-Type": "application/json", "Authorization": "Bearer " + token},
|
|
26
|
+
)
|
|
27
|
+
doc = json.load(urllib.request.urlopen(req, timeout=20))
|
|
28
|
+
if "errors" in doc:
|
|
29
|
+
raise SystemExit("wiki-pre: graphql %s" % json.dumps(doc["errors"])[:200])
|
|
30
|
+
print(json.dumps(doc["data"]["pages"]["list"]))
|
|
31
|
+
PY
|
|
32
|
+
echo "seed-wrapped: wiki-pre.json rows=$(python3 -c 'import json;print(len(json.load(open(".bench/wiki-pre.json"))))')"
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tachikomagundam/abathur",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Evolution harness: observe failures, mutate, re-bench, select — human-gated promotion, offline lineage bundles.",
|
|
5
|
+
"author": "TachikomaGundam",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/TachikomaGundam/Abathur.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/TachikomaGundam/Abathur/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/TachikomaGundam/Abathur#readme",
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=22"
|
|
18
|
+
},
|
|
19
|
+
"bin": {
|
|
20
|
+
"abathur": "dist/cli.js"
|
|
21
|
+
},
|
|
22
|
+
"main": "dist/cli.js",
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"config",
|
|
26
|
+
"graders",
|
|
27
|
+
"docs",
|
|
28
|
+
".github"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc && node scripts/copy-assets.mjs",
|
|
32
|
+
"test": "npm run build && node --test \"dist/test/**/*.test.js\"",
|
|
33
|
+
"prepack": "npm run build"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"zod": "^4.0.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^22.0.0",
|
|
40
|
+
"typescript": "^5.9.0"
|
|
41
|
+
}
|
|
42
|
+
}
|