@julioventura/opensquad 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +433 -0
- package/_opensquad/config/playwright.config.json +11 -0
- package/_opensquad/core/architect.agent.yaml +112 -0
- package/_opensquad/core/best-practices/_catalog.yaml +126 -0
- package/_opensquad/core/best-practices/blog-post.md +132 -0
- package/_opensquad/core/best-practices/blog-seo.md +127 -0
- package/_opensquad/core/best-practices/brand-resolution-checklist.md +172 -0
- package/_opensquad/core/best-practices/copywriting.md +441 -0
- package/_opensquad/core/best-practices/data-analysis.md +401 -0
- package/_opensquad/core/best-practices/email-newsletter.md +118 -0
- package/_opensquad/core/best-practices/email-sales.md +110 -0
- package/_opensquad/core/best-practices/image-design.md +348 -0
- package/_opensquad/core/best-practices/instagram-feed.md +235 -0
- package/_opensquad/core/best-practices/instagram-reels.md +112 -0
- package/_opensquad/core/best-practices/instagram-stories.md +107 -0
- package/_opensquad/core/best-practices/linkedin-article.md +116 -0
- package/_opensquad/core/best-practices/linkedin-post.md +121 -0
- package/_opensquad/core/best-practices/researching.md +349 -0
- package/_opensquad/core/best-practices/review.md +269 -0
- package/_opensquad/core/best-practices/run-recovery.md +61 -0
- package/_opensquad/core/best-practices/social-networks-publishing.md +327 -0
- package/_opensquad/core/best-practices/squad-creation-checklist.md +32 -0
- package/_opensquad/core/best-practices/strategist.md +344 -0
- package/_opensquad/core/best-practices/technical-writing.md +365 -0
- package/_opensquad/core/best-practices/twitter-post.md +105 -0
- package/_opensquad/core/best-practices/twitter-thread.md +122 -0
- package/_opensquad/core/best-practices/whatsapp-broadcast.md +107 -0
- package/_opensquad/core/best-practices/youtube-script.md +122 -0
- package/_opensquad/core/best-practices/youtube-shorts.md +112 -0
- package/_opensquad/core/defaults/youtube-video-assembly.json +84 -0
- package/_opensquad/core/prompts/build.prompt.md +613 -0
- package/_opensquad/core/prompts/design.prompt.md +606 -0
- package/_opensquad/core/prompts/discovery.prompt.md +377 -0
- package/_opensquad/core/prompts/sherlock-instagram.md +123 -0
- package/_opensquad/core/prompts/sherlock-linkedin.md +73 -0
- package/_opensquad/core/prompts/sherlock-shared.md +684 -0
- package/_opensquad/core/prompts/sherlock-twitter.md +78 -0
- package/_opensquad/core/prompts/sherlock-youtube.md +85 -0
- package/_opensquad/core/runner.pipeline.md +743 -0
- package/_opensquad/core/skills.engine.md +384 -0
- package/bin/opensquad.js +108 -0
- package/dashboard/index.html +15 -0
- package/dashboard/package-lock.json +1964 -0
- package/dashboard/package.json +28 -0
- package/dashboard/public/assets/avatars/Female1_1wave.png +0 -0
- package/dashboard/public/assets/avatars/Female1_2wave.png +0 -0
- package/dashboard/public/assets/avatars/Female1_blink.png +0 -0
- package/dashboard/public/assets/avatars/Female1_talk.png +0 -0
- package/dashboard/public/assets/avatars/Female2_1wave.png +0 -0
- package/dashboard/public/assets/avatars/Female2_2wave.png +0 -0
- package/dashboard/public/assets/avatars/Female2_blink.png +0 -0
- package/dashboard/public/assets/avatars/Female2_talk.png +0 -0
- package/dashboard/public/assets/avatars/Female3_blink.png +0 -0
- package/dashboard/public/assets/avatars/Female3_talk.png +0 -0
- package/dashboard/public/assets/avatars/Female3_wave.png +0 -0
- package/dashboard/public/assets/avatars/Female4_blink.png +0 -0
- package/dashboard/public/assets/avatars/Female4_talk.png +0 -0
- package/dashboard/public/assets/avatars/Female4_wave.png +0 -0
- package/dashboard/public/assets/avatars/Female5_blink.png +0 -0
- package/dashboard/public/assets/avatars/Female5_talk.png +0 -0
- package/dashboard/public/assets/avatars/Female5_wave.png +0 -0
- package/dashboard/public/assets/avatars/Female6_blink.png +0 -0
- package/dashboard/public/assets/avatars/Female6_talk.png +0 -0
- package/dashboard/public/assets/avatars/Female6_wave.png +0 -0
- package/dashboard/public/assets/avatars/Male1_1wave.png +0 -0
- package/dashboard/public/assets/avatars/Male1_2wave.png +0 -0
- package/dashboard/public/assets/avatars/Male1_blink.png +0 -0
- package/dashboard/public/assets/avatars/Male1_talk.png +0 -0
- package/dashboard/public/assets/avatars/Male2_1wave.png +0 -0
- package/dashboard/public/assets/avatars/Male2_2wave.png +0 -0
- package/dashboard/public/assets/avatars/Male2_blink.png +0 -0
- package/dashboard/public/assets/avatars/Male2_talk.png +0 -0
- package/dashboard/public/assets/avatars/Male3_blink.png +0 -0
- package/dashboard/public/assets/avatars/Male3_talk.png +0 -0
- package/dashboard/public/assets/avatars/Male3_wave.png +0 -0
- package/dashboard/public/assets/avatars/Male4_blink.png +0 -0
- package/dashboard/public/assets/avatars/Male4_talk.png +0 -0
- package/dashboard/public/assets/avatars/Male4_wave.png +0 -0
- package/dashboard/public/assets/desks/desktop_set_black_down.png +0 -0
- package/dashboard/public/assets/desks/desktop_set_black_down_coding-1.png +0 -0
- package/dashboard/public/assets/desks/desktop_set_black_down_coding.png +0 -0
- package/dashboard/public/assets/desks/desktop_set_black_up.png +0 -0
- package/dashboard/public/assets/desks/desktop_set_white_down.png +0 -0
- package/dashboard/public/assets/desks/desktop_set_white_down_coding-1.png +0 -0
- package/dashboard/public/assets/desks/desktop_set_white_down_coding.png +0 -0
- package/dashboard/public/assets/desks/desktop_set_white_up.png +0 -0
- package/dashboard/public/assets/furniture/armchair_tan.png +0 -0
- package/dashboard/public/assets/furniture/armchair_tan_down.png +0 -0
- package/dashboard/public/assets/furniture/backpack_blue.png +0 -0
- package/dashboard/public/assets/furniture/backpack_red.png +0 -0
- package/dashboard/public/assets/furniture/blinds.png +0 -0
- package/dashboard/public/assets/furniture/blinds_large_closed_white.png +0 -0
- package/dashboard/public/assets/furniture/bookshelf.png +0 -0
- package/dashboard/public/assets/furniture/bookshelf_purple_tall.png +0 -0
- package/dashboard/public/assets/furniture/bulletin_board.png +0 -0
- package/dashboard/public/assets/furniture/clock.png +0 -0
- package/dashboard/public/assets/furniture/coffee_mug.png +0 -0
- package/dashboard/public/assets/furniture/coffee_mug_blue.png +0 -0
- package/dashboard/public/assets/furniture/coffee_table.png +0 -0
- package/dashboard/public/assets/furniture/coffeepot_right.png +0 -0
- package/dashboard/public/assets/furniture/coffeetable_black_horizontal.png +0 -0
- package/dashboard/public/assets/furniture/couch.png +0 -0
- package/dashboard/public/assets/furniture/couch_tan_down.png +0 -0
- package/dashboard/public/assets/furniture/cushion_blue.png +0 -0
- package/dashboard/public/assets/furniture/cushion_tan.png +0 -0
- package/dashboard/public/assets/furniture/desk_wood.png +0 -0
- package/dashboard/public/assets/furniture/fancy_rug.png +0 -0
- package/dashboard/public/assets/furniture/fancy_rug_wide.png +0 -0
- package/dashboard/public/assets/furniture/flowers1.png +0 -0
- package/dashboard/public/assets/furniture/flowers2.png +0 -0
- package/dashboard/public/assets/furniture/lamp_tan.png +0 -0
- package/dashboard/public/assets/furniture/lantern.png +0 -0
- package/dashboard/public/assets/furniture/monstera.png +0 -0
- package/dashboard/public/assets/furniture/monstera_small.png +0 -0
- package/dashboard/public/assets/furniture/picture_frame.png +0 -0
- package/dashboard/public/assets/furniture/plant1.png +0 -0
- package/dashboard/public/assets/furniture/plant2.png +0 -0
- package/dashboard/public/assets/furniture/plant3.png +0 -0
- package/dashboard/public/assets/furniture/plant_poof.png +0 -0
- package/dashboard/public/assets/furniture/plant_spindly.png +0 -0
- package/dashboard/public/assets/furniture/poster_blue.png +0 -0
- package/dashboard/public/assets/furniture/rug.png +0 -0
- package/dashboard/public/assets/furniture/succulent_blue.png +0 -0
- package/dashboard/public/assets/furniture/succulent_green.png +0 -0
- package/dashboard/public/assets/furniture/treasurechest_closed_gold.png +0 -0
- package/dashboard/public/assets/furniture/water_cooler_better.png +0 -0
- package/dashboard/public/assets/furniture/whiteboard.png +0 -0
- package/dashboard/public/assets/furniture/whiteboard_stand_graph.png +0 -0
- package/dashboard/public/assets/furniture/window_blinds_open.png +0 -0
- package/dashboard/src/App.tsx +46 -0
- package/dashboard/src/components/RunDashboardButton.tsx +92 -0
- package/dashboard/src/components/SquadCard.tsx +49 -0
- package/dashboard/src/components/SquadSelector.tsx +67 -0
- package/dashboard/src/components/StatusBadge.tsx +32 -0
- package/dashboard/src/components/StatusBar.tsx +116 -0
- package/dashboard/src/hooks/useSquadSocket.ts +135 -0
- package/dashboard/src/lib/formatTime.ts +16 -0
- package/dashboard/src/lib/normalizeState.ts +25 -0
- package/dashboard/src/main.tsx +10 -0
- package/dashboard/src/office/AgentSprite.ts +241 -0
- package/dashboard/src/office/OfficeScene.ts +153 -0
- package/dashboard/src/office/PhaserGame.tsx +80 -0
- package/dashboard/src/office/RoomBuilder.ts +190 -0
- package/dashboard/src/office/assetKeys.ts +150 -0
- package/dashboard/src/office/palette.ts +32 -0
- package/dashboard/src/plugin/squadWatcher.ts +397 -0
- package/dashboard/src/store/useSquadStore.ts +56 -0
- package/dashboard/src/styles/globals.css +36 -0
- package/dashboard/src/types/state.ts +63 -0
- package/dashboard/src/vite-env.d.ts +1 -0
- package/dashboard/tsconfig.json +24 -0
- package/dashboard/vite.config.ts +13 -0
- package/package.json +59 -0
- package/public/sfx/slide-transition-sfx.mp3 +0 -0
- package/skills/README.md +84 -0
- package/skills/apify/SKILL.md +55 -0
- package/skills/blotato/SKILL.md +63 -0
- package/skills/canva/SKILL.md +60 -0
- package/skills/higgsfield/SKILL.md +147 -0
- package/skills/image-ai-generator/SKILL.md +124 -0
- package/skills/image-ai-generator/scripts/generate.py +175 -0
- package/skills/image-creator/SKILL.md +166 -0
- package/skills/image-creator/editorial-slide-template.js +645 -0
- package/skills/image-fetcher/SKILL.md +91 -0
- package/skills/imgbb-uploader/SKILL.md +73 -0
- package/skills/imgbb-uploader/scripts/upload.js +125 -0
- package/skills/instagram-publisher/README.md +36 -0
- package/skills/instagram-publisher/SKILL.md +231 -0
- package/skills/instagram-publisher/scripts/publish-playwright.js +418 -0
- package/skills/instagram-publisher/scripts/publish.js +521 -0
- package/skills/opensquad-agent-creator/SKILL.md +192 -0
- package/skills/opensquad-skill-creator/SKILL.md +420 -0
- package/skills/opensquad-skill-creator/agents/analyzer.md +274 -0
- package/skills/opensquad-skill-creator/agents/comparator.md +202 -0
- package/skills/opensquad-skill-creator/agents/grader.md +223 -0
- package/skills/opensquad-skill-creator/assets/eval_review.html +146 -0
- package/skills/opensquad-skill-creator/eval-viewer/generate_review.py +471 -0
- package/skills/opensquad-skill-creator/eval-viewer/viewer.html +1325 -0
- package/skills/opensquad-skill-creator/references/schemas.md +430 -0
- package/skills/opensquad-skill-creator/references/skill-format.md +235 -0
- package/skills/opensquad-skill-creator/scripts/__init__.py +0 -0
- package/skills/opensquad-skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/skills/opensquad-skill-creator/scripts/quick_validate.py +103 -0
- package/skills/opensquad-skill-creator/scripts/run_eval.py +310 -0
- package/skills/opensquad-skill-creator/scripts/utils.py +47 -0
- package/skills/pdf-extractor/SKILL.md +57 -0
- package/skills/pdf-extractor/scripts/extract.py +82 -0
- package/skills/resend/SKILL.md +80 -0
- package/skills/run-dashboard/README.md +93 -0
- package/skills/run-dashboard/SKILL.md +173 -0
- package/skills/run-dashboard/scripts/finalize-state.js +273 -0
- package/skills/run-dashboard/scripts/generate.js +1296 -0
- package/skills/run-dashboard/scripts/serve.js +135 -0
- package/skills/run-dashboard/templates/run-dashboard-simple.template.html +191 -0
- package/skills/run-dashboard/templates/run-dashboard.template.html +1164 -0
- package/skills/smtp-sender/SKILL.md +88 -0
- package/skills/smtp-sender/scripts/send.js +478 -0
- package/skills/template-designer/SKILL.md +201 -0
- package/skills/template-designer/base-templates/model-a.html +27 -0
- package/skills/template-designer/base-templates/model-b.html +31 -0
- package/skills/template-designer/base-templates/model-c.html +42 -0
- package/skills/youtube-publisher/SKILL.md +232 -0
- package/skills/youtube-publisher/scripts/publish.js +2078 -0
- package/src/agents-cli.js +158 -0
- package/src/agents.js +134 -0
- package/src/i18n.js +48 -0
- package/src/init.js +442 -0
- package/src/locales/en.json +79 -0
- package/src/locales/es.json +78 -0
- package/src/locales/pt-BR.json +78 -0
- package/src/logger.js +38 -0
- package/src/prompt.js +46 -0
- package/src/readme/README.md +146 -0
- package/src/runs.js +318 -0
- package/src/skills-cli.js +157 -0
- package/src/skills.js +146 -0
- package/src/supabase-cli.js +584 -0
- package/src/update.js +169 -0
- package/templates/_opensquad/.opensquad-version +1 -0
- package/templates/_opensquad/_investigations/.gitkeep +0 -0
- package/templates/ide-templates/antigravity/.agent/rules/opensquad.md +68 -0
- package/templates/ide-templates/antigravity/.agent/workflows/opensquad.md +102 -0
- package/templates/ide-templates/claude-code/.claude/skills/opensquad/SKILL.md +182 -0
- package/templates/ide-templates/claude-code/.mcp.json +8 -0
- package/templates/ide-templates/claude-code/CLAUDE.md +57 -0
- package/templates/ide-templates/codex/.agents/skills/opensquad/SKILL.md +6 -0
- package/templates/ide-templates/codex/AGENTS.md +120 -0
- package/templates/ide-templates/cursor/.cursor/commands/opensquad.md +9 -0
- package/templates/ide-templates/cursor/.cursor/mcp.json +8 -0
- package/templates/ide-templates/cursor/.cursor/rules/opensquad.mdc +62 -0
- package/templates/ide-templates/cursor/.cursorignore +3 -0
- package/templates/ide-templates/gemini-cli/.gemini/settings.json +8 -0
- package/templates/ide-templates/gemini-cli/.gemini/skills/opensquad/SKILL.md +186 -0
- package/templates/ide-templates/gemini-cli/GEMINI.md +57 -0
- package/templates/ide-templates/opencode/.opencode/commands/opensquad.md +9 -0
- package/templates/ide-templates/opencode/AGENTS.md +120 -0
- package/templates/ide-templates/qwen-code/.qwen/settings.json +8 -0
- package/templates/ide-templates/qwen-code/.qwen/skills/opensquad/SKILL.md +182 -0
- package/templates/ide-templates/qwen-code/QWEN.md +57 -0
- package/templates/ide-templates/trae/.trae/mcp.json +8 -0
- package/templates/ide-templates/trae/.trae/rules/opensquad.md +64 -0
- package/templates/ide-templates/vscode-copilot/.github/copilot-instructions.md +59 -0
- package/templates/ide-templates/vscode-copilot/.github/prompts/opensquad.prompt.md +209 -0
- package/templates/ide-templates/vscode-copilot/.vscode/mcp.json +8 -0
- package/templates/ide-templates/vscode-copilot/.vscode/settings.json +3 -0
- package/templates/package.json +8 -0
- package/templates/squads/.gitkeep +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "Run Recovery"
|
|
3
|
+
whenToUse: "Interrupted or manually resumed Opensquad runs that need deterministic closure across publishing, newsletter, and dashboard steps."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Run Recovery Playbook
|
|
7
|
+
|
|
8
|
+
Use this checklist when a run stops mid-execution, a wrapper command fails, or publication has to continue manually from an existing `squads/{name}/output/{run_id}/` folder.
|
|
9
|
+
|
|
10
|
+
## Deterministic Checklist
|
|
11
|
+
|
|
12
|
+
1. Confirm the canonical run folder.
|
|
13
|
+
Use the same `output/{run_id}` directory for every resumed step. Do not create a second run folder for the same execution.
|
|
14
|
+
|
|
15
|
+
2. Reconstruct the archived run state before closing anything.
|
|
16
|
+
Run:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
node --env-file=.env skills/run-dashboard/scripts/finalize-state.js --workspace-root . --run-dir "squads/{name}/output/{run_id}"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
If this step cannot infer a final state yet, continue the missing publish steps first and rerun the command before dashboard closure.
|
|
23
|
+
|
|
24
|
+
3. Recover Instagram/Facebook deterministically.
|
|
25
|
+
First rerun `instagram-publisher` with `--dry-run`.
|
|
26
|
+
If `createChildContainer` fails with transient media errors, retry once with a publish-safe caption: concise body, normalized punctuation, no raw source URLs, hashtags at the end.
|
|
27
|
+
If Instagram already succeeded but Facebook failed, use `--facebook --facebook-only` instead of reposting Instagram.
|
|
28
|
+
If the final Instagram `publishMedia` step fails with Meta `code 4`, `error_subcode 2207051`, or `Application request limit reached` after containers were created, stop retrying the Graph API path. Switch to Meta Business Suite with the approved images and caption, using the correct brand login for the target Instagram account/Page.
|
|
29
|
+
After any manual Meta Business Suite publish, verify the carousel order before finalizing the run. If the order is wrong, republish first. Delete the wrong Instagram post when permissions allow it; treat Facebook deletion as optional because Page permission context may still block cleanup.
|
|
30
|
+
|
|
31
|
+
4. Recover YouTube deterministically.
|
|
32
|
+
First rerun `youtube-publisher` with `--dry-run`.
|
|
33
|
+
If Google returns `invalid_grant`, treat the refresh token as revoked.
|
|
34
|
+
Generate a fresh consent URL, approve with the correct brand account, capture the `code` from the `127.0.0.1:3000` redirect URL even if the page shows `ERR_CONNECTION_REFUSED`, exchange that code manually for a new refresh token, update `.env`, and rerun the dry-run before the live upload.
|
|
35
|
+
|
|
36
|
+
5. Finish complementary distribution.
|
|
37
|
+
If the squad contract includes `jornal-matutino`, run:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
node --env-file=.env squads/jornal-matutino/scripts/send-from-run.js --workspace-root . --run-dir "squads/{name}/output/{run_id}"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
6. Regenerate the final dashboard only after the outputs above are complete.
|
|
44
|
+
Run:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
node --env-file=.env skills/run-dashboard/scripts/generate.js --workspace-root . --run-dir "squads/{name}/output/{run_id}"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
This step must happen after `publish-result.md`, newsletter outputs, and `state.json` are all present.
|
|
51
|
+
If static dashboard publish is enabled with `transport: ftp` or `transport: both`, confirm the configured `publish_dir_env` resolves and that the FTP env keys declared in `channel-config.yaml` are present before treating the run as closed.
|
|
52
|
+
|
|
53
|
+
7. Verify closure artifacts.
|
|
54
|
+
Confirm the run folder contains at minimum:
|
|
55
|
+
`publish-result.md`, `state.json`, `run-dashboard.html`, `run-dashboard.data.json`, and any expected newsletter files.
|
|
56
|
+
|
|
57
|
+
## Non-Negotiable Rules
|
|
58
|
+
|
|
59
|
+
- The runner pipeline document remains the source of truth if a CLI wrapper is incomplete.
|
|
60
|
+
- Do not close a run with dashboard publishing while `state.json` is still missing from the run folder.
|
|
61
|
+
- Do not retry live publishes blindly; always prefer the narrowest dry-run or partial recovery path first.
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: social-networks-publishing
|
|
3
|
+
name: "Social Networks Publishing"
|
|
4
|
+
whenToUse: |
|
|
5
|
+
Creating agents that publish content to Instagram, LinkedIn, X/Twitter,
|
|
6
|
+
YouTube, or other social platforms.
|
|
7
|
+
NOT for: copywriting, visual design, research, strategic planning.
|
|
8
|
+
version: "1.0.0"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Social Networks Publishing — Best Practices
|
|
12
|
+
|
|
13
|
+
## Core Principles
|
|
14
|
+
|
|
15
|
+
1. **Never publish without explicit user confirmation.** This is the cardinal rule. Before any live post, present the full preview (platform, images, caption, hashtags) and wait for the user to confirm. A dry-run is not confirmation. The user must explicitly say "publish" or "go ahead" before any live API call is made.
|
|
16
|
+
|
|
17
|
+
2. **Dry-run first, always.** The first execution of any publishing workflow must be a dry-run (test mode). This validates that credentials are configured, images meet requirements, captions are within limits, and the API connection works. Only after a successful dry-run should the user be offered the option to publish for real.
|
|
18
|
+
|
|
19
|
+
3. **Validate platform requirements before attempting to publish.** Every platform has specific constraints. Validate all of them before making any API call. If validation fails, report the specific issue and suggest a fix before proceeding.
|
|
20
|
+
|
|
21
|
+
4. **Format content natively for each platform.** The same content may need reformatting for different platforms. Instagram captions use line breaks and 5-8 hashtags at the end. LinkedIn uses professional tone with 1-3 hashtags. X/Twitter needs concise messaging within character limits. Never publish the exact same raw text across all platforms without adaptation.
|
|
22
|
+
|
|
23
|
+
5. **Report publishing results immediately.** After every publish attempt, report the outcome clearly:
|
|
24
|
+
- **Success**: Platform, post URL/permalink, post ID, timestamp
|
|
25
|
+
- **Failure**: Platform, error message, HTTP status code, suggested fix
|
|
26
|
+
- **Partial success** (multi-platform): Which platforms succeeded and which failed, with details for each
|
|
27
|
+
|
|
28
|
+
6. **Multi-platform publishing is sequential, not parallel.** When publishing to multiple platforms, publish to one at a time. Report the result of each before proceeding to the next. If one fails, ask the user whether to continue with remaining platforms or stop. Never fire-and-forget across all platforms simultaneously.
|
|
29
|
+
|
|
30
|
+
7. **Respect rate limits and warn proactively.** Track API usage against known rate limits. If the user is approaching a limit (e.g., 20 of 25 Instagram posts in 24 hours), warn them before the publish attempt, not after the error. Better to prevent a failed publish than to explain why it failed.
|
|
31
|
+
|
|
32
|
+
8. **Graceful handling of missing skills.** If the user requests publishing to a platform whose skill is not installed, do not error out. Instead: (a) list which platforms ARE available via installed skills, (b) explain which skill would be needed for the requested platform, (c) offer to proceed with available platforms only.
|
|
33
|
+
|
|
34
|
+
9. **Image format policy must match the active publisher.** In shared Opensquad social/newsletter flows, local slide assets may be JPG/JPEG or PNG. Validate against the active publisher before blocking, and never silently convert or silently fail. If a transformation is required, document it explicitly.
|
|
35
|
+
|
|
36
|
+
10. **Run dashboard finalization is automatic after the last selected output.** When a publish belongs to an Opensquad run, the run is not operationally complete until `run-dashboard.html` and `run-dashboard.data.json` are regenerated for that run. If the squad config enables static publish, publish the latest and archived snapshots automatically and report the URLs. Do not open a second confirmation step just for the dashboard.
|
|
37
|
+
|
|
38
|
+
## Platform Requirements
|
|
39
|
+
|
|
40
|
+
Every platform has specific constraints that must be validated before making any API call.
|
|
41
|
+
|
|
42
|
+
### Instagram
|
|
43
|
+
|
|
44
|
+
- **Image format**: JPG/JPEG or PNG
|
|
45
|
+
- **Image count**: 2-10 images for carousel
|
|
46
|
+
- **Caption length**: Max 2,200 characters
|
|
47
|
+
- **Rate limit**: 25 posts per 24 hours
|
|
48
|
+
- **Image hosting**: Use imgBB for public URLs (requires `IMGBB_API_KEY` in `.env`). Get a free key at <https://api.imgbb.com/>.
|
|
49
|
+
- **Multi-brand routing**: In shared workspaces, prefer squad-specific env aliases over generic keys whenever brand-specific variables already exist.
|
|
50
|
+
- **Known live-publish blocker**: If Instagram container creation succeeds but the final `publishMedia` call fails with Meta `code 4`, `error_subcode 2207051`, or `Application request limit reached`, treat it as a Graph API restriction for that app/account pair. Do not keep retrying blindly.
|
|
51
|
+
|
|
52
|
+
### LinkedIn
|
|
53
|
+
|
|
54
|
+
- **Image format**: JPG/PNG
|
|
55
|
+
- **Image count**: Max 9 images
|
|
56
|
+
- **Caption length**: 3,000 character limit
|
|
57
|
+
- **Hashtags**: No hashtag walls. Keep to 1-3 relevant hashtags.
|
|
58
|
+
|
|
59
|
+
### X/Twitter
|
|
60
|
+
|
|
61
|
+
- **Image format**: JPG/PNG/GIF
|
|
62
|
+
- **Image count**: Max 4 images
|
|
63
|
+
- **Caption length**: 280 characters (or 25,000 for long-form)
|
|
64
|
+
|
|
65
|
+
### TikTok
|
|
66
|
+
|
|
67
|
+
- **Content type**: Video only for posts
|
|
68
|
+
- **Aspect ratios**: Platform-specific aspect ratios required
|
|
69
|
+
|
|
70
|
+
### YouTube
|
|
71
|
+
|
|
72
|
+
- **Thumbnail format**: JPG/JPEG or PNG
|
|
73
|
+
- **Thumbnail size**: Max 2MB
|
|
74
|
+
- **Thumbnail dimensions**: 1280x720 minimum
|
|
75
|
+
- **Local dependency**: `ffmpeg` installed and callable from the same shell used for the publish command
|
|
76
|
+
- **Canonical slideshow assembly**: All YouTube slideshow videos must follow the standard defined in `_opensquad/core/defaults/youtube-video-assembly.json`. Key rules:
|
|
77
|
+
- Transition: `fadeblack`, 2 seconds, visual starts **after** the full slide narration block ends (never overlapping narration)
|
|
78
|
+
- Slide timing formula: `1s lead-in + title narration + 1s pause + text narration + 2s tail + 1s buffer`
|
|
79
|
+
- Middle slides get 2× `transitionDuration` as effective input duration (required by xfade for simultaneous in/out frames)
|
|
80
|
+
- Audio mix: always use `amix` with `normalize=0` to prevent volume jump on last slide when SFX ends before narration
|
|
81
|
+
- Transition SFX: reuse `public/sfx/slide-transition-sfx.mp3` (warm whoosh); do NOT regenerate per run
|
|
82
|
+
- Background music volume with voice: `0.12`; narration volume: `1.2`
|
|
83
|
+
|
|
84
|
+
## Publishing Workflow
|
|
85
|
+
|
|
86
|
+
- **Receive content and identify targets.** Receive the approved content (images and text) from upstream agents or the user. Identify the target platform(s) for publication. If the user has not specified platforms, ask before proceeding.
|
|
87
|
+
|
|
88
|
+
- **Check skill availability.** For each target platform, verify that the required publishing skill is installed:
|
|
89
|
+
- Instagram: `instagram-publisher` skill
|
|
90
|
+
- Multi-platform (LinkedIn, X, TikTok, etc.): `blotato` skill
|
|
91
|
+
- If a required skill is missing, inform the user and list alternatives.
|
|
92
|
+
|
|
93
|
+
- **Validate content against platform requirements.** For each target platform, check:
|
|
94
|
+
- Image format and count against the active publisher constraints (in the shared Opensquad flow, slides may arrive as JPG/JPEG or PNG)
|
|
95
|
+
- Caption length against character limit
|
|
96
|
+
- Aspect ratio compatibility
|
|
97
|
+
- Required local tools for the active publisher (for YouTube, validate `ffmpeg -version` before dry-run)
|
|
98
|
+
- Any platform-specific restrictions
|
|
99
|
+
- If validation fails, report the specific issue and suggest a fix before proceeding.
|
|
100
|
+
|
|
101
|
+
- **Present preview to user.** Show a clear, structured preview:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
PUBLISH PREVIEW
|
|
105
|
+
Platform: Instagram (carousel)
|
|
106
|
+
Images: 7 slides (slide-01.jpg through slide-07.jpg)
|
|
107
|
+
Caption: [first 200 chars]... (1,847 / 2,200 chars)
|
|
108
|
+
Hashtags: #marketing #contentcreation #socialmedia (3)
|
|
109
|
+
Status: All validations passed
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
- **Execute dry-run.** Run the publishing workflow in test mode:
|
|
113
|
+
- Instagram: `--dry-run` flag on the publish script
|
|
114
|
+
- YouTube: validate `ffmpeg -version` in the current shell, then run the publish script with `--dry-run`
|
|
115
|
+
- Blotato: validate API connection and media upload without posting
|
|
116
|
+
- Report dry-run results: credentials OK, media uploaded, container created, ready to publish.
|
|
117
|
+
|
|
118
|
+
- **Request final confirmation.** Present the dry-run results and ask the user to confirm the live publish. Do not proceed without explicit approval.
|
|
119
|
+
|
|
120
|
+
- **Publish and report.** Execute the live publish. Report the result immediately:
|
|
121
|
+
- Success: post URL, post ID, platform, timestamp
|
|
122
|
+
- Failure: error details, suggested fix, option to retry
|
|
123
|
+
|
|
124
|
+
- **Use a UI/Browser fallback when the API path is blocked.** If the Instagram Graph API dry-run or container creation succeeds but the live `publishMedia` step is blocked by the known Meta restriction above (such as rate limits or app-review requirement), switch to the automated Playwright browser fallback script (`publish-playwright.js`). If that automation is not available or encounters issues, perform a manual publish via Meta Business Suite using the same approved assets and caption. Always use the correct brand login for the target account/page.
|
|
125
|
+
|
|
126
|
+
- **Automated Browser (Playwright) Fallback Best Practices:**
|
|
127
|
+
- **Selector Behavior (Visibility vs. Attachment):** In the Instagram web interface, the file upload input element (`<input type="file">`) is styled with `display: none` and is permanently hidden. Consequently, a standard Playwright `waitForSelector('input[type="file"]')` will time out because it waits for visibility. You **must** specify `{ state: 'attached' }` to target this element correctly.
|
|
128
|
+
- **Click Event Bubbling:** Clicking a standard text span like `span:has-text("Criar")` directly might not bubble up to trigger the creation popup. Target the parent anchor link `a:has-text("Criar")` or a button container `div[role="button"]` instead.
|
|
129
|
+
- **Persistent Profile & Headful Execution:** Always run browser-based fallback publishing in headful mode (`headless: false`) and load the persistent user data directory (`_opensquad/_browser_profile`). This allows reusing authenticated sessions/cookies and allows the user to complete 2FA or click manually if any interface element changes.
|
|
130
|
+
|
|
131
|
+
- **Validate carousel order before finalizing.** In any manual or browser-automated publish flow, explicitly confirm that slide 1 is the cover and that the remaining slides stayed in the approved order before you treat the run as complete. If the order is wrong, republish before regenerating dashboards or reporting final URLs.
|
|
132
|
+
|
|
133
|
+
- **Finalize the run dashboard automatically.** After the last selected output succeeds, regenerate the run dashboard for the same run folder. If `jornal-matutino` is still pending, wait and do this only after the newsletter step completes. If the squad config enables static publish, let the dashboard step publish automatically and report the local files plus the public URL(s).
|
|
134
|
+
|
|
135
|
+
- **Multi-platform: repeat per platform.** If publishing to multiple platforms, repeat the validation, dry-run, confirmation, and live publish sequence for each platform sequentially. Report results after each one.
|
|
136
|
+
|
|
137
|
+
## Decision Criteria
|
|
138
|
+
|
|
139
|
+
- **Which skill to use**: Instagram-only content uses `instagram-publisher` (direct API, most control). Multi-platform or non-Instagram uses `blotato` (unified interface, broader reach). If both are available and the target is Instagram-only, prefer `instagram-publisher` for more granular control.
|
|
140
|
+
- **When to convert image formats**: Convert only when the target skill or pipeline truly requires a different format and the user approves the transformation. If the current shared flow already accepts JPG/JPEG and PNG, do not block solely because the slides are PNG.
|
|
141
|
+
- **When to split a caption**: If a caption exceeds the platform limit, present the full caption, highlight where the cut would happen, and ask the user to shorten it. Do not truncate automatically.
|
|
142
|
+
- **When to stop multi-platform publishing**: Stop and ask the user after any platform failure. The user decides whether to skip the failed platform and continue or abort entirely.
|
|
143
|
+
|
|
144
|
+
## Quality Criteria
|
|
145
|
+
|
|
146
|
+
- [ ] User confirmation was received before any live publish (not just dry-run)
|
|
147
|
+
- [ ] Dry-run was executed and passed before live publish
|
|
148
|
+
- [ ] All platform-specific validations passed (image format, dimensions, caption length, image count)
|
|
149
|
+
- [ ] Publish preview was presented with complete details (platform, images, caption, validation status)
|
|
150
|
+
- [ ] Successful publishes include post URL/permalink and post ID
|
|
151
|
+
- [ ] Failed publishes include error details, HTTP status, and suggested fix
|
|
152
|
+
- [ ] Multi-platform publishing was executed sequentially with per-platform reporting
|
|
153
|
+
- [ ] Rate limit status was checked and reported before publishing
|
|
154
|
+
- [ ] No caption was silently truncated or modified without user approval
|
|
155
|
+
- [ ] `run-dashboard.html` and `run-dashboard.data.json` were regenerated after the last selected output
|
|
156
|
+
- [ ] If the squad config enables static publish, the latest and archived `run-dashboard` snapshots were published and reported without a second approval prompt
|
|
157
|
+
|
|
158
|
+
## Output Examples
|
|
159
|
+
|
|
160
|
+
### Example 1: Instagram Carousel Publish Workflow
|
|
161
|
+
|
|
162
|
+
```text
|
|
163
|
+
PUBLISH PREVIEW
|
|
164
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
165
|
+
Platform: Instagram (carousel)
|
|
166
|
+
Account: @brandname
|
|
167
|
+
Skill: instagram-publisher
|
|
168
|
+
Images: 7 slides
|
|
169
|
+
1. slide-01.jpg (1080x1440, JPEG, 287KB)
|
|
170
|
+
2. slide-02.jpg (1080x1440, JPEG, 195KB)
|
|
171
|
+
3. slide-03.jpg (1080x1440, JPEG, 213KB)
|
|
172
|
+
4. slide-04.jpg (1080x1440, JPEG, 178KB)
|
|
173
|
+
5. slide-05.jpg (1080x1440, JPEG, 201KB)
|
|
174
|
+
6. slide-06.jpg (1080x1440, JPEG, 192KB)
|
|
175
|
+
7. slide-07.jpg (1080x1440, JPEG, 244KB)
|
|
176
|
+
|
|
177
|
+
Caption (1,847 / 2,200 chars):
|
|
178
|
+
"You are doing 100 things to grow on Instagram.
|
|
179
|
+
And ignoring the ONE that actually works.
|
|
180
|
+
|
|
181
|
+
Here is what nobody tells you about organic growth:
|
|
182
|
+
[... truncated for preview ...]
|
|
183
|
+
|
|
184
|
+
Comment GUIDE below and I will DM you the full playbook.
|
|
185
|
+
|
|
186
|
+
#instagramgrowth #socialmedia #contentcreator
|
|
187
|
+
#digitalmarketing #organicgrowth"
|
|
188
|
+
|
|
189
|
+
VALIDATION
|
|
190
|
+
Image format: JPEG (required: JPEG)
|
|
191
|
+
Image count: 7 (required: 2-10)
|
|
192
|
+
Image dimensions: 1080x1440 (valid carousel)
|
|
193
|
+
Caption length: 1,847 chars (max: 2,200)
|
|
194
|
+
Hashtags: 5 (recommended: 5-8)
|
|
195
|
+
Rate limit: 3/25 posts used in last 24h
|
|
196
|
+
|
|
197
|
+
Status: All validations passed. Ready for dry-run.
|
|
198
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
199
|
+
|
|
200
|
+
DRY-RUN RESULT
|
|
201
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
202
|
+
Credentials: Valid (token expires 2026-04-15)
|
|
203
|
+
Image upload: 7/7 images uploaded to imgBB
|
|
204
|
+
Media containers: 7/7 containers created
|
|
205
|
+
Carousel container: Created successfully
|
|
206
|
+
Publish: Skipped (dry-run mode)
|
|
207
|
+
|
|
208
|
+
Dry-run passed. Awaiting confirmation to publish live.
|
|
209
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
210
|
+
|
|
211
|
+
PUBLISH RESULT
|
|
212
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
213
|
+
Published successfully
|
|
214
|
+
Platform: Instagram
|
|
215
|
+
Post URL: https://www.instagram.com/p/ABC123xyz/
|
|
216
|
+
Post ID: 17899506834567890
|
|
217
|
+
Published: 2026-02-28 14:32:07 UTC
|
|
218
|
+
Rate limit: 4/25 posts used in last 24h
|
|
219
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Example 2: Multi-platform Publish with Partial Failure
|
|
223
|
+
|
|
224
|
+
```text
|
|
225
|
+
MULTI-PLATFORM PUBLISH
|
|
226
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
227
|
+
Targets: Instagram, LinkedIn, X/Twitter
|
|
228
|
+
Skill: blotato (multi-platform)
|
|
229
|
+
|
|
230
|
+
PLATFORM 1/3: Instagram
|
|
231
|
+
Validation: All checks passed
|
|
232
|
+
Dry-run: Passed
|
|
233
|
+
Publish: Published successfully
|
|
234
|
+
Post URL: https://www.instagram.com/p/DEF456abc/
|
|
235
|
+
Post ID: ig_17899506834567890
|
|
236
|
+
Published: 2026-02-28 14:35:12 UTC
|
|
237
|
+
|
|
238
|
+
PLATFORM 2/3: LinkedIn
|
|
239
|
+
Validation: All checks passed
|
|
240
|
+
Dry-run: Passed
|
|
241
|
+
Publish: FAILED
|
|
242
|
+
Error: 403 Forbidden — "Publishing permission not granted"
|
|
243
|
+
HTTP Status: 403
|
|
244
|
+
Suggested fix: The LinkedIn account may need re-authorization in Blotato.
|
|
245
|
+
1. Go to Blotato Settings > Connected Accounts
|
|
246
|
+
2. Disconnect and reconnect the LinkedIn account
|
|
247
|
+
3. Ensure "Create posts" permission is granted during OAuth
|
|
248
|
+
|
|
249
|
+
LinkedIn publish failed. Continue with remaining platforms?
|
|
250
|
+
|
|
251
|
+
[User confirms: continue]
|
|
252
|
+
|
|
253
|
+
PLATFORM 3/3: X/Twitter
|
|
254
|
+
Validation: Caption exceeds 280 chars (1,847 chars)
|
|
255
|
+
Original caption is too long for X/Twitter.
|
|
256
|
+
Options:
|
|
257
|
+
a) Use the first 277 chars + "..."
|
|
258
|
+
b) Provide a custom short caption for X/Twitter
|
|
259
|
+
c) Skip X/Twitter
|
|
260
|
+
|
|
261
|
+
[User chooses: b, provides short caption]
|
|
262
|
+
|
|
263
|
+
Validation: All checks passed (short caption: 142 chars)
|
|
264
|
+
Dry-run: Passed
|
|
265
|
+
Publish: Published successfully
|
|
266
|
+
Post URL: https://x.com/brandname/status/1234567890123456789
|
|
267
|
+
Post ID: tw_1234567890123456789
|
|
268
|
+
Published: 2026-02-28 14:38:45 UTC
|
|
269
|
+
|
|
270
|
+
SUMMARY
|
|
271
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
272
|
+
Instagram: Published
|
|
273
|
+
LinkedIn: Failed (403 — re-authorize account)
|
|
274
|
+
X/Twitter: Published (with custom short caption)
|
|
275
|
+
|
|
276
|
+
2/3 platforms published successfully.
|
|
277
|
+
Action needed: Re-authorize LinkedIn account in Blotato.
|
|
278
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Anti-Patterns
|
|
282
|
+
|
|
283
|
+
### Never Do
|
|
284
|
+
|
|
285
|
+
1. **Never publish without explicit user confirmation.** Dry-run success is not permission to go live. The user must explicitly confirm every publish. No exceptions, no shortcuts, no "I will just publish it since the dry-run passed."
|
|
286
|
+
|
|
287
|
+
2. **Never silently truncate captions.** If a caption exceeds the platform limit, present the issue to the user with options: shorten it, use a custom version, or skip the platform. Automatic truncation destroys the copy's structure and CTA.
|
|
288
|
+
|
|
289
|
+
3. **Never fire-and-forget across multiple platforms.** Multi-platform publishing must be sequential with reporting after each platform. If one fails, the user decides the next step. Parallel publishing hides failures and removes user control.
|
|
290
|
+
|
|
291
|
+
4. **Never ignore validation failures.** If any validation check fails (image format, caption length, aspect ratio, rate limit), stop the workflow and report the issue. Do not attempt to publish and "see what happens."
|
|
292
|
+
|
|
293
|
+
5. **Never report success without a URL.** "Published successfully" without a post URL is not verifiable. Every successful publish must include the post permalink. If the API does not return a URL, report that as a limitation.
|
|
294
|
+
|
|
295
|
+
6. **Never assume credentials are valid.** Always verify credentials during the dry-run phase. Tokens expire, permissions get revoked, accounts get disconnected. A credential check is part of every publish workflow.
|
|
296
|
+
|
|
297
|
+
7. **Never publish the same raw caption across all platforms without adaptation.** Instagram, LinkedIn, and X/Twitter have different formatting conventions, character limits, and audience expectations. At minimum, verify the caption fits the platform constraints. Ideally, suggest platform-specific adaptations.
|
|
298
|
+
|
|
299
|
+
### Always Do
|
|
300
|
+
|
|
301
|
+
1. **Present a structured preview before every publish.** Show: platform, account, images (with dimensions and format), caption (with character count), hashtags, and validation status. The user must see exactly what will be published.
|
|
302
|
+
|
|
303
|
+
2. **Run a dry-run before every live publish.** Test the full workflow without posting. Verify credentials, upload media, create containers, validate everything. Report dry-run results before requesting confirmation.
|
|
304
|
+
|
|
305
|
+
3. **Report results immediately after each publish.** Do not batch results. After each platform publish (success or failure), report the outcome with all relevant details before moving to the next platform.
|
|
306
|
+
|
|
307
|
+
4. **Warn about rate limits proactively.** Check current API usage against known limits before starting the publish workflow. "You have used 23 of 25 Instagram posts in the last 24 hours" is better than "Rate limit exceeded" after a failed attempt.
|
|
308
|
+
|
|
309
|
+
## Vocabulary Guidance
|
|
310
|
+
|
|
311
|
+
### Use
|
|
312
|
+
|
|
313
|
+
- **"Publish preview"** — Always present a structured preview before any publish action. Use this exact header.
|
|
314
|
+
- **"Dry-run result"** — Report test outcomes with this label. Clear distinction from live publishes.
|
|
315
|
+
- **"Published successfully: [URL]"** — The success message always includes the post URL/permalink.
|
|
316
|
+
- **"Validation passed/failed"** — Binary status for each platform requirement check.
|
|
317
|
+
- **"Awaiting confirmation"** — The explicit state when waiting for user approval to go live.
|
|
318
|
+
- **"Platform requirements"** — Reference specific constraints by platform name and numbers.
|
|
319
|
+
- **"Rate limit: X/Y used"** — Proactive reporting of API usage against limits.
|
|
320
|
+
|
|
321
|
+
### Avoid
|
|
322
|
+
|
|
323
|
+
- **"I will go ahead and publish"** — Never announce publishing without having received explicit confirmation first.
|
|
324
|
+
- **"Published"** without a URL — Every success claim must include a verifiable post link.
|
|
325
|
+
- **"It should work"** or **"probably fine"** — Publishing status is binary: validated or not, succeeded or failed.
|
|
326
|
+
- **"Oops"** or casual language for failures — Publish failures are serious. Report them professionally with error details and next steps.
|
|
327
|
+
- **Em dashes** — Use periods, colons, or line breaks instead.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Squad Creation Checklist
|
|
2
|
+
|
|
3
|
+
Default structural contract for every new squad.
|
|
4
|
+
|
|
5
|
+
Use this checklist to avoid squads that are locally plausible but globally incoherent.
|
|
6
|
+
|
|
7
|
+
## Checklist
|
|
8
|
+
|
|
9
|
+
1. Define each pipeline step as a contract, not just a task.
|
|
10
|
+
Every step must make explicit what it reads, what it writes, how success is judged, and what blocks approval.
|
|
11
|
+
|
|
12
|
+
2. Bound research before deepening.
|
|
13
|
+
Research steps should cap the initial scan, use summaries and snippets to filter, and only open full materials when they are necessary to support the brief.
|
|
14
|
+
|
|
15
|
+
3. Specify the primary deliverable with the right amount of elasticity.
|
|
16
|
+
If the output can vary in size, count, or length, express that as a clear minimum and maximum instead of hiding a fixed assumption inside examples or downstream steps.
|
|
17
|
+
|
|
18
|
+
4. Propagate the same deliverable contract end to end.
|
|
19
|
+
If a squad works with a range such as 2 to 4 slides, the same contract must appear consistently in planning, drafting, visual direction, rendering, preview, publication, examples, and quality criteria.
|
|
20
|
+
|
|
21
|
+
5. Put a human checkpoint before irreversible execution.
|
|
22
|
+
Any step that renders, publishes, sends, posts, or otherwise performs a costly or irreversible action must have an approval checkpoint immediately before it.
|
|
23
|
+
|
|
24
|
+
6. Close with a coherence sweep.
|
|
25
|
+
Before the squad is considered finished, search the canonical files for stale assumptions, superseded counts, and contract mismatches so the delivered squad matches its intended behavior.
|
|
26
|
+
|
|
27
|
+
## Quick Heuristics
|
|
28
|
+
|
|
29
|
+
- Prefer a bounded range over an arbitrary fixed count when the narrative or output size can legitimately vary.
|
|
30
|
+
- Prefer one clear primary deliverable contract over multiple conflicting local assumptions.
|
|
31
|
+
- Prefer cheap filtering before expensive research reads.
|
|
32
|
+
- Prefer one final coherence pass over trusting that earlier edits propagated correctly.
|