Harness spec 3.0.0-draft: the file system as a contract
filesystem.md: paths, the node kinds dir/file/mount, the access levels none/ro/stage/commit with grants and floors, the exact error texts, and the rule that a granted path under one that is not is reached only by its full path. Listings, search, indexing by tokens (480 a piece, 64 repeated), instruction files stacked from the boundary to the start directory, skills, and memory kept by the server for both sides. Conformance areas fs_access, instructions and chunk_tokens, answered from a reference model of the rules. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
5 files changed
+1290
-1
No files matched your search
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"about": "Text → the pieces a knowledge document is cut into for search: about `size` characters (raised to 200 when smaller), cut just after a paragraph break, else a line break, else a sentence's \". \", found in the window's last third, with `overlap` characters (at most half the size) repeated; CRLF read as LF; pieces under 40 characters dropped.",
|
||||
"about": "Text → the pieces a knowledge document is cut into for search: about `size` characters (raised to 200 when smaller), cut just after a paragraph break, else a line break, else a sentence's \". \", found in the window's last third, with `overlap` characters (at most half the size) repeated; CRLF read as LF; pieces under 40 characters dropped. Spec 3.0.0: indexing for search cuts by tokens instead (chunk_tokens.json, filesystem.md); this character splitter stays the rule wherever a piece is still measured in characters.",
|
||||
"cases": [
|
||||
{
|
||||
"size": 200,
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
{
|
||||
"about": "Text → the pieces a file is cut into for search, measured in tokens (filesystem.md, Indexing, by tokens): at most `size` tokens each (raised to 16 when smaller), the next one beginning at the start of the token `overlap` tokens (at most half the size) before the cut; the cut just after a paragraph break, else a line break, else a sentence's \". \", looked for in the window's last third (by characters), else at the end of the window's last token; CRLF read as LF, the text trimmed, every piece trimmed; pieces under 40 characters dropped; a text of at most `size` tokens is one piece. `tokenizer: words` is the stand-in for an embedder's: a token is a run of non-whitespace characters. LLeMbas: services/library/chunks.py (to be written); CLI: library/chunks.ts (to be written).",
|
||||
"cases": [
|
||||
{
|
||||
"tokenizer": "words",
|
||||
"size": 480,
|
||||
"overlap": 64,
|
||||
"text": "One short paragraph that fits in a single piece.",
|
||||
"expect": [
|
||||
"One short paragraph that fits in a single piece."
|
||||
]
|
||||
},
|
||||
{
|
||||
"tokenizer": "words",
|
||||
"size": 16,
|
||||
"overlap": 4,
|
||||
"text": "The first paragraph is here, with nine words in it.\n\nThe second paragraph follows it and has ten words in total.\n\nA third one closes the text with a few more words.",
|
||||
"expect": [
|
||||
"The first paragraph is here, with nine words in it.\n\nThe second paragraph follows it and",
|
||||
"paragraph follows it and has ten words in total.\n\nA third one closes the text with"
|
||||
]
|
||||
},
|
||||
{
|
||||
"tokenizer": "words",
|
||||
"size": 20,
|
||||
"overlap": 5,
|
||||
"text": "Alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu nu xi omicron pi rho sigma tau upsilon phi chi psi omega. Alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu nu xi omicron pi rho sigma tau upsilon phi chi psi omega.",
|
||||
"expect": [
|
||||
"Alpha beta gamma delta epsilon zeta eta theta iota kappa lambda mu nu xi omicron pi rho sigma tau upsilon",
|
||||
"pi rho sigma tau upsilon phi chi psi omega. Alpha beta gamma delta epsilon zeta eta theta iota kappa lambda",
|
||||
"eta theta iota kappa lambda mu nu xi omicron pi rho sigma tau upsilon phi chi psi omega."
|
||||
]
|
||||
},
|
||||
{
|
||||
"tokenizer": "words",
|
||||
"size": 16,
|
||||
"overlap": 4,
|
||||
"text": "line one has four\nline two has four\nline three has five words\nline four has five words\nline five is the last one here\n",
|
||||
"expect": [
|
||||
"line one has four\nline two has four\nline three has five words",
|
||||
"three has five words\nline four has five words\nline five is the last one here"
|
||||
]
|
||||
},
|
||||
{
|
||||
"tokenizer": "words",
|
||||
"size": 16,
|
||||
"overlap": 40,
|
||||
"text": "w0 w1 w2 w3 w4 w5 w6 w7 w8 w9 w10 w11 w12 w13 w14 w15 w16 w17 w18 w19 w20 w21 w22 w23 w24 w25 w26 w27 w28 w29 w30 w31 w32 w33 w34 w35 w36 w37 w38 w39 w40 w41 w42 w43 w44 w45 w46 w47 w48 w49 w50 w51 w52 w53 w54 w55 w56 w57 w58 w59",
|
||||
"expect": [
|
||||
"w0 w1 w2 w3 w4 w5 w6 w7 w8 w9 w10 w11 w12 w13 w14 w15",
|
||||
"w8 w9 w10 w11 w12 w13 w14 w15 w16 w17 w18 w19 w20 w21 w22 w23",
|
||||
"w16 w17 w18 w19 w20 w21 w22 w23 w24 w25 w26 w27 w28 w29 w30 w31",
|
||||
"w24 w25 w26 w27 w28 w29 w30 w31 w32 w33 w34 w35 w36 w37 w38 w39",
|
||||
"w32 w33 w34 w35 w36 w37 w38 w39 w40 w41 w42 w43 w44 w45 w46 w47",
|
||||
"w40 w41 w42 w43 w44 w45 w46 w47 w48 w49 w50 w51 w52 w53 w54 w55",
|
||||
"w48 w49 w50 w51 w52 w53 w54 w55 w56 w57 w58 w59"
|
||||
]
|
||||
},
|
||||
{
|
||||
"tokenizer": "words",
|
||||
"size": 16,
|
||||
"overlap": 4,
|
||||
"text": "a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd ",
|
||||
"expect": [
|
||||
"a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d",
|
||||
"a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd a3f29c0e1b7d 9d8e7f6a5b4c 0011aabbccdd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"tokenizer": "words",
|
||||
"size": 16,
|
||||
"overlap": 4,
|
||||
"text": " \r\n ",
|
||||
"expect": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,876 @@
|
||||
{
|
||||
"about": "The file system as one session sees it (filesystem.md): `tree` (paths; a directory ends with `/`, parents are implied), `mounts` (directories that are forge repositories), `grants` (path → level none/ro/stage/commit, covering everything below; the most specific wins; none by default), `floor` (path → the most a session may have there; the most specific applies), `cwd` (the start directory, default `/`), and one `op` on `path`: `level` (the session's level there, and whether it is a passage: at none with something granted below), `list` (the entries the session sees: directories and mounts with `/`, a mount ` [mount]`, an entry at ro in a writable directory ` [read-only]`; directories first, then by name), `read`, `write` (a file), `mkdir`, `rm`, `commit`. Answers `{ok: true}`, `{entries}`, `{level, passage}` or `{error}` with the exact text, naming the resolved absolute path. A path the session cannot see is answered by what the model already knows: by its nearest ancestor that is visible (No such file or directory) or a passage (Access denied) — so a hidden entry and a missing one read the same; creating a name taken by an entry at none is denied. LLeMbas: services/files/view.py (to be written); CLI: not run until it has a view of its own (an agent's disk is one level for the whole working directory).",
|
||||
"cases": [
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "level",
|
||||
"path": "/Dir1",
|
||||
"expect": {
|
||||
"level": "none",
|
||||
"passage": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "level",
|
||||
"path": "/Dir2",
|
||||
"expect": {
|
||||
"level": "none",
|
||||
"passage": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "level",
|
||||
"path": "/Dir1/Dir3/a.md",
|
||||
"expect": {
|
||||
"level": "stage",
|
||||
"passage": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "list",
|
||||
"path": "/Dir1",
|
||||
"expect": {
|
||||
"error": "Access denied: /Dir1 is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "list",
|
||||
"path": "/",
|
||||
"expect": {
|
||||
"error": "Access denied: / is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "read",
|
||||
"path": "/Dir1/FILE1.txt",
|
||||
"expect": {
|
||||
"error": "Access denied: /Dir1/FILE1.txt is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "write",
|
||||
"path": "/Dir1/new.txt",
|
||||
"expect": {
|
||||
"error": "Access denied: /Dir1/new.txt is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "mkdir",
|
||||
"path": "/Dir1/x",
|
||||
"expect": {
|
||||
"error": "Access denied: /Dir1/x is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "read",
|
||||
"path": "/Dir2/b.md",
|
||||
"expect": {
|
||||
"error": "Access denied: /Dir2/b.md is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "read",
|
||||
"path": "/Dir2",
|
||||
"expect": {
|
||||
"error": "Access denied: /Dir2 is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "read",
|
||||
"path": "/Nope.md",
|
||||
"expect": {
|
||||
"error": "Access denied: /Nope.md is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "read",
|
||||
"path": "/Dir1/Dir3/missing.md",
|
||||
"expect": {
|
||||
"error": "No such file or directory: /Dir1/Dir3/missing.md"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "write",
|
||||
"path": "/Dir2/x.md",
|
||||
"expect": {
|
||||
"error": "Access denied: /Dir2/x.md is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "list",
|
||||
"path": "/Dir1/Dir3",
|
||||
"expect": {
|
||||
"entries": [
|
||||
"a.md"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "read",
|
||||
"path": "/AGENTS.md",
|
||||
"expect": {
|
||||
"ok": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "write",
|
||||
"path": "/AGENTS.md",
|
||||
"expect": {
|
||||
"error": "Read-only: /AGENTS.md can be read in this session but not changed."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "write",
|
||||
"path": "/Dir1/Dir3/new.md",
|
||||
"expect": {
|
||||
"ok": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "write",
|
||||
"path": "new.md",
|
||||
"cwd": "/Dir1/Dir3",
|
||||
"expect": {
|
||||
"ok": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "read",
|
||||
"path": "../FILE1.txt",
|
||||
"cwd": "/Dir1/Dir3",
|
||||
"expect": {
|
||||
"error": "Access denied: /Dir1/FILE1.txt is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/",
|
||||
"/Dir1/FILE1.txt",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/",
|
||||
"/Dir1/Dir3/a.md",
|
||||
"/Dir2/",
|
||||
"/Dir2/b.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"op": "list",
|
||||
"path": "/Dir1/Dir3/../../Dir1//Dir3/",
|
||||
"expect": {
|
||||
"entries": [
|
||||
"a.md"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "stage",
|
||||
"/Notes/Private": "none",
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "list",
|
||||
"path": "/",
|
||||
"expect": {
|
||||
"entries": [
|
||||
"Notes/",
|
||||
"Ref/ [read-only]"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "stage",
|
||||
"/Notes/Private": "none",
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "list",
|
||||
"path": "/Notes",
|
||||
"expect": {
|
||||
"entries": [
|
||||
"a.md"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "stage",
|
||||
"/Notes/Private": "none",
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "read",
|
||||
"path": "/Notes/Private/p.md",
|
||||
"expect": {
|
||||
"error": "No such file or directory: /Notes/Private/p.md"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "stage",
|
||||
"/Notes/Private": "none",
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "mkdir",
|
||||
"path": "/Notes/Private",
|
||||
"expect": {
|
||||
"error": "Access denied: /Notes/Private is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "stage",
|
||||
"/Notes/Private": "none",
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "write",
|
||||
"path": "/Notes/Private/x.md",
|
||||
"expect": {
|
||||
"error": "Access denied: /Notes/Private/x.md is not open to this session."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "stage",
|
||||
"/Notes/Private": "none",
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "rm",
|
||||
"path": "/Notes/Private",
|
||||
"expect": {
|
||||
"error": "No such file or directory: /Notes/Private"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "stage",
|
||||
"/Notes/Private": "none",
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "rm",
|
||||
"path": "/Notes/gone.md",
|
||||
"expect": {
|
||||
"error": "No such file or directory: /Notes/gone.md"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "stage",
|
||||
"/Notes/Private": "none",
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "write",
|
||||
"path": "/Ref/r.md",
|
||||
"expect": {
|
||||
"error": "Read-only: /Ref/r.md can be read in this session but not changed."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "stage",
|
||||
"/Notes/Private": "none",
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "write",
|
||||
"path": "/Ref/new.md",
|
||||
"expect": {
|
||||
"error": "Read-only: /Ref/new.md can be read in this session but not changed."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "stage",
|
||||
"/Notes/Private": "none",
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "rm",
|
||||
"path": "/Notes/a.md",
|
||||
"expect": {
|
||||
"ok": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "commit"
|
||||
},
|
||||
"floor": {
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "level",
|
||||
"path": "/Ref/r.md",
|
||||
"expect": {
|
||||
"level": "ro",
|
||||
"passage": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/Notes/",
|
||||
"/Notes/a.md",
|
||||
"/Notes/Private/",
|
||||
"/Notes/Private/p.md",
|
||||
"/Ref/",
|
||||
"/Ref/r.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "commit"
|
||||
},
|
||||
"floor": {
|
||||
"/Ref": "ro"
|
||||
},
|
||||
"op": "write",
|
||||
"path": "/Ref/r.md",
|
||||
"expect": {
|
||||
"error": "Read-only: /Ref/r.md can be read in this session but not changed."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/repo/",
|
||||
"/repo/README.md",
|
||||
"/repo/src/",
|
||||
"/repo/src/x.ts",
|
||||
"/home/",
|
||||
"/home/n.md"
|
||||
],
|
||||
"mounts": [
|
||||
"/repo"
|
||||
],
|
||||
"grants": {
|
||||
"/": "commit",
|
||||
"/repo": "stage"
|
||||
},
|
||||
"op": "list",
|
||||
"path": "/",
|
||||
"expect": {
|
||||
"entries": [
|
||||
"home/",
|
||||
"repo/ [mount]"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/repo/",
|
||||
"/repo/README.md",
|
||||
"/repo/src/",
|
||||
"/repo/src/x.ts",
|
||||
"/home/",
|
||||
"/home/n.md"
|
||||
],
|
||||
"mounts": [
|
||||
"/repo"
|
||||
],
|
||||
"grants": {
|
||||
"/": "commit",
|
||||
"/repo": "stage"
|
||||
},
|
||||
"op": "commit",
|
||||
"path": "/repo/src/x.ts",
|
||||
"expect": {
|
||||
"error": "Not committed: this session may change /repo/src/x.ts but not commit it; the change stays staged."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/repo/",
|
||||
"/repo/README.md",
|
||||
"/repo/src/",
|
||||
"/repo/src/x.ts",
|
||||
"/home/",
|
||||
"/home/n.md"
|
||||
],
|
||||
"mounts": [
|
||||
"/repo"
|
||||
],
|
||||
"grants": {
|
||||
"/": "commit"
|
||||
},
|
||||
"op": "commit",
|
||||
"path": "/home/n.md",
|
||||
"expect": {
|
||||
"error": "Nothing to commit: /home/n.md is not in a repository."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/repo/",
|
||||
"/repo/README.md",
|
||||
"/repo/src/",
|
||||
"/repo/src/x.ts",
|
||||
"/home/",
|
||||
"/home/n.md"
|
||||
],
|
||||
"mounts": [
|
||||
"/repo"
|
||||
],
|
||||
"grants": {
|
||||
"/repo": "commit"
|
||||
},
|
||||
"op": "commit",
|
||||
"path": "/repo/README.md",
|
||||
"expect": {
|
||||
"ok": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/repo/",
|
||||
"/repo/README.md",
|
||||
"/repo/src/",
|
||||
"/repo/src/x.ts",
|
||||
"/home/",
|
||||
"/home/n.md"
|
||||
],
|
||||
"mounts": [
|
||||
"/repo"
|
||||
],
|
||||
"grants": {
|
||||
"/repo": "ro"
|
||||
},
|
||||
"op": "commit",
|
||||
"path": "/repo/README.md",
|
||||
"expect": {
|
||||
"error": "Read-only: /repo/README.md can be read in this session but not changed."
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/repo/",
|
||||
"/repo/README.md",
|
||||
"/repo/src/",
|
||||
"/repo/src/x.ts",
|
||||
"/home/",
|
||||
"/home/n.md"
|
||||
],
|
||||
"mounts": [
|
||||
"/repo"
|
||||
],
|
||||
"grants": {
|
||||
"/": "commit"
|
||||
},
|
||||
"op": "write",
|
||||
"path": "/repo/src",
|
||||
"expect": {
|
||||
"error": "Is a directory: /repo/src"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/repo/",
|
||||
"/repo/README.md",
|
||||
"/repo/src/",
|
||||
"/repo/src/x.ts",
|
||||
"/home/",
|
||||
"/home/n.md"
|
||||
],
|
||||
"mounts": [
|
||||
"/repo"
|
||||
],
|
||||
"grants": {
|
||||
"/": "commit"
|
||||
},
|
||||
"op": "write",
|
||||
"path": "/home/n.md/x",
|
||||
"expect": {
|
||||
"error": "Not a directory: /home/n.md"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/repo/",
|
||||
"/repo/README.md",
|
||||
"/repo/src/",
|
||||
"/repo/src/x.ts",
|
||||
"/home/",
|
||||
"/home/n.md"
|
||||
],
|
||||
"mounts": [
|
||||
"/repo"
|
||||
],
|
||||
"grants": {
|
||||
"/": "commit"
|
||||
},
|
||||
"op": "mkdir",
|
||||
"path": "/home/n.md",
|
||||
"expect": {
|
||||
"error": "Already exists: /home/n.md"
|
||||
}
|
||||
},
|
||||
{
|
||||
"tree": [
|
||||
"/repo/",
|
||||
"/repo/README.md",
|
||||
"/repo/src/",
|
||||
"/repo/src/x.ts",
|
||||
"/home/",
|
||||
"/home/n.md"
|
||||
],
|
||||
"mounts": [
|
||||
"/repo"
|
||||
],
|
||||
"grants": {
|
||||
"/": "commit"
|
||||
},
|
||||
"op": "mkdir",
|
||||
"path": "/home",
|
||||
"expect": {
|
||||
"ok": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
{
|
||||
"about": "The instruction files a session starts with (filesystem.md, Instruction files, stacked): `files` that exist, the `boundary` and the `start` directory (outside the boundary: read as the boundary), and `grants` as in fs_access (absent: everything readable). From the boundary down to the start directory, outermost first, each directory gives the first of AGENTS.md, CLAUDE.md that is a file the session can read — never both; a file at none (in a passage, or taken away) is not loaded and the walk goes on below it. The answer is the loaded paths, in order. The CLI's global AGENTS.md, before the chain, and its configured `instructions`, after it, are not part of these cases. LLeMbas: services/files/instructions.py (to be written); CLI: prompt/assemble.ts instructionFiles (today: the nearest file only — 3.0.0 changes it).",
|
||||
"cases": [
|
||||
{
|
||||
"files": [
|
||||
"/AGENTS.md",
|
||||
"/sec/AGENTS.md",
|
||||
"/sec/repo/CLAUDE.md",
|
||||
"/sec/repo/src/AGENTS.md"
|
||||
],
|
||||
"boundary": "/",
|
||||
"start": "/sec/repo",
|
||||
"expect": [
|
||||
"/AGENTS.md",
|
||||
"/sec/AGENTS.md",
|
||||
"/sec/repo/CLAUDE.md"
|
||||
]
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"/AGENTS.md",
|
||||
"/sec/AGENTS.md",
|
||||
"/sec/repo/CLAUDE.md",
|
||||
"/sec/repo/src/AGENTS.md"
|
||||
],
|
||||
"boundary": "/",
|
||||
"start": "/sec/repo/src",
|
||||
"expect": [
|
||||
"/AGENTS.md",
|
||||
"/sec/AGENTS.md",
|
||||
"/sec/repo/CLAUDE.md",
|
||||
"/sec/repo/src/AGENTS.md"
|
||||
]
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"/AGENTS.md",
|
||||
"/sec/AGENTS.md",
|
||||
"/sec/repo/CLAUDE.md",
|
||||
"/sec/repo/src/AGENTS.md"
|
||||
],
|
||||
"boundary": "/sec",
|
||||
"start": "/sec/repo",
|
||||
"expect": [
|
||||
"/sec/AGENTS.md",
|
||||
"/sec/repo/CLAUDE.md"
|
||||
]
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"/AGENTS.md",
|
||||
"/sec/AGENTS.md",
|
||||
"/sec/repo/CLAUDE.md",
|
||||
"/sec/repo/src/AGENTS.md"
|
||||
],
|
||||
"boundary": "/sec",
|
||||
"start": "/other",
|
||||
"expect": [
|
||||
"/sec/AGENTS.md"
|
||||
]
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"/x/AGENTS.md",
|
||||
"/x/CLAUDE.md"
|
||||
],
|
||||
"boundary": "/",
|
||||
"start": "/x",
|
||||
"expect": [
|
||||
"/x/AGENTS.md"
|
||||
]
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/AGENTS.md",
|
||||
"/Dir1/Dir3/AGENTS.md"
|
||||
],
|
||||
"grants": {
|
||||
"/AGENTS.md": "ro",
|
||||
"/Dir1/Dir3": "stage"
|
||||
},
|
||||
"boundary": "/",
|
||||
"start": "/Dir1/Dir3",
|
||||
"expect": [
|
||||
"/AGENTS.md",
|
||||
"/Dir1/Dir3/AGENTS.md"
|
||||
]
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"/x/AGENTS.md",
|
||||
"/x/CLAUDE.md"
|
||||
],
|
||||
"grants": {
|
||||
"/": "ro",
|
||||
"/x/AGENTS.md": "none"
|
||||
},
|
||||
"boundary": "/",
|
||||
"start": "/x",
|
||||
"expect": [
|
||||
"/x/CLAUDE.md"
|
||||
]
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"/AGENTS.md",
|
||||
"/a/AGENTS.md",
|
||||
"/a/b/AGENTS.md"
|
||||
],
|
||||
"grants": {
|
||||
"/a/b": "ro"
|
||||
},
|
||||
"boundary": "/",
|
||||
"start": "/a/b",
|
||||
"expect": [
|
||||
"/a/b/AGENTS.md"
|
||||
]
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"/README.md"
|
||||
],
|
||||
"boundary": "/",
|
||||
"start": "/",
|
||||
"expect": []
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in new issue
Block a user