every command handed to an agent is an order, not a label
'next: memo wake 2 246' is an annotation, not an instruction. ASD-STE100: an instruction is an imperative, verb first. Same defect in the nap prompt, where the command sat on a bare line with nothing telling the agent to run it. The wake terminator is 'You are awake.', the same words memo sleep already used, instead of a bare 'awake.' -- one term, one meaning. test.py now asserts that every offered command starts with 'Run: '.
This commit is contained in:
parent
dc5339c55b
commit
af17f94c2f
3 changed files with 30 additions and 14 deletions
|
|
@ -37,7 +37,7 @@ export MEMORY_DIR="$HOME/memory" # required; there is no default
|
||||||
```sh
|
```sh
|
||||||
memo wake # who you are. run this first, every session,
|
memo wake # who you are. run this first, every session,
|
||||||
# then the command each part names, until
|
# then the command each part names, until
|
||||||
# one of them prints `awake.`
|
# one of them prints `You are awake.`
|
||||||
memo note "..." # record a memory. one line, <= 280 chars.
|
memo note "..." # record a memory. one line, <= 280 chars.
|
||||||
memo sleep # compress. keep going until it says you woke up.
|
memo sleep # compress. keep going until it says you woke up.
|
||||||
memo recall <regex> # search the raw log for detail a summary lost.
|
memo recall <regex> # search the raw log for detail a summary lost.
|
||||||
|
|
|
||||||
6
memo
6
memo
|
|
@ -272,7 +272,7 @@ def nap_prompt(d, lo, hi, left):
|
||||||
"Keep every name, number, date and decision.\n"
|
"Keep every name, number, date and decision.\n"
|
||||||
"Invent nothing. State the facts; do not describe them.\n\n"
|
"Invent nothing. State the facts; do not describe them.\n\n"
|
||||||
"%s\n\n"
|
"%s\n\n"
|
||||||
"memo sleep %d-%d \"<your line>\"\n"
|
"Run: memo sleep %d-%d \"<your line>\"\n"
|
||||||
"%d left after this." % (ENTRY_CHARS, body, lo, hi, left))
|
"%d left after this." % (ENTRY_CHARS, body, lo, hi, left))
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -338,11 +338,11 @@ def cmd_wake(d, args):
|
||||||
print("memory, part %d of %d, oldest first" % (k, len(parts)))
|
print("memory, part %d of %d, oldest first" % (k, len(parts)))
|
||||||
print("\n".join(parts[k - 1]))
|
print("\n".join(parts[k - 1]))
|
||||||
if k < len(parts):
|
if k < len(parts):
|
||||||
print("next: memo wake %d %d" % (k + 1, T))
|
print("Run: memo wake %d %d" % (k + 1, T))
|
||||||
else:
|
else:
|
||||||
# always, even for a one-part memory: the contract an agent is given
|
# always, even for a one-part memory: the contract an agent is given
|
||||||
# is "run parts until one says awake", so it must always arrive
|
# is "run parts until one says awake", so it must always arrive
|
||||||
print("awake.")
|
print("You are awake.")
|
||||||
|
|
||||||
|
|
||||||
def cmd_note(d, args):
|
def cmd_note(d, args):
|
||||||
|
|
|
||||||
36
test.py
36
test.py
|
|
@ -8,6 +8,7 @@ import contextlib
|
||||||
import datetime
|
import datetime
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -109,6 +110,18 @@ def run(*args, store=None):
|
||||||
return Result(code, out.getvalue(), err.getvalue())
|
return Result(code, out.getvalue(), err.getvalue())
|
||||||
|
|
||||||
|
|
||||||
|
def nap_id(out):
|
||||||
|
"""The block id from the command a nap prompt offers."""
|
||||||
|
m = re.search(r"memo sleep (\d+)-(\d+)", out)
|
||||||
|
return "%s-%s" % m.groups() if m else None
|
||||||
|
|
||||||
|
|
||||||
|
def offered(out):
|
||||||
|
"""The line offering a command. Every command handed to an agent must be
|
||||||
|
an order, not a label: `Run: memo ...`, never `next: memo ...`."""
|
||||||
|
return [l for l in out.splitlines() if "memo sleep " in l or "memo wake " in l]
|
||||||
|
|
||||||
|
|
||||||
# the real entry point still has to work: shebang, argv parsing, exit code
|
# the real entry point still has to work: shebang, argv parsing, exit code
|
||||||
smoke = subprocess.run(memo + ["wake"], env=dict(os.environ, MEMORY_DIR=d),
|
smoke = subprocess.run(memo + ["wake"], env=dict(os.environ, MEMORY_DIR=d),
|
||||||
capture_output=True, text=True)
|
capture_output=True, text=True)
|
||||||
|
|
@ -140,11 +153,13 @@ check(r.returncode == 1 and "Cannot wake" in r.stdout,
|
||||||
naps = 0
|
naps = 0
|
||||||
r = run("sleep")
|
r = run("sleep")
|
||||||
while "You are awake" not in r.stdout:
|
while "You are awake" not in r.stdout:
|
||||||
line = [l for l in r.stdout.splitlines() if l.strip().startswith("memo sleep ")]
|
line = offered(r.stdout)
|
||||||
check(bool(line), "no command offered:\n" + r.stdout + r.stderr)
|
check(bool(line), "no command offered:\n" + r.stdout + r.stderr)
|
||||||
if not line:
|
if not line:
|
||||||
break
|
break
|
||||||
bid = line[0].split()[2]
|
check(line[0].startswith("Run: "), "a command was offered as a label, not "
|
||||||
|
"an order: %r" % line[0])
|
||||||
|
bid = nap_id(r.stdout)
|
||||||
body = [l.strip() for l in r.stdout.splitlines()
|
body = [l.strip() for l in r.stdout.splitlines()
|
||||||
if l.startswith(" #") or (l.startswith(" ") and l.strip()
|
if l.startswith(" #") or (l.startswith(" ") and l.strip()
|
||||||
and not l.strip().startswith("memo"))]
|
and not l.strip().startswith("memo"))]
|
||||||
|
|
@ -174,8 +189,10 @@ lines = [l for p in parts for l in p]
|
||||||
check(len(lines) == WAKE_LINES, "woke with %d lines, want %d" % (len(lines), WAKE_LINES))
|
check(len(lines) == WAKE_LINES, "woke with %d lines, want %d" % (len(lines), WAKE_LINES))
|
||||||
check(lines[-1].startswith("#%d " % (N - 1)), "newest memory not last / not raw")
|
check(lines[-1].startswith("#%d " % (N - 1)), "newest memory not last / not raw")
|
||||||
check(lines[0].startswith("#0-"), "oldest line should be a summary block")
|
check(lines[0].startswith("#0-"), "oldest line should be a summary block")
|
||||||
check("memo wake 2" in run("wake").stdout, "part 1 must name the next command")
|
check("Run: memo wake 2" in run("wake").stdout,
|
||||||
check("awake." in run("wake", str(len(parts))).stdout, "last part must say it is last")
|
"part 1 must ORDER the next command, not label it")
|
||||||
|
check("You are awake." in run("wake", str(len(parts))).stdout,
|
||||||
|
"last part must say it is last")
|
||||||
check(run("wake", str(len(parts) + 1)).returncode == 1, "a nonexistent part should fail")
|
check(run("wake", str(len(parts) + 1)).returncode == 1, "a nonexistent part should fail")
|
||||||
|
|
||||||
# append-only: nothing was ever rewritten
|
# append-only: nothing was ever rewritten
|
||||||
|
|
@ -210,7 +227,7 @@ while True:
|
||||||
r = run("sleep")
|
r = run("sleep")
|
||||||
if "You are awake" in r.stdout:
|
if "You are awake" in r.stdout:
|
||||||
break
|
break
|
||||||
bid = [l for l in r.stdout.splitlines() if l.strip().startswith("memo sleep ")][0].split()[2]
|
bid = nap_id(r.stdout)
|
||||||
check(run("sleep", bid, "rebuilt after forget").returncode == 0, "rebuild rejected")
|
check(run("sleep", bid, "rebuilt after forget").returncode == 0, "rebuild rejected")
|
||||||
n += 1
|
n += 1
|
||||||
check(n > 0, "forget created no work")
|
check(n > 0, "forget created no work")
|
||||||
|
|
@ -235,7 +252,7 @@ while True:
|
||||||
r = run("sleep")
|
r = run("sleep")
|
||||||
if "You are awake" in r.stdout:
|
if "You are awake" in r.stdout:
|
||||||
break
|
break
|
||||||
bid = [l for l in r.stdout.splitlines() if l.strip().startswith("memo sleep ")][0].split()[2]
|
bid = nap_id(r.stdout)
|
||||||
run("sleep", bid, "settled")
|
run("sleep", bid, "settled")
|
||||||
check(run("wake").returncode == 0, "wake refuses at the very end")
|
check(run("wake").returncode == 0, "wake refuses at the very end")
|
||||||
|
|
||||||
|
|
@ -290,12 +307,11 @@ while True:
|
||||||
r = run("sleep", store=d2)
|
r = run("sleep", store=d2)
|
||||||
if "You are awake" in r.stdout:
|
if "You are awake" in r.stdout:
|
||||||
break
|
break
|
||||||
bid = [l for l in r.stdout.splitlines()
|
bid = nap_id(r.stdout)
|
||||||
if l.strip().startswith("memo sleep ")][0].split()[2]
|
|
||||||
run("sleep", bid, "settled", store=d2)
|
run("sleep", bid, "settled", store=d2)
|
||||||
r = run("wake", store=d2)
|
r = run("wake", store=d2)
|
||||||
check(r.stdout.rstrip().endswith("awake."),
|
check(r.stdout.rstrip().endswith("You are awake."),
|
||||||
"a one-part wake never says `awake.`:\n" + r.stdout)
|
"a one-part wake never says `You are awake.`:\n" + r.stdout)
|
||||||
|
|
||||||
shutil.rmtree(d2)
|
shutil.rmtree(d2)
|
||||||
shutil.rmtree(d)
|
shutil.rmtree(d)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue