Verification and gates
Right before publishing, a post clears two gates in series: the Phase 3 quality verdict and the Phase 4 AI-smell score. Both have to pass before it reaches the Blogger upload. This section covers what each gate looks at, and the security baseline underneath them.
Phase 3 — quality-check’s four axes
Section titled “Phase 3 — quality-check’s four axes”quality-check reads the Korean and English versions together and judges across four axes. The report lands at _workspace/briefs/{slug}-quality.md.
- AdSense policy — low-value content signals, policy-violation risk. It pairs with the separate
adsense-optimizationreview. - SEO — meta tags, schema, hreflang cross-references, keyword density.
- E-E-A-T — experience, expertise, authority, trust signals. Whether first-person experience and source citations are actually present.
- ko/en parity — core message, H2 structure correspondence, data match, hreflang cross-reference, slug match.
If the verdict is FAIL, it stops before publishing. If NEEDS_REVIEW, it fixes the Phase 2 outputs and runs Phase 3 again. It has to be PASS to move to the next gate.
The quality report compares the Korean character count and English word count against the brief’s mode (long 10000–12000 characters, short 5000–7000), and lists the citation count and H2 section count alongside. Because the length standard is defined in one place, the Phase 2 length policy in AI_AUTOMATION.md, the report references that value rather than setting its own.
Phase 4 — ai-pattern-check’s score
Section titled “Phase 4 — ai-pattern-check’s score”ai-pattern-check scans the Korean and English versions under _workspace/posts/new/ and scores them from 0 to 100. The higher the score, the heavier the AI flavor. Most categories are counted automatically with Grep patterns, while spots that need a manual read, like structural uniformity, are looked at separately.
| Verdict | Score | Action |
|---|---|---|
| Pass | Under 30 | Proceed to blog-publish |
| Warn | 30 to 60 | Fix the obvious spots first; proceed only if full automation was requested, and record the reason |
| Fail | Over 60 | Block publishing. Ask production-agent for a rewrite, up to twice. If it still fails, hand back to the user |
The spots the categories catch are things like these. Template phrases (“정리하면,” “핵심은,” “독자 여러분”), enumeration patterns (“첫째/둘째/셋째”), overuse of AI as a subject (“I asked the AI” several times in one post), English boilerplate (“In summary,” “It’s important to”), next-episode teasers at the end, structural uniformity (every H2 the same length, every paragraph three to five lines), decisive connectives (“결국,” “즉,” “다만” clustered), and conclusion-form boilerplate (sentences ending in “~에 있다” repeated). Each hit adds points, and when the sum crosses the threshold a verdict drops. The exact patterns and scores live in the ai-pattern-check skill.
The score thresholds are the same in blog-orchestrator and AI_AUTOMATION.md. Neither side redefines them.
Where the gate is enforced at the code level
Section titled “Where the gate is enforced at the code level”Blocking a failing post isn’t a promise the orchestrator makes; it’s what the script does. scripts/deploy_to_blogger.py re-checks the AI-smell and quality gates right before upload and refuses to upload if it fails. That’s why calling the script directly to bypass the orchestrator still gets blocked. --skip-gate is an exit kept only for republishing or urgent situations.
Security baseline S1–S8
Section titled “Security baseline S1–S8”Eight lines planted in AI_AUTOMATION.md. Each is enforced in a different place.
| Code | Rule | Enforced at |
|---|---|---|
| S1 | Google OAuth credentials.json/token.json and API keys are not git-tracked | .gitignore |
| S2 | No modifying or deleting files outside _workspace/. Infrastructure only after human approval | agent definitions |
| S3 | Back up before overwriting an output. Preserve the prior version on republish | blog-publish |
| S4 | External search (research) only on explicit user request | research |
| S5 | Posts that might trip AdSense policy publish only after passing review | adsense-optimization |
| S6 | Auto-detect real names, phone numbers, real addresses and recommend masking. No automatic masking | quality-check |
| S7 | API keys and OAuth tokens are never planted in plaintext in bodies, logs, or outputs | all agents |
| S8 | A post that fails the AI-smell gate is blocked from Blogger upload | scripts/deploy_to_blogger.py |
S1 and S7 handle credentials, and S5 and S8 are publishing gates. S6 leaves it to a human rather than masking automatically, so whether to publish a post containing a real name is the user’s call.
The next section is publishing. It covers where the Blogger OAuth credentials live, how scripts/deploy.sh splits between staging, dry-run, and the publish command, and where it stops when credentials are missing.