test(convert): manifest v2 — one line per agent, platform-neutral hashes, advisory drift on PRs (#844)

See the PR for the why/what/proof. Contributors no longer touch scripts/convert-outputs.sha256; drift is advisory on pull requests and strict on main.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Michael Sitarzewski
2026-09-08 18:59:03 -05:00
committed by GitHub
co-authored by Claude Fable 5.1
parent 647c8baa42
commit 449e0c71b1
4 changed files with 433 additions and 55 deletions
+3 -1
View File
@@ -26,7 +26,9 @@ jobs:
run: bash scripts/test-convert-frontmatter.sh run: bash scripts/test-convert-frontmatter.sh
- name: Validate converted outputs (round-trip, strict parse, counts, drift) - name: Validate converted outputs (round-trip, strict parse, counts, drift)
run: bash scripts/test-convert-outputs.sh # Drift is advisory on pull requests (agent PRs always move their own manifest line;
# maintainers regenerate at landing) and enforced on pushes to main.
run: bash scripts/test-convert-outputs.sh ${{ github.event_name == 'pull_request' && '--drift=advisory' || '' }}
- name: Validate agent selection (install.sh --agent / --agents-file) - name: Validate agent selection (install.sh --agent / --agents-file)
run: bash scripts/test-agent-selection.sh run: bash scripts/test-agent-selection.sh
+7 -4
View File
@@ -251,9 +251,12 @@ Want agency-agents to install into a new tool (a CLI, editor, or agent runtime)?
file parses with a real YAML/TOML parser, every tool emits exactly one output file parses with a real YAML/TOML parser, every tool emits exactly one output
per agent, and every source file parses the way the desktop app reads it. per agent, and every source file parses the way the desktop app reads it.
When you've changed a converter on purpose it will report **manifest drift** When you've changed a converter on purpose it will report **manifest drift**
— that's expected. Look over what changed, run it again with `--update`, and on that tool's line — that's expected. Look over what changed, run it again
commit the refreshed `scripts/convert-outputs.sha256` so reviewers can see with `--update`, and commit the refreshed `scripts/convert-outputs.sha256` so
the blast radius at a glance. CI runs it on every PR. reviewers can see the blast radius at a glance. The manifest holds one line
per agent and one per tool, and its hashes are the same on every platform
(forward-slash paths, LF line endings), so a Windows checkout produces the
same file. CI runs it on every PR.
If your PR commits the converted output (the generated `integrations/<tool>/*` files), CI and review will ask you to remove it and add the `.gitignore` rule instead. If your PR commits the converted output (the generated `integrations/<tool>/*` files), CI and review will ask you to remove it and add the `.gitignore` rule instead.
@@ -310,7 +313,7 @@ We love ambitious ideas — a [Discussion](https://github.com/msitarzewski/agenc
4. **Define Metrics**: Include specific, measurable success criteria 4. **Define Metrics**: Include specific, measurable success criteria
5. **Proofread**: Check for typos, formatting issues, clarity 5. **Proofread**: Check for typos, formatting issues, clarity
6. **Check it's original**: Run `./scripts/check-agent-originality.sh path/to/your-agent.md`. It compares your agent against the whole roster and flags near-duplicates (a swapped country/platform name won't fool it). A new agent should be genuinely new — if you're localizing for a market, make the platforms, tactics, and examples actually different, not a find-replace. 6. **Check it's original**: Run `./scripts/check-agent-originality.sh path/to/your-agent.md`. It compares your agent against the whole roster and flags near-duplicates (a swapped country/platform name won't fool it). A new agent should be genuinely new — if you're localizing for a market, make the platforms, tactics, and examples actually different, not a find-replace.
7. **Check it comes through every tool intact**: Run `./scripts/test-convert-outputs.sh`. It regenerates every tool's output and confirms your agent survives each converter — description round-tripped, files parsing, nothing dropped — and that its frontmatter parses the way the desktop app reads it. Adding or editing an agent changes the generated product, so it will report **manifest drift**; that's expected, not a failure on your part. Look over the change, run it again with `--update`, and commit the refreshed `scripts/convert-outputs.sha256` alongside your agent. CI runs the same check. 7. **Check it comes through every tool intact**: Run `./scripts/test-convert-outputs.sh`. It regenerates every tool's output and confirms your agent survives each converter — description round-tripped, files parsing, nothing dropped — and that its frontmatter parses the way the desktop app reads it. Adding or editing an agent changes the generated product, so it will report **manifest drift** naming your agent — that's expected, and it is **advisory** on pull requests: CI prints it but does not fail on it. You don't need to touch `scripts/convert-outputs.sha256` at all; the maintainers regenerate it when your PR lands. (If you do run `--update`, that's fine too — the manifest has one line per agent, so it won't conflict with anyone else's PR, and the hashes are identical on Windows, macOS and Linux.)
A word on why these checks exist. People are building genuinely remarkable things on top of these agents, and thousands rely on them every day across a dozen different tools. That's wonderful — and it means a small slip in one converter, or a stray quote in one file, quietly reaches all of them at once. Running the suite locally is how we keep that smooth for everyone downstream. It takes about a minute, and it means your work arrives exactly as you wrote it, in every tool, for everyone. Thank you for taking the extra step — it's a real kindness to people you'll never meet. A word on why these checks exist. People are building genuinely remarkable things on top of these agents, and thousands rely on them every day across a dozen different tools. That's wonderful — and it means a small slip in one converter, or a stray quote in one file, quietly reaches all of them at once. Running the suite locally is how we keep that smooth for everyone downstream. It takes about a minute, and it means your work arrives exactly as you wrote it, in every tool, for everyone. Thank you for taking the extra step — it's a real kindness to people you'll never meet.
+292 -17
View File
@@ -1,17 +1,292 @@
antigravity 3a6a9f27c2478c05093f8cecef99793870250cfc1774e4d8642d8d92001d4b0e # convert-outputs manifest v2 — one line per agent (its output across every tool), one per tool
gemini-cli 389eaa64b91beef18e999471f227036aefcbf3ac8d87858cabcae39a594c5951 # (non-agent files), one per contract. Platform-neutral hashes. Regenerate: scripts/test-convert-outputs.sh --update
opencode 99af3bd8f155ea2ce9c5f9bfbf53ff1a083be1863cc998d2a40e63cd6314fff9 agent 3d-scene-developer fc016961eae1b7938a92f176a4f06a3b41aa383836c52cff93e2432adde1359f
cursor 169d7c6e752490cfe8ad9a40a0e13a19f5bb641862d580bad9b23596a7d731f2 agent accessibility-auditor 531e4d3f763385b8fec7cda81438b37a787013b14eaef4104fb250a560dbb40c
aider 9438f15e56aec67943b56deb21f459f4f4adeb457b96316309175c6ca6fcff30 agent account-strategist 80b709f079672a78f96d972f61c1f7058c12f87bb323fd9e1702e38a3b1e528d
windsurf e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 agent accounts-payable-agent e61a79cd9e94dc01efe6585d270a2b2452da14d8e74bc4174736ee7a982f66dc
openclaw 3019e15be427bc9d38e22765dab57951fe7d91d352c1b04b61e045f8b360dd22 agent ad-creative-strategist 20317f3a86123e8dfb4d9449e3e5ee66a3cfa6207a6e8810b3fd515a6528c50c
qwen 6602754c05df8a700dde9864afc3bf5275fa5c1b52a2c52771c63f0d5c4bf358 agent aeo-foundations-architect 609c0d0734afa4b13b6d3e36352b266a0c3fc60aafa9acb7f7d1f459e831cb99
zcode 994ce45c33d46d2c694d201792fc1cd9dffcb1bcfe285ab46767d7d29f0831c6 agent agentic-identity-trust-architect f085fe2b9bd5ace943b9db7b2356119158211155d015716c381594fa8658259a
kimi 0be25760acdcf1638c2605d05ffb80fe05f751b6b76e5b3ba67af82885118606 agent agentic-search-optimizer b723e63deeb61f1716944e776b1a3606f83caabcd1feb7661fb9ba6d67973476
codex d666dfb2d78328d0cfccb6ebcdb3d35103e2280cca113cf0248a78bb66039150 agent agents-orchestrator 6e233f2aa73a22732da3fa31a9e4af48d99c7d985b48d6d0ac5d3ad79c594042
osaurus 8c7b843ed0cfb8279ed75306c1744e14e49a1e6815a4ce7bb055d047b87a5cc6 agent aging-parent-care-companion 19da4e473b70eeb669f937c15c5b50c49759565cc15e99b316e1c1ab9ddd2de0
hermes 4b3909263d777345a6aad5af6d61dd75251bd7e29b867a4440f280f656224bb8 agent ai-citation-strategist ef6a556ac3a6335bec190fb991b5394b403e2cceff62dbc583c92f4276aafb6b
vibe 8c79416463420d73bfa7ec79f51df95568bb7bd73626e1107137f8fa5900c9ea agent ai-data-remediation-engineer b047eddc466be07592dafe1ba30702adfcc9f8e703ea85397bf2d5b6eff7bfd4
divisions.json a85d4ceeabe671051559e7703dfca074bf7a259ba26b61fb5e14ed36d54ae051 agent ai-engineer 9a62bf0be72e0fd50f31b32aa327cbb3146c0167194789da2076f9267306aa5e
tools.json 2b9635406d8980dfde28849f965f2a22de384b4906128ec345ef6fc6246f127d agent ai-generated-code-security-auditor 9e7291fd8fc34032a572ff3ea780554d9ca8f53202eb4257dcf0156629e24251
strategy/runbooks.json 2d0372782460694bddcbdb5ec04ff28ae6284a2c751888f8010e16033024ac49 agent analytics-reporter c16be262b25a55adb1725a60d19f56a88c27d7cdb3a2320a3d61e16d3a26003e
agent anthropologist 717ed5a489ce189c1a145f5c428d43024b210831581431ed9b60cad52d772dda
agent api-platform-engineer a3235000ae28c7791ffacc87c06c68b732002503f5f324db3c8eceb6759eccd4
agent api-tester a3e72294e3a7a743dcbd2ed3dcf8d98b8b2f17d1205938d6c0bbe79238003578
agent app-store-optimizer dc40749e4893f4105cbfd131e5c7220e5f0d2515a4d126a6826a5cd247aafa38
agent application-security-engineer 47e9ac7641d8863a8ec2069b583ff6dda2da6983d12312ea94630c7910dd985b
agent automation-governance-architect bf5d9822bd3b930ad14de49e9c9232a7149ff9b180dc9c233f18500f72caddc0
agent autonomous-optimization-architect d02f1ff302b3111540bbba97dc70cde2127b2d4d668bdcea44bbc7416083e593
agent backend-architect c7e285813ab044ebeff4007bbfa781a929fab947a891aaf81aaddc986bdb6c89
agent baidu-seo-specialist 8aedc05ce42f82af9674d1c65b258e591a67738aff81e4bbaa12b2a444a766c6
agent behavioral-nudge-engine 7d39f4e066c6ff54cb5796c1664f549367694a80048f79452de86c3b443882dc
agent bilibili-content-strategist 965b5bae8c0521f696bc48c733c46683a280ac8f13cacfe9eecec2d9df7a70c9
agent bim-gis-specialist bf6f29856e43ecf1fcc7a8dae5a32d20dec2cd1f6abe7a591391e32d2634ffd4
agent blender-add-on-engineer e5ecd8bfb7e26cfc80af6ee87b374002738d84c11f18a0a3c7e3a358cb4b2704
agent blockchain-security-auditor 274ecbce59d30e14b3bed8467aa95d6b4b8e048ebec62db9a5741497820cc754
agent book-co-author 90258d7c0a671bda082309f6db6866ae8e8c3d91e4d6595756ea4ca6d3f838f8
agent bookkeeper-controller 6ca9d331d3679a2891cea5ce5614cbad48492b29fe5055a172264f70dc159cda
agent brand-guardian 57e1bc6418f5e7baa54398930f218501a6398ef1bc9eaf2513baca6f534f8607
agent business-strategist f493985599df0171ed24c9f8de888d0c323ce6aaa3f444a2b8461ad1ac153d76
agent carousel-growth-engine c7ca846ed4f0049b733a771d774b10d0ece6dcbfdb026894a25213b1632f7366
agent cartography-designer 058fb8e306bb54ce2eca3a991b4d833281911bc3028ad895e7f05ff6e8c8ec2f
agent change-management-consultant 596be6b1e4478356860261b0d3e546edfa532bdb76446125e5414cbff19f5426
agent chief-financial-officer 19224dd8a6582d74752a23156e3d810a56a10ae857ad009660136d5f464a6f11
agent chief-of-staff 3c0bcf52e87123277d3900f477053db94e42f15f3c75bd374c51786347eeadaf
agent china-e-commerce-operator 8b3ea173e2174ddac3ba0fe7dc18d8c0474bd37bdf29bcde09de5944e7b841e4
agent china-market-localization-strategist a583d08e874b2702f93bfef8498cac10d1452aca9d3c9fe49cb61192d6d5a0fb
agent civil-engineer c0516e459263f598a9924bfec0d588a477d8c70077214d33daadcc20cd99349f
agent clinical-evidence-agent 718b61dd3392b242e4f19832ab8f5bd63aec7f0cfe45e18d190fae96994517ab
agent cloud-security-architect bcb4a2946891364563aefaa5576a2833aaf1910b7efa17731832b91b28afda07
agent cms-developer 8e3e31fdc7cb34781f579251df294b012b6b119780f4b2c1cbf36c2fcdc0464c
agent code-reviewer 71c91ed253267724c89a43a914fae4992bb58e4776e5d39b7bbe713d12201e24
agent codebase-archaeologist db6736949c483d325937695b335536ecaad070d237c8d67cc15eb6c841dceb79
agent codebase-onboarding-engineer cd4191dd5168943e0b21e3cf5e3a76392522b69049b9b16db9798473510dd5d9
agent compliance-auditor 4140a1b8a8bd884eb6495e89aa3a39f5925be0ac4fecb4f875ce098dd3920ffa
agent content-creator 3dc60ea8974928c0e7ad1b8e34a3c47bc4b5f915782bf42f23549b90625fb013
agent corporate-training-designer 56a6a17e7ee1f4bdd5a8ffc7ee9960ed9bdf7adc2f168a27d1d84ee1962abf40
agent cross-border-e-commerce-specialist 14bc774aaf394d22a1dce6b0af2cc1d8f7c2286772b6b8142d7b1748f1f5553d
agent cultural-intelligence-strategist ef1c00e1e345458af3bc8d5d424ecc5a38d92be10408077e34e54541ab4aabac
agent customer-service 320c755c01a2303d972dfc992ec40de32c512bbdef6f2bf9dec0486175acf822
agent customer-success-manager 07b149c584473401131b0125dc5bdae52d022e4d46ff8aab9522c2fa411262ff
agent data-consolidation-agent 1796465a8cf3405465cf34cad956b21826d320bee2995416ce2fa46db83b4cde
agent data-engineer bc6facf3b53c99838eb5963fbdc1d195c33798c407e89bb34b1687e191d6c0fa
agent data-privacy-officer 82051c33e913115713937423bf3f4d03f336d6b7f351154fda4914c973f57582
agent data-visualization-engineer d1171dacd5b7fa637649d86999a62dcbcc9f4afa919dad61b73b41b4e17fb33b
agent database-optimizer 53903de26fdd39e29ffc9a7178e844570e24694cf939b88aecda3363d9548a4d
agent database-reliability-engineer 4d8e8743be3e3709d6a81a8d43953baf89700b6c7fc613574f020d000bdcb240
agent deal-strategist dc5dd95636e495063cf00b1dde4c9e56b66437f8d7a3dc1af7b27ed7d209caf0
agent desktop-app-engineer 9dc4fd3409742c0360f77aea913033c0cc347c3b50eb9cc1b08ebd687f63ca83
agent developer-advocate 3701de694d76c50325703229025ef16088e38e8e35fef183dddc6336860fc6c9
agent developer-tooling-engineer 26ee7881fc754b3b7fd7da3ebec6b0f0974641940616ea0f0b41de6141fc0e20
agent devops-automator 70cee9eafe1156d8df705ea34f83b6aa4e430c68308bd12e9e362ad30f16439f
agent discovery-coach a1799b1b278699cf65eea3ea5adf50e50ec23371ca24d88c4d078280e0b83623
agent document-generator 78b7ec972d86a794ca211eca23a62b1a9d3fa1e2b5e97d6874dc33e51efc11e2
agent douyin-strategist 668b8ac71d540d8fa8361f518e102d369ca1d0cf43de942685bdb6bdd1e9575f
agent drone-reality-mapping-specialist 68c46c2109a52296c0a8b57eef893c994b89efd68a4507064d44efdb6bc09280
agent drupal-performance-engineer d78cde305b4d7faddd3b9278e838009cc3a20093ae2c238c981fde98cba8b84f
agent drupal-shopping-cart-engineer 83dcae574ada590e8fbad98d7a880a8c1dca323ec2527896405b5319beaeb395
agent economy-designer 27c6b86ce42570142aa6943d3bbf1c7ebd3f41bc9e69d96880cb8ca2671c49ad
agent email-intelligence-engineer 1f99bc5105efeaa9b3d980119a6b3cd85035e322ea3e5b89bce1e8efc5998200
agent email-marketing-strategist 32a6552f4a4268d791410c3fa211471b6e6df64d7b157a9805d8d03d55ac11bd
agent embedded-firmware-engineer ac8a61a1174a7946124439bf4d276daec43235fa6013608a0f39c519fa19c7d7
agent esg-sustainability-officer 9121ecfdc8613296722ba4352676ac23d9da2160fc9200057367f2a7554dd183
agent evidence-collector cd32049d0a17510a985b3d7c8045a63c7ebf68f62daa571a71bfee1e35cc0655
agent executive-summary-generator 31e700b0374f1a41f8e79ce684b6c1a3ca7f6c01b60094a9f6f9e6f11f8f1b93
agent experiment-tracker 55628aa104fed9d1242785b63fad65fc0c1ad39f7544298146e8464be8e41553
agent fedramp-rmf-compliance-engineer 7f58808ab494512410a91cb02e788287fa571a504a95363c8104df952ef89e55
agent feedback-synthesizer 3b93a4d1d92cff529d96f786772f684ef0b343c4b957a6134cbe0651a1282b89
agent feishu-integration-developer 988b66877a19383770e7d706a35024614b01067d29bb685f8d3ff080290ccae8
agent filament-optimization-specialist 75dbfc5667178716749958bd482727e0a85fbff4a3e370301afd77e7c968aa73
agent finance-tracker e28b6f10fe8fd927cb0a9d66c7ccd3cba542e05d852b42575963202f5e723827
agent financial-analyst 025a74dc2ce7aa96b4f2fbb9a11fcb45f7d03a1d58793313183cbe8e347a7b37
agent finops-engineer e4c27efea116c03044ff8b60d21b83d2bf55a0bcd34986afcc35d37a62d98241
agent fp-a-analyst cd5a69bd6a964860a219ef4c315b5c9ac3059dedb0669eabf3e1aa2e9a94291f
agent french-consulting-market-navigator f5080ff0e4f37f40bd91f5507b913202d67adc1b975036db4d1630696c80211d
agent frontend-developer c01bfbab36d7a15a6dbd9e625ce2f7ecb57a0d9ab96676c0c3d9e9f7870b2d85
agent game-audio-engineer 8cbce5bcb3b4aec97fe0a6d0fc427203b3852c450e5392f3ffcd6e9477342e70
agent game-designer 1985d3982faf5ec45addbc604758603a3f3d847541793ef2336d7e4ed5dbde05
agent gaussdb-expert-engineer 2c5cfec21dffd95203291515842b4452b16cafac3bae1312f16442551df73f59
agent geoai-ml-engineer a5d0ae519c2f29a1f6f17bd216eedc42ef146017ac7482f277b228f73a441556
agent geographer 9ec04973e392ea0f7883f64c5bd1b47dbf727c3fc08d0d8468cbb672914913b8
agent geoprocessing-specialist da58a2b87d7999271428bdd902e691da14c8f401fa5c7698d1c7ee5b25094e30
agent gis-analyst 6aad2e21fab62a0b5c8afa6e9a1d1f147ab40e1560532a833f8ff534c6ddd920
agent gis-qa-engineer 08d424435b10b3cd95be785ae281cedce374575599d2e07e53dca9429ba6c361
agent git-workflow-master cbea1fc502bcc242bed933183c3017334dd0d94235433d71432b2c2f23e6caaf
agent global-podcast-strategist 825862d052b361eb9fa9b9558c1bc46c230f9268235f97c889a8035a59518be7
agent godot-gameplay-scripter 7c5f43d180334f9df710fb3e25bb10d0bd798ad3b43c4c11f8c59cc4ea3562f2
agent godot-multiplayer-engineer 6968b96da873411b6ff30a5f71322482116dc02205ebe071942465ccf473e3a9
agent godot-shader-developer eed41026d50e5a5b099a67f9eb1fe9747f509345b4d44d528e3e2beb72902148
agent government-digital-presales-consultant 86a743df9a5d29305d85a578071ef47d7542489f57438ae7770daecbd2d7302d
agent grant-writer daab881f6faf732e8a4466d0d9029940a713bef2fa2181bb37cc0383f14ea5e5
agent growth-hacker 372be3d5dc1ebf19f0fabd5129d6dfe1465d7f67196fcf4b5845578ede398eb2
agent healthcare-customer-service 465f3e47402898625ea7bc25e24e2522a0784f09690aab1fca7f4bd154a84170
agent healthcare-innovation-strategist ffc64e2bd47cba3c32cd756a0c993260e155a25d1f2e528d67c233306fca5a36
agent healthcare-marketing-compliance-specialist bfd672a80d250d2e0785ed339742a5a537357e5dd4e5d42c30b4612e8402e766
agent historian d0c6ab0da820c2ecd44e2cd55a49811afb5b676065060837b78644ca551c910a
agent hospitality-guest-services 8250743b1b7b8f7b9dbd733bf1a7199601681f4f5e9e89e48431c6e4df522d43
agent hr-onboarding 74768b5133b57873419525819600daae93f6550f45d8de161c18dfde5a4a1461
agent identity-access-engineer cd21e9fdae6133e93ad53b011e0fbbc5f8266b2e29c7a4dba53f30de80c5077a
agent identity-graph-operator 1fb3600479d4afa48d3cbc6e30358246bf0a320a59e4e9818b367d116c846ae6
agent image-prompt-engineer fb37bda0f7e509964029cabfa8e629edbb53e946043f686ec8bfe532439771fc
agent incident-responder 923cb920f4649b48e41f3074a2727b441a48c7b2978b4b9f27cde39d648b07ba
agent incident-response-commander b5fca7e26de3f7c3eee73b2b3db4051d6a2efe0843ac8a1a29d6aee6a1b14454
agent inclusive-visuals-specialist ddb31d99e461efa49301bb24685148295a77881622fe783c536c5270a84e9e7a
agent infrastructure-maintainer af51f8c47f62b87d22dc2356bc9904e7126e03420614f968566dfac113ea2c7a
agent instagram-curator 4b0d5e941c793cb354bbab3d2498b7e673e42f8486d9b8ccb019a20bdb0852f2
agent internationalization-engineer bb28049d78f2d8051fabe660df930c79cd0858ea6b17d40d4b5923513f265a49
agent investment-researcher 836dfa54cbcabf4c3505638407f389109d2cc69de221e5b75f888c6be45f8e41
agent iot-fleet-engineer 62d0a4c48e172a01c5346117e73d71ac2a79b63e9f19473d36a6b259b163c7c1
agent it-service-manager 5e43ce4b394c43cb5777703cc29885e7112ba0402aee3992fa19653fddf15d3a
agent jira-workflow-steward 200089fc664cec10417ac7a9c725a8eb18c51491f120a00025a344e9b378bc33
agent knowledge-graph-engineer b76b47bb06556cfd21c9652ec2b764a507cc9c1017c88fd5b5ea157c647695c2
agent korean-business-navigator 4ea8e05fbf783e4c609ede64303297d4c3517492dc9673d84c3870661ea20117
agent kuaishou-strategist 90d94b63ef6541ce0ae58cb013dea8723de70a7c974e0e1a54e86cc0ea91ab33
agent language-translator d6a0aeec68bd2023ed5334c276d01517076fdcb622f8db96ce79bbb7fcfa2450
agent legal-billing-time-tracking a044badba2f930fde5e0b7f26bd87683972e919e53bcacb94ba4f003478ed36f
agent legal-client-intake 4e9d749c57bd7ff6b0ebc0da37fc67427a3b330bb07d63ce703db6095ff02840
agent legal-compliance-checker c184f364072bc23af5e5999d5759960a651881bd736608f4b7247fd614f53a66
agent legal-document-review 9560cb37d843386d3dd2fda19a08f1a6482e03c67648582ee594691d643557d2
agent level-designer eeeb14584adc4a340852c002205581ba09d4cd964d7088eeebff13457ff54e3d
agent linkedin-content-creator 87c8678183702579d0a9dd41180235faa81eecb1900b11ad52399f6f1191b089
agent livestream-commerce-coach 61408af7fa476a6684c16ad34dd254248c40c3ff428f472bfdc186fad77d88e5
agent llm-post-training-engineer 8737d9ca4b370e6736fa747e2904dbd7acce32686bfdd81f2e947c1d9b98ad5a
agent loan-officer-assistant 80e4775533ae3303c11225338fa9f0878ad03d299db3749da1e5e4c4d207d9d7
agent lsp-index-engineer caad7bfed4f8bccf6cb0af9ad6409b952b4a6aa78af5b88431fd453b98ffd2f1
agent m-a-integration-manager d50cbc86474c9d2820737791cd5f8b8616c3ebba71ee9af0826d5e88d1500a70
agent macos-spatial-metal-engineer 9d46ec7ffad1767d472b2f1dc88b724aad63da8375b5550dbea53f0f47bd6b2b
agent master-plan-architect 5656f370a1e043c527b59f7401570e40033b65fb03db2f1498416f22eceeb3f8
agent mcp-builder 0dfeeea08a5819a19974f951b222debc3bcc619e36577d71ef543559cd1f9cca
agent medical-billing-coding-specialist c4eb556bf7ce7c9472b887c27a1a94992504eaed72d2758b387f3fe0a262f813
agent meeting-notes-specialist 1b33a0d8383926ae28549d9186afba9ded953b47daf2db02a61eb00169d22b9e
agent minimal-change-engineer 718463d5a96ea6a17da19f5f14ac7b4981085a5be35c750690feaa0998ebce2e
agent mobile-app-builder fcc09e3672776311a14c6d7c3402af32bb1f0492ce0d5b5a08ea7dc6e773963a
agent mobile-release-engineer efd8b28f0d85bfe38fa436ba0f96f6a45c41ca51c14a844281324a210c49b5d4
agent model-qa-specialist 8da6617fd0389f078012dc11bb87ec865425bf22016cc52a39f8ed08ede3ba04
agent multi-agent-systems-architect eb64d61e4af1728303a258d0756bffe5d9ee021895e62e7ca28af286400b49df
agent multi-platform-publisher e1a31098ef94e704f3fe9977a001103b093e4010d56fd825812518cbbc19a681
agent narrative-designer 62738d124d23f3e28654516bebc1c7bf92486edf6af2a9bc6f028e78930c46fa
agent narratologist 1833964a2264138c9db1e2ccdc56151c842c0e7bc4751839962e4ac984feac27
agent network-engineer 5d5e2243d3c23826e5c9234cb52d8188d7410221c7b94c1d426252dfabf88fd2
agent offer-lead-gen-strategist 804cd861e2e629537611442df6d08d4df9884f4f5c86f0549005c6f0ac82d9ac
agent operations-manager 15a22ee8517193b40a95c4601a8549bfde3be833f610b03ddf3abd4f20102905
agent organizational-psychologist 4701bd63d3ea3187e3a3bae6947b7b4575ff00f1e085dc4d5cfc1142ca701a05
agent orgscript-engineer 45953b7418d62779f12ee0a00e735a9c5a9abb2595f847dd8f9e0e3edabd3230
agent outbound-strategist 064b42e7edf4b82f26d7173dd94b31641d2a4a70cb917933a0ec4acc74c3bbf3
agent paid-media-auditor ac1b6d6556037b3c80a2a3cbf3d9e0b8295ad7dc0c3b7d4734a3b0d980a088bc
agent paid-social-strategist 4c5917fe0086daf6fbb2859952336e04c5f55fb0b78d9fc66efdc19251e95921
agent payments-billing-engineer 2cecf17d55f824af2bcf0c8250900452b86dfcaae256f695f1b3a1247e20f082
agent penetration-tester 07f8a920a02280e254a0bdee38bc03c7b1e278a791fce6c195bcf9ced100816d
agent performance-benchmarker a0e2e818e4bacaf6a9b9e8d4038a553434d5237e13f7b361d8e9326e2ab81514
agent persona-walkthrough-specialist 854795d5d704c3a320120fbaa06b0e2674e2cf7c59c1138f13a78f40afcbb3ba
agent personal-growth-mentor bbc0308d1d4b3489b367443b6a692ded21baeae053e177583e11611d4b47ea23
agent pipeline-analyst 6eaf2082012f2ccf0a98463f6b5d0798e91b0d746dbcd0584ddf9792f0adc4e2
agent podcast-strategist d33c6c447a3052bce34ea67687fa1ab1c83299d5ca3af2868805f8f6d28476eb
agent ppc-campaign-strategist 80e1ba09b9b16fcb7e8c36cdb4e4d4e9b90e68c3385541408a808ac44e66cc82
agent pr-communications-manager 985987b563f82b26480af8148e023508549a0f971a0f2a9860c347d0d994bb74
agent pricing-analyst 60b55e4bc2a917d407aea47dec558bc14dd2b913bb22817628bea448c80f5da9
agent privacy-engineer d9f13c3c603d0e5413d91d59054fab2578db1da2afca51d7be4359b2cf39747f
agent private-domain-operator 8c75c2a6134a4591c636191c4e0631ff715a5f638b260e25fc52c8f8d8b3dd67
agent product-manager 15f15072051256ff48256c3c0af2a2a626499158fef2625e677850a120a3b0ce
agent programmatic-display-buyer 74e79e5dc286b877d7cdfb00357382d8d28c3ff0e9049214e4140b15330cf5d2
agent project-shepherd 84233bd4d5ee07e3804b86f2affe56ad215ca717eebdcfa69002b350f4fb384d
agent prompt-engineer 13345946e965bdd2abf3b084caef48a1cc69acf1183f8232933ba525b2876a27
agent proposal-strategist 086efada0b1f21d4d09ed82bb33333f8647b7e31c6a44e67270b3d2abdf4a19d
agent psychologist 64d9265499c16a89dc94af4a72ab7edec572827c8b67cef14a35149b1e8ce6cf
agent rag-pipeline-engineer 8d9fe77f6cefa8c2379c33fa43f88544161f003479d6434c4670e2c3fcffcaad
agent rapid-prototyper 0ef3c873f9b0bfae063b9315703aea5ebba1e8342b5cdce98897638774bb3119
agent real-estate-buyer-seller bfa0e2fd9e226ef8ea3d16d8115ae60b673164f3d174d02cd088ec6d237e09b3
agent reality-checker d1aee0e310aacb2dc2581b04867fbc038d0f570c4f1e6b946afe793b8d47818e
agent realtime-collaboration-engineer 851b1fff61bf9e1f724ec9e802aec55b81ad663f6e216967ef58d41e9353a956
agent recruitment-specialist ef82e43cbdd91b4d2956c961e17e5010d6149e6dae2325f0c676c090896d04c5
agent reddit-community-builder 136badbecbe03d54c88ec7f2a74140034d2596eea2259345830b5195c764d5a5
agent report-distribution-agent 2cd7fe2536e880a739dc7016c94d222a2e651d94a8d0d82ec4b533b17bf832ed
agent research-synthesist 530104559dbb35a2176d108faf672053f8ae8018ac7bcf3056ebc1b782619749
agent resume-tailor 62059aac988ca39ba553aa7d0a83b4adcbf9be11f4727ed4465e112cd5f50dcb
agent retail-customer-returns 99475b79fc918c5565af6afe88aa4b5bde232e6bc4642e922dd5c1ae97d075e6
agent roblox-avatar-creator 55cf9073681028a635ffd0f3aa074edd9ab663d88dbe600c75b5465a0cf06f2d
agent roblox-experience-designer 4df6d426b2855185fe4127df663ad8cf1db8dcf916cf5fb4867fc854f46ec1a7
agent roblox-systems-scripter 76dd0a0a3abd53ec453a0d276a76fbb9722911580711a393f26d9735ea1e70a4
agent rust-refactoring-specialist 51ce94f93b03da8d48b56ac01173dbf34472e752a854d8a074106675c4cb1cb0
agent sales-coach 3f38afd01f7a0b6c01f02fc702dedab014fb5825f978feb9a698ba738c00ce0b
agent sales-data-extraction-agent 4ddcf6bc8b87c648a160b506f30c0fcc6ae8f847962d01fc58b2d1be1687589a
agent sales-engineer 9b9a8eac07ec272a5b650e0a044bc3d8b6837bbb85ba409f31b9b0d0181212be
agent sales-outreach 51bc877094326166a5c3344145f2637d165b59819d7760314940cbf169db2955
agent salesforce-architect f1b2f2de8a0896dc90f72478ce698b36494b2ff13e7fbc7212ca19efc8afa240
agent search-query-analyst 57eba2df774c6d54354cce18dbf748357548c937b2c892686fbcbd5d37c82eb0
agent search-relevance-engineer 85722db3d07a2d8335e3cd6b55ec10249e74b90d72b2e107c62d285472c00d92
agent secrets-credential-hygiene-engineer 323b69018a6592e9a3e85f820421f3b72e21fc1243d93a84a9e565a6c131fc51
agent section-508-accessibility-specialist a19c628ad66dc5592944d196a7829e361ccf225545775b9cbb18ee3d3dff999b
agent security-architect 222d463796940d96feef6d9d59487a6bc34e61cd5fe55fdbecc87c7820e4adc3
agent senior-developer c1e8fab47ee289e56168570f6cd0f1f9052be4915d0766f3ee74e593dfe7ac53
agent senior-project-manager 91e7a4123509589b8aa38ad4956f6e5e3f0dbb2eda5637991e18cd5e76798a9c
agent senior-secops-engineer a87a4cd68c24bdc857899b952d92a7256cd4421ac1490384ca3517e135c9432d
agent seo-specialist 97a5d243907d1bb9998ab1db95407f0d668f34f71c259a75f86cd695bbe8c018
agent short-video-editing-coach d6765240cf3c30554c3285814a85eb502512b2a942f69cd7efe6830d097155d8
agent social-media-strategist 9633737e00070aecee9dec5a73905141984ef1b72b8d313f9630f7e80a04f907
agent software-architect 711aef19407615b460d1cc60be7b465d2837a9649889ebcced9345cfa03ce6f0
agent solidity-smart-contract-engineer 5aefcc4f0eb4580f2a99d83e905d0d769eb605d87b0c82b6f291e154ef794087
agent solution-engineer 00f98ed471d33ff6b8ee9cdfe092bf3253e4a419b654827473f69631640761fe
agent sovereign-health-systems-agent 0eee82d7f42393ce56999598737e3cf1259837e02f1435b7454c41f026e521d0
agent spatial-data-engineer 0a92db82ba1d7a3e777e3cd7d4d536e61cf66da084ecc33a74700892be9f80ce
agent spatial-data-scientist 7ff1488011765946e8680f2133aae9f0bfceef745c7a6e98e3e8b047faf2f023
agent sprint-prioritizer 97d25ffd1f328d21b51363452089df6331633903ed8e4b76aafa81ee5213e33d
agent sre-site-reliability-engineer 6b2eb3d22f60a0b97cdd450c5a6c88b004a8ea2b564d918c2f8739ac8c6f6f2a
agent statistician e410f8e3b186025408e58769b93894310140f98148b7d8768feb4d96c3cdd2d3
agent strategy-duel-agent 79e00696d488b13538faeac30cfe86036efa47c60acfc1f6698c53233059cc8f
agent studio-operations aa940e3c12ae5118a649ec0dbd385185e944e2f42ca9636b9de04eae696b3cb8
agent studio-producer 7020d5e7807b9466ae1bcb651f93212f6db30f6ca1339d135ef8f31733321a8b
agent study-abroad-advisor 4b9f0edc1a08402d6165d50e469388246af39d37b98bb04a1f0baba85f0019ed
agent supply-chain-strategist b5d5d3cd8479864643d0eb2abc9b9def959fee22d6c726e522ea4e29178a9e03
agent support-responder 176312f2769adc5fdeab572eb5335d9f71f945f540cb60517b16e9c06e03817d
agent tax-strategist 5b2bc49008e11889f218e10b09cdbbf862af8bf3437852564b2301083bc42615
agent technical-artist 33198a9a6ce5b828290b39f8750e1f712603888e9ed38bf376fc31db4f5ea1ea
agent technical-consultant 04bdebd58130a032fe7427f442ddf4dc7c30e5ad261566aa2797dbb26e8cd710
agent technical-writer 9b4ff0e0d74bb187f859c113f0df7f588c03f41f83594c6525c4bde57ef03fe4
agent terminal-integration-specialist 958dc0b4f345cdb727b698927ecb170af4b180be917b46323cb0228d2c260173
agent test-automation-engineer ddd3af1da3156cfd478b3e5a631410fe3d6f551b123d25f224137b1184b01c6e
agent test-results-analyzer b61fa7cb528a82cbd1ea8da6cccd959938ad274053f6cbc19545385ed231a848
agent threat-detection-engineer 6b6933ebc896e078d0f77fc826238ef4142f1c6d930da0044b5228d5bf7b88de
agent threat-intelligence-analyst 54699417d65b00afc63f5a88bc804e7bff593fa6c2e5c0a8330f631de9e0cb71
agent tiktok-strategist 1a29fc17b8295442b8af367974fcc9fc3fa6a3311ab4ef76739d6b5e254ed2fe
agent tool-evaluator 543315ffccebda0a27390580f222a7049f8fdc1d2c9d235ed2274761ff4018f3
agent tracking-measurement-specialist 0deb53ff7752759c96d800b189cd70b210b8b2c51235080807fb744399571b93
agent trend-researcher 8ad6219bf8aa012b4e24726f8939770b4c243d060613778460080d23b956298b
agent twitter-engager 44eb97870c566e958e12bd25399dee18457666a6720bdefe53baed5599db314f
agent ui-designer ce285582f2d6e2389d61af41e52c9dc76cf8d0bb167e050684e0f0719afc2ae5
agent ui-finish-gate-reviewer 8ba4214f6fdb54cf6fc1c6ae15783db8d12e293a5d0bdfbacc7ccc23efc3a479
agent unity-architect c48f56c636b1d6d0804313c2d8e1b6c5139391a8127af5f1bf9a06afc85e1746
agent unity-editor-tool-developer b1d8eaa48f83d2eebf86481c045737c39ad13f264b6ffeb658556e152ea41b84
agent unity-multiplayer-engineer b30a0dbb49856eb1f9d00bc3109e188f6a25db76ba208c284cffc41dd4a054cf
agent unity-shader-graph-artist 3ac6c3d1635bf44bfe002f068314d9608220ad308f01156af8ea13044babdf5b
agent unreal-multiplayer-architect e4cb2db600888b31de5430ec46c06dfa2ef40f31ea5372e303cf62a9dc51a1eb
agent unreal-systems-engineer e3413866f222ff57dc15359f1f3d7fad1989012a75d71d1b7e2f274ea69eb2b4
agent unreal-technical-artist 8d8d6640ec9baa4b28b2eea5fda473f28a9fdf4a230234ee99fee4b4230f90b5
agent unreal-world-builder 6b8af4df8843e905e6935806b60f405d05872ec4b59219a0baf9d95884ea9701
agent uswds-developer 5be7af60edbcc4c0b3d58ddd8cbcf8fd84dacd67c2db587f05407f7446c0ce61
agent ux-architect 35b5e29ae0a198b1482207d3da0020d139c26c8e9b5494e8a87aa05b08e81517
agent ux-researcher c3e0849270788805f96ea26c89084496172a52be485e1ad028a0675cd7a8b99d
agent video-optimization-specialist 06276d84de0a51679c761824e0271e9e86122eb08931bac7d8ee3c27f4ae65f6
agent video-streaming-engineer 38a9ce5e88b02868c4412e8f6c67661dbd5da9ff12f60bc804cee262830b072b
agent visionos-spatial-engineer 580ff7226293af03a46ef69c83b45664d0692c2eb7b5097e8ec9a7c5c48f5c82
agent visual-storyteller 2dc2680f9d859697216843dec66e38153bb0506bf8e8bbc73e8c8802c9a489f4
agent voice-ai-integration-engineer ac6059cab86fe03ca6111357d749f73901ff721579da9ad2934cf31526b3c071
agent web-gis-developer a6d5047093e5b3c1951142a5434a238d9ff2bcb80ea58020e0ce1a9671ea450c
agent webassembly-engineer b60aa610dd0142b1fbe700749caad033a7288631d187679f683a173fb58be715
agent wechat-mini-program-developer 5011a5b045b917d0548ae3942f5dbba4c689d06dcb7c727e16e42c11d40b4b8f
agent wechat-official-account-manager f9dbee8c209233363c915c039fc4d9eb0ddf67faa6f852ea32115f9c97c5b025
agent weibo-strategist b33678661a8f70df52e85b6f735abb10d8e1b72ba5f115361feed487b6717305
agent whimsy-injector bde4c2dd75a6d788dfa5312378b90bdc73702d6639c4119ded76336f5c0f604c
agent wordpress-performance-engineer f639bd07726c824e69aa326f305d987f118d3460c72e77aab7f710199b36c3ff
agent wordpress-shopping-cart-engineer 40bb89da2129c1d8ba844a975d875c5ade1c72eb856bd4ffc83e259fc83b6393
agent workflow-architect ef4638a6903c48e7506a106ff3b5a899d98649545e5c40246f754b1862e56341
agent workflow-optimizer 0e45d85379f4dcfbf198b154c92e2f1f701b9bd8c612a8c429ecde0d7c34996a
agent x-twitter-intelligence-analyst 74523e67f87e75308f0c3716d8d88ae22308489ed5f02a51c98d764fa9ca61ce
agent xiaohongshu-specialist 1eb1734f426ab9356eebfcabe4b1b5fa18c05357ebd3e5ed9053c5488023f85a
agent xr-cockpit-interaction-specialist 28a6140385133a669e50e01a72e73ab3290133a817488556f587124666af117b
agent xr-immersive-developer 5fc625ce7e0248360a8c1face34f09770e30be54e8be17b8a5e9a7faa756bf65
agent xr-interface-architect 58a32671e074f28930558d5e911960c08f8eff07fa0d55d9e8ac61c19b4774c5
agent zhihu-strategist 16022d018f20633327d77bd09f83dfdca5a03d6a7a7299daab6373f62971cd34
agent zk-steward a8fcb272e873c58064167d066594dd792dd36263b5393a7813b35d23ddf3bd50
tool antigravity e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tool gemini-cli e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tool opencode e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tool cursor e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tool aider c64dd58c36d755a6a0738dbbd4915feb82a16c643333edd0cbe423f60765ed3a
tool windsurf e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tool openclaw e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tool qwen e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tool zcode e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tool kimi e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tool codex e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tool osaurus e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
tool hermes b5f3ec8e93b5690e1351ec69509e3a6aeac15f94fe6b2c6495a8d739cdec8b5b
tool vibe e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
contract divisions.json a85d4ceeabe671051559e7703dfca074bf7a259ba26b61fb5e14ed36d54ae051
contract tools.json 2b9635406d8980dfde28849f965f2a22de384b4906128ec345ef6fc6246f127d
contract strategy/runbooks.json 2d0372782460694bddcbdb5ec04ff28ae6284a2c751888f8010e16033024ac49
+127 -29
View File
@@ -19,19 +19,30 @@
# description carries no leaked quote character # description carries no leaked quote character
# #
# Layer B — drift (needs the committed manifest): # Layer B — drift (needs the committed manifest):
# scripts/convert-outputs.sha256 holds one aggregate hash per tool plus the # scripts/convert-outputs.sha256 (v2) holds
# three cross-repo contracts (divisions.json, tools.json, runbooks.json). # agent <slug> <hash> one line per roster agent: that agent's generated output
# A flipped line means that tool's outputs (or a contract) changed; the # across every tool (its files, its section of the
# author regenerates deliberately with --update and the diff shows the blast # accumulated aider/windsurf files, its hermes JSON entry)
# radius in review. Per-agent detail: --diff. # tool <tool> <hash> the tool's NON-agent files (README, plugin code, manifests):
# moves only when a generator/template changes
# contract <file> <hash> divisions.json, tools.json, runbooks.json
# Adding or editing one agent flips exactly its own line, so two agent PRs
# never collide on this file. Hashes are platform-neutral: forward-slash paths
# and LF line endings, so a Windows checkout produces the same manifest.
#
# Contributors adding/editing agents do NOT need to touch the manifest: CI runs
# this with --drift=advisory on pull requests (drift is printed, not failed) and
# maintainers regenerate it when the PR lands. A generator change should ship
# with --update so the tool line moves in the same commit.
# #
# Usage: # Usage:
# ./scripts/test-convert-outputs.sh # generate into a temp dir, check everything # ./scripts/test-convert-outputs.sh # generate into a temp dir, check everything
# ./scripts/test-convert-outputs.sh --update # ...and rewrite the manifest # ./scripts/test-convert-outputs.sh --update # ...and rewrite the manifest
# ./scripts/test-convert-outputs.sh --diff # list per-agent files behind a flipped line # ./scripts/test-convert-outputs.sh --drift=advisory # drift is reported but does not fail (CI on PRs)
# ./scripts/test-convert-outputs.sh --out=DIR # check an already-generated DIR (no generation) # ./scripts/test-convert-outputs.sh --out=DIR # check an already-generated DIR (no generation)
# #
# Exit 0 only when every check passes AND the manifest matches (or --update). # Exit 0 only when every invariant passes AND the manifest matches (or --update,
# or --drift=advisory).
# Runs on bash 3.2 (macOS) and 5 (Linux); parsing is done by python3. # Runs on bash 3.2 (macOS) and 5 (Linux); parsing is done by python3.
set -euo pipefail set -euo pipefail
@@ -40,13 +51,15 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
MANIFEST="$REPO_ROOT/scripts/convert-outputs.sha256" MANIFEST="$REPO_ROOT/scripts/convert-outputs.sha256"
UPDATE=false; DIFF=false; OUT="" UPDATE=false; DIFF=false; OUT=""; DRIFT=strict
for a in "$@"; do for a in "$@"; do
case "$a" in case "$a" in
--update) UPDATE=true ;; --update) UPDATE=true ;;
--diff) DIFF=true ;; --diff) DIFF=true ;;
--drift=advisory) DRIFT=advisory ;;
--drift=strict) DRIFT=strict ;;
--out=*) OUT="${a#--out=}" ;; --out=*) OUT="${a#--out=}" ;;
-h|--help) sed -n '2,36p' "$0"; exit 0 ;; -h|--help) sed -n '2,44p' "$0"; exit 0 ;;
*) printf 'unknown flag: %s\n' "$a" >&2; exit 2 ;; *) printf 'unknown flag: %s\n' "$a" >&2; exit 2 ;;
esac esac
done done
@@ -95,11 +108,12 @@ fi
# --- check: invariants + manifest (python does the parsing) ------------------- # --- check: invariants + manifest (python does the parsing) -------------------
REPO_ROOT="$REPO_ROOT" OUT="$OUT" SOURCES="$SOURCES" N="$N" MANIFEST="$MANIFEST" \ REPO_ROOT="$REPO_ROOT" OUT="$OUT" SOURCES="$SOURCES" N="$N" MANIFEST="$MANIFEST" \
UPDATE="$UPDATE" DIFF="$DIFF" TOOLS="$TOOLS" python3 - <<'PY' UPDATE="$UPDATE" DIFF="$DIFF" DRIFT="$DRIFT" TOOLS="$TOOLS" python3 - <<'PY'
import os, sys, glob, json, hashlib, yaml, tomllib import os, re, sys, glob, json, hashlib, yaml, tomllib
R, OUT, N = os.environ["REPO_ROOT"], os.environ["OUT"], int(os.environ["N"]) R, OUT, N = os.environ["REPO_ROOT"], os.environ["OUT"], int(os.environ["N"])
MANIFEST, UPDATE, DIFF = os.environ["MANIFEST"], os.environ["UPDATE"] == "true", os.environ["DIFF"] == "true" MANIFEST, UPDATE, DIFF = os.environ["MANIFEST"], os.environ["UPDATE"] == "true", os.environ["DIFF"] == "true"
ADVISORY = os.environ.get("DRIFT") == "advisory"
TOOLS = os.environ["TOOLS"].split() TOOLS = os.environ["TOOLS"].split()
# slug -> (description, name, source path) # slug -> (description, name, source path)
@@ -279,36 +293,120 @@ for m in src_bad[:5]: bad(m)
if len(src_bad) > 5: bad(f"...and {len(src_bad)-5} more source frontmatter problems") if len(src_bad) > 5: bad(f"...and {len(src_bad)-5} more source frontmatter problems")
if not src_bad: ok(f"all {N} source agents strict-parse (app contract)") if not src_bad: ok(f"all {N} source agents strict-parse (app contract)")
# --- Layer B: manifest --------------------------------------------------------- # --- Layer B: manifest (v2: per-agent lines, platform-neutral hashes) ----------
def norm_bytes(b): return b.replace(b"\r\n", b"\n")
def sha(b): return hashlib.sha256(b).hexdigest() def sha(b): return hashlib.sha256(b).hexdigest()
def tool_hash(tool): def rel(f): return os.path.relpath(f, OUT).replace(os.sep, "/")
h = hashlib.sha256()
slugs = set(src)
names = {name: slug for slug, (_d, name, _p) in src.items()}
per_agent = {slug: [] for slug in slugs} # slug -> [(label, bytes)]
per_tool = {t: [] for t in TOOLS} # tool -> [(label, bytes)] for non-agent files
def owner_of(path):
"""Which roster agent a generated file belongs to, by exact path component or stem."""
parts = rel(path).split("/")[1:] # drop the tool dir
for comp in parts[:-1]:
d = comp[len("agency-"):] if comp.startswith("agency-") else comp
if d in slugs: return d
stem = os.path.splitext(parts[-1])[0]
return stem if stem in slugs else None
for tool in TOOLS:
pat, fmt = SPEC[tool]
for f in sorted(glob.glob(os.path.join(OUT, tool, "**", "*"), recursive=True)): for f in sorted(glob.glob(os.path.join(OUT, tool, "**", "*"), recursive=True)):
if os.path.isfile(f): if not os.path.isfile(f): continue
h.update(os.path.relpath(f, OUT).encode()); h.update(sha(open(f, "rb").read()).encode()) data = norm_bytes(open(f, "rb").read())
if fmt == "accum" and rel(f) == f"{tool}/{pat}":
# One file for all agents: attribute each "## <name>" section to its agent;
# anything outside a known section (preamble) is the tool's contract.
lines_ = data.decode("utf-8", "replace").split("\n")
cur, buf, pre = None, [], []
def flush():
if cur: per_agent[cur].append((f"{tool}:section", "\n".join(buf).encode()))
for l in lines_:
m = names.get(l.rstrip()[3:]) if l.startswith("## ") else None
if m: flush(); cur, buf = m, [l]; continue
(buf if cur else pre).append(l)
flush()
per_tool[tool].append((rel(f) + ":preamble", "\n".join(pre).encode()))
continue
if fmt == "json" and rel(f) == f"{tool}/{pat}":
try:
items = json.loads(data.decode("utf-8"))
items = items if isinstance(items, list) else items.get("agents", [])
for it in items:
sl = it.get("slug") if isinstance(it, dict) else None
if sl in slugs: per_agent[sl].append((f"{tool}:entry", json.dumps(it, sort_keys=True, ensure_ascii=False).encode()))
else: per_tool[tool].append((rel(f) + ":stray-entry", json.dumps(it, sort_keys=True, ensure_ascii=False).encode()))
except Exception:
per_tool[tool].append((rel(f), data))
continue
o = owner_of(f)
if o is None and os.path.basename(f).lower() == "readme.md":
# Roster-derived text in generated docs ("Generated agent count: 273") must not move
# the tool line — only template changes should.
data = re.sub(rb"(?m)^(Generated agent count: )\d+$", rb"\1N", data)
(per_agent[o] if o else per_tool[tool]).append((rel(f), data))
def digest(entries):
h = hashlib.sha256()
for label, b in sorted(entries, key=lambda e: e[0]):
h.update(label.encode()); h.update(b"\0"); h.update(sha(b).encode()); h.update(b"\n")
return h.hexdigest() return h.hexdigest()
lines = [f"{t}\t{tool_hash(t)}" for t in TOOLS]
rows = [("agent", slug, digest(per_agent[slug])) for slug in sorted(slugs)]
rows += [("tool", t, digest(per_tool[t])) for t in TOOLS]
for c in ("divisions.json", "tools.json", "strategy/runbooks.json"): for c in ("divisions.json", "tools.json", "strategy/runbooks.json"):
p = os.path.join(R, c) p = os.path.join(R, c)
lines.append(f"{c}\t{sha(open(p,'rb').read()) if os.path.exists(p) else 'MISSING'}") rows.append(("contract", c, sha(norm_bytes(open(p, "rb").read())) if os.path.exists(p) else "MISSING"))
new = "\n".join(lines) + "\n" new = ("# convert-outputs manifest v2 — one line per agent (its output across every tool), one per tool\n"
"# (non-agent files), one per contract. Platform-neutral hashes. Regenerate: scripts/test-convert-outputs.sh --update\n"
+ "".join(f"{k}\t{key}\t{h}\n" for k, key, h in rows))
def drift_report(old_text):
old = {}
for l in old_text.splitlines():
if l.startswith("#") or "\t" not in l: continue
f = l.split("\t")
if len(f) == 3: old[(f[0], f[1])] = f[2]
elif len(f) == 2: return None # v1 manifest
cur = {(k, key): h for k, key, h in rows}
changed = sorted(key for (k, key), h in cur.items() if (k, key) in old and old[(k, key)] != h and k == "agent")
added = sorted(key for (k, key) in cur if k == "agent" and (k, key) not in old)
removed = sorted(key for (k, key) in old if k == "agent" and (k, key) not in cur)
tools = sorted(key for (k, key), h in cur.items() if k != "agent" and old.get((k, key)) != h)
return changed, added, removed, tools
if UPDATE: if UPDATE:
open(MANIFEST, "w").write(new); ok(f"manifest written: {os.path.relpath(MANIFEST, R)}") open(MANIFEST, "w", newline="\n").write(new); ok(f"manifest written: {os.path.relpath(MANIFEST, R)}")
elif not os.path.exists(MANIFEST): elif not os.path.exists(MANIFEST):
bad(f"manifest missing: run with --update to create {os.path.relpath(MANIFEST, R)}") bad(f"manifest missing: run with --update to create {os.path.relpath(MANIFEST, R)}")
else: else:
old = dict(l.split("\t") for l in open(MANIFEST).read().splitlines() if "\t" in l) d = drift_report(open(MANIFEST, encoding="utf-8").read())
changed = [l.split("\t")[0] for l in lines if old.get(l.split("\t")[0]) != l.split("\t")[1]] if d is None:
if changed: bad("manifest is the old v1 format (per-tool aggregate hashes) — run --update once to migrate")
bad("manifest drift — outputs/contracts changed for: " + ", ".join(changed) +
"\n If intended, review the change and run --update; if not, this is a regression.")
if DIFF:
for t in changed:
if t in SPEC:
print(f" --diff {t}: (regenerate on the base branch to compare per-agent; hashes are aggregate)")
else: else:
changed, added, removed, tools = d
if not (changed or added or removed or tools):
ok("manifest matches (no output or contract drift)") ok("manifest matches (no output or contract drift)")
else:
def few(xs, n=8): return ", ".join(xs[:n]) + (f", … ({len(xs)} total)" if len(xs) > n else "")
parts = []
if added: parts.append(f"new agents: {few(added)}")
if changed: parts.append(f"changed agents: {few(changed)}")
if removed: parts.append(f"removed agents: {few(removed)}")
if tools: parts.append(f"tool/contract lines: {', '.join(tools)}")
msg = "manifest drift — " + "; ".join(parts)
if len(changed) >= max(20, N // 4):
msg += f"\n {len(changed)} of {N} agents changed at once — that is a converter/template change, not an agent edit; review the generator diff"
if ADVISORY:
print(f" ADVISORY {msg}\n (expected for agent additions/edits; maintainers regenerate the manifest when this lands)")
ok("manifest drift reported (advisory mode)")
else:
bad(msg + "\n Agent lines move when agents are added/edited — regenerate with --update when landing."
"\n A tool/contract line moving means a generator or contract changed — review it.")
# --- report -------------------------------------------------------------------- # --- report --------------------------------------------------------------------
for m in fails: print(f" FAIL {m}") for m in fails: print(f" FAIL {m}")