Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ when.
| [desire-path](https://github.com/scbrown/desire-path) | turns agent mistakes into feature requests; works on its own without Quipu |
| [seeds](https://github.com/scbrown/seeds) | a work item tracker backed by the Quipu knowledge base |
| [shantytown](https://github.com/scbrown/shantytown) | runs crews of AI agents on work items, triggered by hand, on a schedule or by events; can share work and memory through Quipu |
| [rikuy](https://github.com/scbrown/rikuy) | live brief: status, graphs, watches and signed decisions over Quipu |
| [shuttle](https://github.com/scbrown/shuttle) | runs signed agent workflows and keeps their records in Quipu |

<!-- stack-table:end -->
Expand Down
5 changes: 3 additions & 2 deletions docs/stack-table.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Canonical stack table

This is the source for the marked stack overview in the eight tool READMEs.
This is the source for the marked stack overview in the nine tool READMEs.

<!-- ANCHOR: table -->
<!-- stack-table:start -->
Expand All @@ -20,11 +20,12 @@ when.
| [desire-path](https://github.com/scbrown/desire-path) | turns agent mistakes into feature requests; works on its own without Quipu |
| [seeds](https://github.com/scbrown/seeds) | a work item tracker backed by the Quipu knowledge base |
| [shantytown](https://github.com/scbrown/shantytown) | runs crews of AI agents on work items, triggered by hand, on a schedule or by events; can share work and memory through Quipu |
| [rikuy](https://github.com/scbrown/rikuy) | live brief: status, graphs, watches and signed decisions over Quipu |
| [shuttle](https://github.com/scbrown/shuttle) | runs signed agent workflows and keeps their records in Quipu |

<!-- stack-table:end -->
<!-- ANCHOR_END: table -->

Run `python3 scripts/check-stack-table.py` to check this repository, or add
`--remote` to compare all eight published READMEs. Update the marked blocks
`--remote` to compare all nine published READMEs. Update the marked blocks
together when changing this table.
6 changes: 3 additions & 3 deletions docs/stack/README-STANDARD.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,14 @@ each book, and diverging from it is a review finding.
## 3. The shared stack block (identical everywhere)

The canonical table is [docs/stack-table.md](../stack-table.md). Copy its complete
marked block verbatim into the eight stack READMEs: Caboodle, Quipu, Camayoc,
Bobbin, Yupana, Desire Path, Seeds and Shantytown. Keep the Shuttle row. Do not add a
marked block verbatim into the nine stack READMEs: Caboodle, Quipu, Camayoc,
Bobbin, Yupana, Desire Path, Seeds, Shantytown and Rikuy. Keep the Shuttle row. Do not add a
repository-specific self marker; every copy must remain byte-identical.

The [README template](README-TEMPLATE.md) carries the same marked block. Run
`python3 scripts/check-stack-table.py README.md docs/stack/README-TEMPLATE.md`
from the repository root to verify both local copies, and add `--remote` to
check the eight published READMEs. Update the canonical source and copies
check the nine published READMEs. Update the canonical source and copies
together when changing outcome-first row wording.

## 4. Rules every README is held to
Expand Down
1 change: 1 addition & 0 deletions docs/stack/README-TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ when.
| [desire-path](https://github.com/scbrown/desire-path) | turns agent mistakes into feature requests; works on its own without Quipu |
| [seeds](https://github.com/scbrown/seeds) | a work item tracker backed by the Quipu knowledge base |
| [shantytown](https://github.com/scbrown/shantytown) | runs crews of AI agents on work items, triggered by hand, on a schedule or by events; can share work and memory through Quipu |
| [rikuy](https://github.com/scbrown/rikuy) | live brief: status, graphs, watches and signed decisions over Quipu |
| [shuttle](https://github.com/scbrown/shuttle) | runs signed agent workflows and keeps their records in Quipu |

<!-- stack-table:end -->
Expand Down
4 changes: 2 additions & 2 deletions scripts/check-stack-table.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from urllib.request import Request, urlopen

ROOT = Path(__file__).resolve().parents[1]
REPOS = ("quipu", "bobbin", "camayoc", "yupana", "desire-path", "seeds", "caboodle", "shantytown")
REPOS = ("quipu", "bobbin", "camayoc", "yupana", "desire-path", "seeds", "caboodle", "shantytown", "rikuy")
START = b"<!-- stack-table:start -->"
END = b"<!-- stack-table:end -->"
MAX_BYTES = 256 * 1024
Expand Down Expand Up @@ -56,7 +56,7 @@ def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("readmes", nargs="*", type=Path, help="local README copies")
parser.add_argument("--canonical", type=Path, default=ROOT / "docs/stack-table.md")
parser.add_argument("--remote", action="store_true", help="also audit all eight public main branches")
parser.add_argument("--remote", action="store_true", help="also audit all nine public main branches")
args = parser.parse_args()
try:
canonical = marked_table(args.canonical.read_bytes(), str(args.canonical))
Expand Down
9 changes: 5 additions & 4 deletions scripts/test-stack-table.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,22 +66,23 @@ def test_remote_error_is_not_a_clean_zero(self):
redirect_stdout(io.StringIO()), redirect_stderr(io.StringIO()):
self.assertEqual(CHECK.main(), 1)

def test_shantytown_is_audited_and_its_missing_block_fails(self):
def test_new_rikuy_and_shantytown_missing_blocks_fail(self):
canonical = CANONICAL.read_bytes()
for missing, expected in ((False, 0), (True, 1)):
for missing, expected in ((None, 0), ("shantytown", 1), ("rikuy", 1)):
seen = []

def read(repo):
seen.append(repo)
return b"A README without a stack block.\n" if missing and repo == "shantytown" else canonical
return b"A README without a stack block.\n" if repo == missing else canonical

with self.subTest(missing=missing), \
patch.object(CHECK, "remote_readme", side_effect=read), \
patch.object(sys, "argv", [str(SCRIPT), "--remote"]), \
redirect_stdout(io.StringIO()), redirect_stderr(io.StringIO()):
self.assertEqual(CHECK.main(), expected)
self.assertEqual(seen.count("shantytown"), 1)
self.assertEqual(len(seen), 8)
self.assertEqual(seen.count("rikuy"), 1)
self.assertEqual(len(seen), 9)

def test_remote_response_has_a_size_limit(self):
response = MagicMock()
Expand Down
Loading