diff --git a/.github/workflows/check-tools.yml b/.github/workflows/check-tools.yml index d09e526c..ec13b3ec 100644 --- a/.github/workflows/check-tools.yml +++ b/.github/workflows/check-tools.yml @@ -26,7 +26,9 @@ jobs: run: bash scripts/test-convert-frontmatter.sh - 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) run: bash scripts/test-agent-selection.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 47708dcc..3059e3b1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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 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** - — that's expected. Look over what changed, run it again with `--update`, and - commit the refreshed `scripts/convert-outputs.sha256` so reviewers can see - the blast radius at a glance. CI runs it on every PR. + on that tool's line — that's expected. Look over what changed, run it again + with `--update`, and commit the refreshed `scripts/convert-outputs.sha256` so + 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//*` 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 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. -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. diff --git a/scripts/convert-outputs.sha256 b/scripts/convert-outputs.sha256 index 75836c93..eae175c3 100644 --- a/scripts/convert-outputs.sha256 +++ b/scripts/convert-outputs.sha256 @@ -1,17 +1,292 @@ -antigravity 3a6a9f27c2478c05093f8cecef99793870250cfc1774e4d8642d8d92001d4b0e -gemini-cli 389eaa64b91beef18e999471f227036aefcbf3ac8d87858cabcae39a594c5951 -opencode 99af3bd8f155ea2ce9c5f9bfbf53ff1a083be1863cc998d2a40e63cd6314fff9 -cursor 169d7c6e752490cfe8ad9a40a0e13a19f5bb641862d580bad9b23596a7d731f2 -aider 9438f15e56aec67943b56deb21f459f4f4adeb457b96316309175c6ca6fcff30 -windsurf e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -openclaw 3019e15be427bc9d38e22765dab57951fe7d91d352c1b04b61e045f8b360dd22 -qwen 6602754c05df8a700dde9864afc3bf5275fa5c1b52a2c52771c63f0d5c4bf358 -zcode 994ce45c33d46d2c694d201792fc1cd9dffcb1bcfe285ab46767d7d29f0831c6 -kimi 0be25760acdcf1638c2605d05ffb80fe05f751b6b76e5b3ba67af82885118606 -codex d666dfb2d78328d0cfccb6ebcdb3d35103e2280cca113cf0248a78bb66039150 -osaurus 8c7b843ed0cfb8279ed75306c1744e14e49a1e6815a4ce7bb055d047b87a5cc6 -hermes 4b3909263d777345a6aad5af6d61dd75251bd7e29b867a4440f280f656224bb8 -vibe 8c79416463420d73bfa7ec79f51df95568bb7bd73626e1107137f8fa5900c9ea -divisions.json a85d4ceeabe671051559e7703dfca074bf7a259ba26b61fb5e14ed36d54ae051 -tools.json 2b9635406d8980dfde28849f965f2a22de384b4906128ec345ef6fc6246f127d -strategy/runbooks.json 2d0372782460694bddcbdb5ec04ff28ae6284a2c751888f8010e16033024ac49 +# convert-outputs manifest v2 — one line per agent (its output across every tool), one per tool +# (non-agent files), one per contract. Platform-neutral hashes. Regenerate: scripts/test-convert-outputs.sh --update +agent 3d-scene-developer fc016961eae1b7938a92f176a4f06a3b41aa383836c52cff93e2432adde1359f +agent accessibility-auditor 531e4d3f763385b8fec7cda81438b37a787013b14eaef4104fb250a560dbb40c +agent account-strategist 80b709f079672a78f96d972f61c1f7058c12f87bb323fd9e1702e38a3b1e528d +agent accounts-payable-agent e61a79cd9e94dc01efe6585d270a2b2452da14d8e74bc4174736ee7a982f66dc +agent ad-creative-strategist 20317f3a86123e8dfb4d9449e3e5ee66a3cfa6207a6e8810b3fd515a6528c50c +agent aeo-foundations-architect 609c0d0734afa4b13b6d3e36352b266a0c3fc60aafa9acb7f7d1f459e831cb99 +agent agentic-identity-trust-architect f085fe2b9bd5ace943b9db7b2356119158211155d015716c381594fa8658259a +agent agentic-search-optimizer b723e63deeb61f1716944e776b1a3606f83caabcd1feb7661fb9ba6d67973476 +agent agents-orchestrator 6e233f2aa73a22732da3fa31a9e4af48d99c7d985b48d6d0ac5d3ad79c594042 +agent aging-parent-care-companion 19da4e473b70eeb669f937c15c5b50c49759565cc15e99b316e1c1ab9ddd2de0 +agent ai-citation-strategist ef6a556ac3a6335bec190fb991b5394b403e2cceff62dbc583c92f4276aafb6b +agent ai-data-remediation-engineer b047eddc466be07592dafe1ba30702adfcc9f8e703ea85397bf2d5b6eff7bfd4 +agent ai-engineer 9a62bf0be72e0fd50f31b32aa327cbb3146c0167194789da2076f9267306aa5e +agent ai-generated-code-security-auditor 9e7291fd8fc34032a572ff3ea780554d9ca8f53202eb4257dcf0156629e24251 +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 diff --git a/scripts/test-convert-outputs.sh b/scripts/test-convert-outputs.sh index 31244264..8f6c03ec 100755 --- a/scripts/test-convert-outputs.sh +++ b/scripts/test-convert-outputs.sh @@ -19,19 +19,30 @@ # description carries no leaked quote character # # Layer B — drift (needs the committed manifest): -# scripts/convert-outputs.sha256 holds one aggregate hash per tool plus the -# three cross-repo contracts (divisions.json, tools.json, runbooks.json). -# A flipped line means that tool's outputs (or a contract) changed; the -# author regenerates deliberately with --update and the diff shows the blast -# radius in review. Per-agent detail: --diff. +# scripts/convert-outputs.sha256 (v2) holds +# agent one line per roster agent: that agent's generated output +# across every tool (its files, its section of the +# accumulated aider/windsurf files, its hermes JSON entry) +# tool the tool's NON-agent files (README, plugin code, manifests): +# moves only when a generator/template changes +# contract 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: -# ./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 --diff # list per-agent files behind a flipped line -# ./scripts/test-convert-outputs.sh --out=DIR # check an already-generated DIR (no generation) +# ./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 --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) # -# 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. set -euo pipefail @@ -40,13 +51,15 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" MANIFEST="$REPO_ROOT/scripts/convert-outputs.sha256" -UPDATE=false; DIFF=false; OUT="" +UPDATE=false; DIFF=false; OUT=""; DRIFT=strict for a in "$@"; do case "$a" in --update) UPDATE=true ;; --diff) DIFF=true ;; + --drift=advisory) DRIFT=advisory ;; + --drift=strict) DRIFT=strict ;; --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 ;; esac done @@ -95,11 +108,12 @@ fi # --- check: invariants + manifest (python does the parsing) ------------------- REPO_ROOT="$REPO_ROOT" OUT="$OUT" SOURCES="$SOURCES" N="$N" MANIFEST="$MANIFEST" \ -UPDATE="$UPDATE" DIFF="$DIFF" TOOLS="$TOOLS" python3 - <<'PY' -import os, sys, glob, json, hashlib, yaml, tomllib +UPDATE="$UPDATE" DIFF="$DIFF" DRIFT="$DRIFT" TOOLS="$TOOLS" python3 - <<'PY' +import os, re, sys, glob, json, hashlib, yaml, tomllib 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" +ADVISORY = os.environ.get("DRIFT") == "advisory" TOOLS = os.environ["TOOLS"].split() # 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 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 tool_hash(tool): - h = hashlib.sha256() +def rel(f): return os.path.relpath(f, OUT).replace(os.sep, "/") + +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)): - if os.path.isfile(f): - h.update(os.path.relpath(f, OUT).encode()); h.update(sha(open(f, "rb").read()).encode()) + if not os.path.isfile(f): continue + data = norm_bytes(open(f, "rb").read()) + if fmt == "accum" and rel(f) == f"{tool}/{pat}": + # One file for all agents: attribute each "## " 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() -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"): p = os.path.join(R, c) - lines.append(f"{c}\t{sha(open(p,'rb').read()) if os.path.exists(p) else 'MISSING'}") -new = "\n".join(lines) + "\n" + rows.append(("contract", c, sha(norm_bytes(open(p, "rb").read())) if os.path.exists(p) else "MISSING")) +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: - 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): bad(f"manifest missing: run with --update to create {os.path.relpath(MANIFEST, R)}") else: - old = dict(l.split("\t") for l in open(MANIFEST).read().splitlines() if "\t" in l) - changed = [l.split("\t")[0] for l in lines if old.get(l.split("\t")[0]) != l.split("\t")[1]] - if changed: - 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)") + d = drift_report(open(MANIFEST, encoding="utf-8").read()) + if d is None: + bad("manifest is the old v1 format (per-tool aggregate hashes) — run --update once to migrate") else: - ok("manifest matches (no output or contract drift)") + changed, added, removed, tools = d + if not (changed or added or removed or tools): + 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 -------------------------------------------------------------------- for m in fails: print(f" FAIL {m}")