mcp-gee-sweet 0.9.6.dev132__tar.gz → 0.9.6.dev136__tar.gz
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.
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/merge-pr.md +3 -3
- mcp_gee_sweet-0.9.6.dev136/.claude/commands/notify-kai.md +12 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/qa-kickoff.md +3 -1
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/team-roles/amy.md +1 -1
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/team-roles/joy.md +1 -1
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/team-roles/kai.md +1 -1
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/team-roles/rio.md +1 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/CHANGELOG.md +2 -1
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/CLAUDE.md +4 -3
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/PKG-INFO +1 -1
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/role-file-history.md +4 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/markdown-parser.md +2 -2
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/known-limitations.md +29 -23
- mcp_gee_sweet-0.9.6.dev136/docs/qa/fixtures/md/tc-doc246/native-lines.html +4 -0
- mcp_gee_sweet-0.9.6.dev136/docs/qa/fixtures/md/tc-doc246/rules.md +11 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc104-nested-lists.html +19 -1
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc106-nested-lists-4space.md +15 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/docs_content.md +68 -11
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/roadmap.md +4 -4
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/ast.py +5 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/ast_to_markdown.py +65 -25
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/doc_to_ast.py +93 -4
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/emitter.py +87 -6
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/html_parser.py +59 -43
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_content.py +5 -5
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_core.py +218 -63
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_markdown_export.py +57 -0
- mcp_gee_sweet-0.9.6.dev136/tests/test_docs_rule.py +403 -0
- mcp_gee_sweet-0.9.6.dev132/.claude/commands/notify-kai.md +0 -12
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/cleanup-worktrees.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/notify-partner.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/orchestrator.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/prep-for-pr.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/release.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/retro.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/roadmap-status.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/security-advisory.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/start-worktree.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/team-member.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/commands/verify-pr.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/settings.json +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/team-roles/aziz.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/team-roles/bob.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/team-roles/dev.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.claude/team-roles/qa.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.dockerignore +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.gitattributes +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.github/dependabot.yml +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.github/workflows/ci.yml +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.github/workflows/docs.yml +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.github/workflows/mcpb.yml +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.github/workflows/publish.yml +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.gitignore +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.mcpbignore +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.pre-commit-config.yaml +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/.python-version +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/CODE_OF_CONDUCT.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/CONTRIBUTING.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/Dockerfile +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/LICENSE +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/Makefile +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/README.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/SECURITY.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docker-compose.yml +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/assets/logo.png +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/auth.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/client-setup.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/configuration.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-async-tool-execution.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-auth-status-limitation-categories.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-cache-invalidation.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-chart-theming.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-comments-first-class.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-composite-tools.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-condition-type-docstring-generation.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-converted-doc-change-detection.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-dev-team.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-docs-formatting.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-fork.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-gmail-domain.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-grid-data-size-cap.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-http-socket-timeout.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-impact-reach-triage.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-local-fs-test-harness.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-mcp-v2-resource-context-access.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-pillow-image-dependency.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-prompt-qa-role.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-publishing.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-release-docs-roles.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-repositioning.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-response-size-cap-generalization.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-response-size-cap-reevaluation-519.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-review-finding-ticket-bar.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-supports-all-drives-lint-check.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-sync-folder-recursion.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-testing.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/decision-tool-error-visibility.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/index.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/blockquote-representation.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/borderless-table-columns.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/cancelled-write-invalidation.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/doc-replace-backup.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/doc-revision-export.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/doc-to-markdown.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/docs-ast-pipeline.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/effectiveformat-spike.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/gmail-send-confirmation.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/heading-anchor-resolution.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/image-conversion.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/image-share-lifecycle.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/index.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/local-file-access-policy.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/markdown-support.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/mcp-bundle.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/module-history.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/oauth-reauthorize-from-tool-call.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/phase3-theme-system.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design/sse-consent-off-event-loop.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/design.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/index.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/notes-read.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/README.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r01-meeting-notes.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r02-project-plan.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r03-spec-prd.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r04-readme.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r05-status-report.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r06-howto.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r07-comparison.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r08-research-summary.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r09-changelog.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r10-task-plan.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r11-incident-postmortem.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r12-interview-guide.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r13-api-reference.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r14-study-notes.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r15-travel-itinerary.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/realistic/r16-planning-notes.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/state/dropped-links.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/state/theme.json +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/state/www-scheme.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-01-starts-bullets.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-02-starts-numbered.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-03-starts-table.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-04-starts-code.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-05-starts-quote.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-06-starts-image.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-07-starts-rule.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-08-ends-table.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-09-ends-list.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-10-empty.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-11-whitespace-only.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-12-no-trailing-newline.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-13-crlf-line-endings.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-14-front-matter.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-15-rule-then-setext-heading.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/docstart/ds-16-front-matter-lists.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-adjacency-blank.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-adjacency-noblank.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-blockquotes.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-breaks-rules.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-code-blocks.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-containment.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-emphasis.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-escapes.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-headings.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-images.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-inline-code.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-inline-html.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-inline-matrix.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-links.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-lists-blocks.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-lists-boundaries.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-lists-markers.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-lists-nesting.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-long-document.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-tables.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-tasks.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/syntax/md-unicode.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/md/tc-doc245/relative-image.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/qa fixture pixel /303/251.png" +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/qa-fixture-pixel.png +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-d195-create-doc.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-d196-create-doc.html +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-d213-dollar-escape.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-d226-heading-table.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc102-image-conversion.html +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc103-image-conversion.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc105-nested-lists-gfm.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc135-paragraph-boundary.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc136-interrupted-block-boundary.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc137-inline-hr-no-block-ancestor.html +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc138-nbsp-spacer-paragraph.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc141-mismatched-list-tags.html +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc142-heading-anchors.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc144-anchor-in-table-cell.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc145-anchor-on-first-element.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc240-bullet.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc240-heading.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc240-normal.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc240-quote.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc240-seed.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc241-links.html +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc241-links.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc241-write.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc242-loose.html +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures/tc-doc242-loose.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/fixtures.template.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/gmail-test-plan.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/operations.yaml +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/playwright_oauth.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/.gitkeep +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-06-02.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-06-14.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-06-17.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-06-18.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-06-21-drive-discovery.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-06-21-sheets-delete-clear.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-06-28.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-07-04-docs.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-07-04-drive-smoke.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-07-04-infra.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-07-04-sheets_read.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-07-04.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-09-04.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-10-17-pass-audit.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-10-17-spec.txt +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-10-17.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-10-18-markdown-phase2.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-10-18-markdown.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-10-22-markdown-boundaries-state.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-10-25-markdown.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-10-28-markdown-pr1286.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-10-29-markdown-pr1295.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-10-30-markdown-pr1301.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/results/2026-10-30-markdown-pr1303.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/retro-v0.8.0.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/retro-v0.9.0.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/retro-v0.9.2.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/run.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/runs/README.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/runs/v0.8.0.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/runs/v0.8.1.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/runs/v0.9.0.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/runs/v0.9.1.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/runs/v0.9.2.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/runs/v0.9.3.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/setup.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/calendar.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/docs_layout.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/docs_markdown.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/docs_style.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/docs_tables.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/drive_activity.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/drive_files.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/drive_sharing.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/drive_transfer.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/gmail.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/infra.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/sheets_charts.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/sheets_mgmt.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/sheets_read.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/qa/tests/sheets_write.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/style-guide.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/tools.md +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/manifest.json +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/mkdocs.yml +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/pyproject.toml +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/pyrightconfig.json +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/build_mcpb.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/check_supports_all_drives.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/gen_tool_docs.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/kai_status.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/lane_context_hook.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/oauth_setup.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/qa_cancel_inflight_write.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/qa_cancel_insert_local_images.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/qa_compile_results.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/qa_gen_md_fixtures.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/qa_gmail_fixtures.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/qa_launch_mcpb.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/qa_revision_temp_doc_parent.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/setup_team.sh +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/sync_slot_config.sh +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/scripts/write_team_mcp_configs.sh +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/server.json +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/.env.template +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/__init__.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/__main__.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/auth.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/cache.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/http_auth.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/http_transport.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/local_files.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/reauth.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/server.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/sse_shutdown.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/__init__.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/atomic_write.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/cache.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/calendar.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/concurrency.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/__init__.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/anchors.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/batch_retry.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/comments.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/content.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/editing.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/images.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/indices.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/invalidation.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/layout.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/markdown_export.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/md_to_html.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/named_ranges.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/style.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/docs/tables.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/drive/__init__.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/drive/activity.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/drive/files.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/drive/sharing.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/drive/transfer.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/front_matter.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/gmail.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/http_errors.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/mime_types.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/pagination.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/response_limits.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/sheets/__init__.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/sheets/data.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/sheets/helpers.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/src/mcp_gee_sweet/tools/sheets/structure.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/__init__.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/conftest.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/drive/__init__.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/drive/test_activity.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/drive/test_files.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/drive/test_sharing.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/drive/test_transfer.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/drive/test_transfer_front_matter.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/drive/test_transfer_pagination.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/drive/test_transfer_query_escaping.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/fakes.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/integration/__init__.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/integration/conftest.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/integration/test_local_fs_harness.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/sheets/__init__.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/sheets/test_data.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/sheets/test_helpers.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/sheets/test_structure.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_atomic_write.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_auth.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_cache.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_cache_isolation.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_calendar.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_cancelled_write_invalidation.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_check_supports_all_drives.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_concurrency.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_dependency_floors.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_anchors.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_batch_retry.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_comments.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_dropped_links.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_editing.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_images.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_indices.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_layout.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_md_to_html.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_named_ranges.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_relative_link.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_revision_export.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_style.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_docs_tables.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_front_matter.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_gen_tool_docs.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_get_doc_structure_inline_objects.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_gmail.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_gmail_send_confirm.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_http_auth.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_http_errors.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_http_transport.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_kai_status.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_lane_context_hook.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_local_file_sites.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_local_files.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_mcpb_manifest.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_mime_types.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_python_versions.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_qa_gen_md_fixtures.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_qa_gmail_fixtures.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_reauth.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_response_limits.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_server.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_server_json.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_sse_shutdown.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_sync_slot_config.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/tests/test_team_mcp_configs.py +0 -0
- {mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/uv.lock +0 -0
|
@@ -11,8 +11,8 @@ Merge the current branch's PR and clean up its worktree. Uses `--admin` only to
|
|
|
11
11
|
- The PR must not carry the `parked` label (`gh pr view <number> --json labels`), even with every approval label it needs. `parked` means it's still waiting on its blocker (`kai.md` "Parked PRs"). Stop and report what its parking comment says it waits on.
|
|
12
12
|
- If the branch's second `/`-separated segment is one of the four dev-lane slot names (`ash`, `sky`, `jay`, `kit` — the type prefix in front varies, `feat`/`fix`/`chore`/etc., don't assume `feat`), it must carry the `qa-approved` label (check `gh pr view <number> --json labels`). If it doesn't, stop — that means the paired QA agent (`/team-member`) hasn't signed off yet; don't merge and don't review it yourself here. This check deliberately stays scoped to the four dev-lane names — Aziz's branch (`team/aziz`) isn't part of any Dev/QA pairing and goes through normal review instead.
|
|
13
13
|
- **Exception — prompt PRs (checked first, before the QA-slot exception below):** read the file list (`gh pr view <number> --json files`), not the branch prefix. If at least one path is a prompt file (`.claude/team-roles/*.md`, `.claude/commands/*.md`, or root `CLAUDE.md`) and every other path is under `docs/` or is root `CONTRIBUTING.md`, the required label is `prompt-qa-approved` instead of `qa-approved`, and only Bob merges it (`bob.md` step 4). If this session isn't Bob, stop and leave it for Bob. A PR that also touches anything outside `docs/`, root `CONTRIBUTING.md`, and the prompt files (`src/`, `tests/`, `scripts/`, `.github/`, `pyproject.toml`, …) needs `qa-approved`, plus `prompt-qa-approved` for its prompt-file changes. **One carve-out: a code-doc hunk needs only `qa-approved`.** A code-doc hunk is a change to root `CLAUDE.md` that meets all three conditions: (a) it sits inside one of the `## Architecture` section's per-module or per-mechanism entries (a bullet or bold-led paragraph naming a `src/` file, function, or constant), never the section's introductory paragraph; (b) every sentence it adds, removes, or rewords states what code in a `src/` file this PR changes does, or must keep doing, and names that code; (c) it adds, removes, or rewords no instruction about how agents work: reviewing, testing, logging practice, verification, commits/PRs, or where history is recorded. A hunk that fails any part needs `prompt-qa-approved`. QA classifies each hunk in writing (`qa.md` step 3). Don't require `prompt-qa-approved` if the QA `approved` comment lists every `CLAUDE.md` hunk as a `code-doc hunk:` line. A hunk missing from that list, or marked `prompt-qa needed`, still needs it, as does every `.claude/team-roles/*.md` or `.claude/commands/*.md` change. When unsure whether a hunk qualifies, it doesn't (2026-10-13, PR #1016). (Widened 2026-10-12, PR #1005: retros record incidents in `docs/decisions/role-file-history.md` per `bob.md`, so a prompt-files-only allowlist blocked every retro PR, e.g. #1004. Root `CONTRIBUTING.md` added 2026-10-25 on the maintainer's call: it's public documentation, and PR #1253 changed it alongside `kai.md`.) (Added 2026-09-25: PR #804, `doc/jay/claude-md-560`, was a `CLAUDE.md`-only edit, and this check would otherwise have blocked it for lacking `qa-approved`.)
|
|
14
|
-
- **Exception:** a QA-named slot (`sky`/`kit`) authoring its own process/meta PR (e.g. `chore/sky/...`) has no Dev/QA partner to approve it; it's Rio's to review (`rio.md`), and Rio's `qa-approved` is its label. A PR Rio authors itself (`.../rio/...`) has no reviewer: there's no label path for that case, so stop and ask the user directly whether it's safe to merge without one, same as any missing-label PR. If they confirm (e.g. because it's a prompting/process change with no application-code risk), proceed — that confirmation stands in for the label for this PR only, it doesn't waive the check generally.
|
|
15
|
-
- If the branch's second segment is `amy` (`docs/amy/issue-<n>`), it must carry the `docs-qa-approved` label instead — a parallel track, started 2026-08-02 (first case: PR #482), for docs PRs reviewed for product/tone accuracy. As of that date it's applied directly by the user rather than by an automated QA partner (Amy has no dedicated QA pairing the way Ash/Jay do),
|
|
14
|
+
- **Exception:** a QA-named slot (`sky`/`kit`) authoring its own process/meta PR (e.g. `chore/sky/...`) has no Dev/QA partner to approve it; it's Rio's to review (`rio.md`), and Rio's `qa-approved` is its label (`docs-qa-approved` on a docs-only PR as `rio.md` defines it). A PR Rio authors itself (`.../rio/...`) has no reviewer: there's no label path for that case, so stop and ask the user directly whether it's safe to merge without one, same as any missing-label PR. If they confirm (e.g. because it's a prompting/process change with no application-code risk), proceed — that confirmation stands in for the label for this PR only, it doesn't waive the check generally.
|
|
15
|
+
- If the branch's second segment is `amy` (`docs/amy/issue-<n>`), it must carry the `docs-qa-approved` label instead — a parallel track, started 2026-08-02 (first case: PR #482), for docs PRs reviewed for product/tone accuracy. As of that date it's applied directly by the user rather than by an automated QA partner (Amy has no dedicated QA pairing the way Ash/Jay do). Since 2026-10-31 Rio also applies it to any docs-only PR it approves, as `rio.md` defines docs-only. Treat its presence the same as any other approval label — sufficient to merge, no need to re-review — but if it's missing, stop and ask rather than merging or reviewing the PR yourself.
|
|
16
16
|
- **Review-finding ticket check (dev-lane branches: `ash`/`sky`/`jay`/`kit`).** Read the QA comments and the PR body (`gh pr view <number> --json body,comments,createdAt`) and list every issue `gh issue list --state all --search "<number> in:body created:>=<createdAt date>"` returns. Don't filter by label: the check exists for tickets that skipped the rule, and those skip the `from-review` label too. Skip roadmap bundles and other issues that only reference the PR. Every remaining hit filed from this PR's review or by its Dev must appear as `ticket — bar N: <reason> (#<issue>)` in a QA comment's finding list (`qa.md` step 3) or in the PR body's follow-up list (`dev.md` step 6), and carry `from-review`. A bar-2 ticket must name a behavior impact (bar 2's value test); a refactor or dedup reason doesn't fit bar 2. Stop and don't merge if any filed ticket has no `bar N:` reason, if a comment still files findings under a "non-blocking"/"not blocking" heading, or if a `dropped:` reason describes size or priority instead of why the finding is wrong ("outside this diff, no behavior impact" is a valid drop). Tell the user which line, and send the PR back to whoever wrote that list (the QA partner or the Dev) to redo it. If a bar is named but the reason plainly doesn't fit it (e.g. bar 1 for a choice between implementation options), don't decide alone: name it to the user before merging. You check that a fitting reason is given; you don't redo the review. Background: `docs/decisions/decision-review-finding-ticket-bar.md`.
|
|
17
17
|
3. If the PR is authored by `app/dependabot` (branch prefixed `dependabot/`): run the tiered dependency-review check below before summarizing. A single PR can match more than one tier (e.g. a security update that's also a major bump) — apply every tier that matches, not just the first hit. None of these tiers block a merge on their own: this is a sanity check, not a full audit — flag anything that looks off to the user rather than silently blocking, and don't hold up an otherwise-clean bump over it. (Established 2026-08-05 after a run of 7 batched Dependabot PRs exposed that the only check in place was security-only and one-size-fits-all — see `project_v09_roadmap` memory for the full reasoning.)
|
|
18
18
|
|
|
@@ -42,7 +42,7 @@ Merge the current branch's PR and clean up its worktree. Uses `--admin` only to
|
|
|
42
42
|
|
|
43
43
|
This step only ever touches the lane whose PR was just merged — Kai completing its own action, not reaching into another lane's independent state. Detecting a sibling lane that raced the same ticket without ever opening a PR is that lane's own job: `dev.md`'s self-heal checks whether the issue behind its current branch is already closed by someone else's merge, not something Kai sweeps for post-merge (see [[feedback_worktree_self_heal]] for why an external, commit-message-matching sweep was removed — it produced a false positive on every routine QA branch copy).
|
|
44
44
|
7. From the main checkout on `develop`, `git pull` — unconditionally, even if step 8 turns out to be a no-op. `gh pr merge` merges via the API; it never touches the main checkout's local branch, so skipping this leaves Kai's live-testing home base stale until the next unrelated pull happens to catch it up.
|
|
45
|
-
8. Update the roadmap: check `docs/roadmap.md` for a checkbox line referencing the issue(s) this PR closes (search by issue number). If the roadmap has no line item for this issue (not every ticket is roadmap-tracked — chores, follow-up defects, etc.), skip this step silently. If found, check it off (`- [ ]` → `- [x]`) and append `(PR <number>)` in the existing style (e.g. `(PR #280)`) — see recent `- [x]` entries for the exact convention. **The check-off goes on a roadmap PR, never a direct push to `develop`.** Ruleset 26262344 requires CodeQL results for every commit that lands on `develop` or `main`, and a pushed commit has none yet, so GitHub rejects any direct push ("Code scanning is waiting for results from CodeQL", 2026-10-31). Find Kai's open roadmap PR with `gh pr list --state open --json number,headRefName --jq '.[] | select(.headRefName | startswith("docs/kai/roadmap-"))'`. Add the commit (`docs(roadmap): check off #<issue> (PR <number>)`) to it only if Rio hasn't started reviewing it (no Rio review comment, no `qa-approved`); a commit added after that would sit under a label covering a diff Rio never saw. Otherwise start a new one on a `docs/kai/roadmap-<date>` branch off `origin/develop` (with a `-2`, `-3` suffix when that name is taken), in a `.claude/worktrees/kai-roadmap` worktree (absolute path; not a persistent slot, so `cleanup-worktrees` removes it after the PR merges), so the main checkout stays on `develop`. Don't open one PR per check-off. It merges through Rio's review like any other non-lane PR (`kai.md` step 4). Never add a bypass actor to the ruleset to get direct pushes back: a bypass also lets an `--admin` merge past a failing CodeQL check.
|
|
45
|
+
8. Update the roadmap: check `docs/roadmap.md` for a checkbox line referencing the issue(s) this PR closes (search by issue number). If the roadmap has no line item for this issue (not every ticket is roadmap-tracked — chores, follow-up defects, etc.), skip this step silently. If found, check it off (`- [ ]` → `- [x]`) and append `(PR <number>)` in the existing style (e.g. `(PR #280)`) — see recent `- [x]` entries for the exact convention. **The check-off goes on a roadmap PR, never a direct push to `develop`.** Ruleset 26262344 requires CodeQL results for every commit that lands on `develop` or `main`, and a pushed commit has none yet, so GitHub rejects any direct push ("Code scanning is waiting for results from CodeQL", 2026-10-31). Find Kai's open roadmap PR with `gh pr list --state open --json number,headRefName --jq '.[] | select(.headRefName | startswith("docs/kai/roadmap-"))'`. Add the commit (`docs(roadmap): check off #<issue> (PR <number>)`) to it only if Rio hasn't started reviewing it (no Rio review comment, no `docs-qa-approved` or `qa-approved`); a commit added after that would sit under a label covering a diff Rio never saw. Otherwise start a new one on a `docs/kai/roadmap-<date>` branch off `origin/develop` (with a `-2`, `-3` suffix when that name is taken), in a `.claude/worktrees/kai-roadmap` worktree (absolute path; not a persistent slot, so `cleanup-worktrees` removes it after the PR merges), so the main checkout stays on `develop`. Don't open one PR per check-off. It merges through Rio's review like any other non-lane PR (`kai.md` step 4). Never add a bypass actor to the ruleset to get direct pushes back: a bypass also lets an `--admin` merge past a failing CodeQL check.
|
|
46
46
|
9. If step 6 reported a dev-lane slot (`ash`/`sky`/`jay`/`kit`) back to idle, check whether that lane already has its next ticket queued: `gh issue list --state open --label ready-for-development --label lane-a` (or `lane-b` for `jay`/`kit`). If one is already labeled, nothing to do. Otherwise, figure out its next ticket:
|
|
47
47
|
- Check the active roadmap-planning memory (memory index, not a hardcoded filename) for phase order, then cross-reference `docs/roadmap.md`'s current `- [ ]`/`- [x]` state for that lane's queue — the memory can be stale (bugs ship out of the order it recorded, tickets get re-triaged), so the roadmap doc's live checkbox state is the tiebreaker, not the memory.
|
|
48
48
|
- First, check `gh issue list --state open --label solo-only --label ready-for-development`. If that returns anything, stop here — per `kai.md`'s ticket-triage section, no other ticket gets `ready-for-development` while a `solo-only` ticket holds it, regardless of how many lanes are idle. This is not a judgment call to weigh against file overlap; treat any hit as an unconditional hold, and don't attempt the rest of this step until it ships.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Wake Kai directly, if it's already running as a live agent, right after a PR picks up the `qa-approved` label (or Rio's `docs-qa-approved`) — instead of leaving it sitting until the user manually tells Kai to check. Invoked from `qa.md` step 8, immediately after `gh pr edit <number> --add-label qa-approved` (or `docs-qa-approved`) — not run standalone by a user, and never a blocking dependency: when no live Kai session exists, this is a silent no-op and the existing fully-manual flow (Kai's own `/orchestrator`/`/team-member Kai` startup report already surfaces the PR via `gh pr list --state open`, or the user tells Kai to check) is completely unaffected.
|
|
2
|
+
|
|
3
|
+
This is a separate, narrower mechanism from `notify-partner.md` — that one resolves a *pairing* (Ash↔Sky, Jay↔Kit) for Dev/QA handoffs. There's exactly one Kai, so this file has no pairing table to resolve, just a fixed target name.
|
|
4
|
+
|
|
5
|
+
**Scope: `qa-approved`, plus `docs-qa-approved` when Rio applies it.** Rio applies `docs-qa-approved` instead of `qa-approved` to a docs-only PR it approves (`rio.md`), so it fires this then too. When the user applies `docs-qa-approved` directly (Amy's docs-PR track, `amy.md`), no agent session is there to fire it, and a user-driven label change can't call `SendMessage`. Don't extend this to any other approval label without first giving it an agent-side application step.
|
|
6
|
+
|
|
7
|
+
1. `ListAgents`. Look for a row named `Kai`, **case-insensitively** — same reasoning as `notify-partner.md` step 1: a session registers under whatever casing it was actually invoked with.
|
|
8
|
+
- **No matching row:** nothing to do — don't report this as a failure. Continue with the rest of `qa.md` step 8 (report to the user that it's ready for Kai to run `/merge-pr`).
|
|
9
|
+
- **More than one row matches:** there should only ever be one live Kai — it owns the single main checkout, and `kai.md` step 1 refuses to run from anywhere else. Don't guess which row is real; ask the user rather than sending to either.
|
|
10
|
+
- **Exactly one match:** proceed to step 2, addressing it by the row's own literal name as `ListAgents` returned it (not the canonical `Kai` spelling above), the same case-preservation reasoning as `notify-partner.md` step 1's last clause.
|
|
11
|
+
2. `SendMessage({to: "<name>", message: "PR #<n> just got <label>."})`. Keep it to the triggering fact only — Kai re-derives its own next steps (checking the PR, running `/merge-pr`) from its own role file, the same as if the user had just told it to look.
|
|
12
|
+
3. Fire-and-forget, same contract as `notify-partner.md` step 3: don't wait for a reply and don't poll `ListAgents` to check whether Kai picked it up.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Invoked from `.claude/team-roles/qa.md` step 2, after resetting this worktree to the partner Dev's PR branch. Determine which case applies, then send the user **exactly** the block below as your next message — verbatim, no rewording, no splitting across turns — except substitute `<name>` with this role's own lowercase name (e.g. `sky`, `kit`) so the block is directly copy-pasteable, and drop the `/mcp reconnect` line when the "No server-code change" rule below applies:
|
|
1
|
+
Invoked from `.claude/team-roles/qa.md` step 2, after resetting this worktree to the partner Dev's PR branch. Determine which case applies, then send the user **exactly** the block below as your next message — verbatim, no rewording, no splitting across turns — except substitute `<name>` with this role's own lowercase name (e.g. `sky`, `kit`) so the block is directly copy-pasteable, and drop the `/mcp reconnect` line when the "No server-code change" rule below applies, or send nothing when the "Docs-only PR" rule applies:
|
|
2
2
|
|
|
3
3
|
**First QA pass on this PR** (no `/code-review` has run against it yet this cycle):
|
|
4
4
|
|
|
@@ -15,6 +15,8 @@ Invoked from `.claude/team-roles/qa.md` step 2, after resetting this worktree to
|
|
|
15
15
|
|
|
16
16
|
**No server-code change, no reconnect:** if `git diff --name-only origin/develop...HEAD` lists nothing under `src/` and neither `pyproject.toml` nor `uv.lock` (a dependency change alters what the `uv run`-launched server imports), leave the `/mcp reconnect` line out of either block, because the live server never runs the changed code. A re-verification round in that case sends the user nothing and goes straight to the fix commit. PR #866 (a Claude Code hook script) asked for two reconnects that verified nothing.
|
|
17
17
|
|
|
18
|
+
**Docs-only PR, no `/code-review`:** if `git diff --name-only origin/develop...HEAD` lists only paths under `docs/`, send the user nothing on a first pass either. `/code-review` looks for code defects, and a docs-only diff has none to find. This replaces only `/code-review`; `qa.md` step 4's live run of any touched `docs/qa/tests/` case still applies. In its place, read the diff yourself and check every claim it makes against its source: the code at this head for a description of code, and GitHub's live state (`gh issue view`, `gh pr view`) for a roadmap or status line. PR #1318 (a roadmap edit) asked for a `/code-review` that had nothing to review.
|
|
19
|
+
|
|
18
20
|
On a re-verification round, do not ask for `/code-review` again. After the reconnect lands, run `git show <fix-sha>` on the Dev's new commit yourself and live-verify against its own new QA test case (see `.claude/team-roles/qa.md` Retro). Fall back to a full `/code-review` only if the fix's diff is structurally larger than the named finding, or unrelated commits landed in between.
|
|
19
21
|
|
|
20
22
|
Either way, once the reconnect confirmation lands, check it names *this role's own* `mcp-gee-sweet-<name>` server before trusting any live tool result — naming the server explicitly in the command above rules out the old bare-`/mcp reconnect` failure mode where the wrong role's server got reconnected, but the confirmation is still worth a glance. Don't rely on `ToolSearch`'s cached tool description as a substitute freshness check either — it can keep showing the pre-reset docstring even after a correct reconnect. Treat a live tool call's own observed behavior as the only reliable signal a reconnect actually took effect.
|
|
@@ -13,7 +13,7 @@ Amy keeps documentation accurate, friendly, comprehensive, and fun — README, `
|
|
|
13
13
|
6. Remove the `documentation` label once the PR is open.
|
|
14
14
|
- **On any other branch (mid-ticket):** report status rather than claiming new work.
|
|
15
15
|
|
|
16
|
-
Amy has no dedicated MCP server and isn't gated by `qa-approved` (that's the Dev/QA dev-lane pairing's own label) — but as of 2026-08-02 her PRs do need the `docs-qa-approved` label (review for product/tone accuracy) before `/merge-pr` will merge them; currently applied directly by the user rather than an automated QA partner, since Amy has no dedicated QA pairing the way Ash/Jay do.
|
|
16
|
+
Amy has no dedicated MCP server and isn't gated by `qa-approved` (that's the Dev/QA dev-lane pairing's own label) — but as of 2026-08-02 her PRs do need the `docs-qa-approved` label (review for product/tone accuracy) before `/merge-pr` will merge them; currently applied directly by the user rather than an automated QA partner, since Amy has no dedicated QA pairing the way Ash/Jay do. Rio applies it instead when the user hands Rio the PR (`rio.md`).
|
|
17
17
|
|
|
18
18
|
## Retro
|
|
19
19
|
|
|
@@ -7,7 +7,7 @@ Joy doesn't work a ticket queue like Ash/Jay, and she isn't release-cadence like
|
|
|
7
7
|
3. **Do the work**, scoped to what was asked:
|
|
8
8
|
- A written recommendation or design doc goes in `docs/decisions/` (why) or `docs/design/` (how) per the ADR convention (see `project_docs_structure` memory / `CLAUDE.md`'s docs-structure notes).
|
|
9
9
|
- A scoped code or doc change: `git fetch origin develop && git checkout -b <type>/joy/issue-<n> origin/develop` inside `.claude/worktrees/joy` — never the main checkout, never `team/joy` itself (that branch is the persistent slot, not a place to accumulate commits). Use `doc/joy/...` or `feat/joy/...` per the type of change, matching the prefix conventions Amy/Ash/Jay already use.
|
|
10
|
-
- Doc-only change:
|
|
10
|
+
- Doc-only change: Rio reviews it and applies `docs-qa-approved` (`rio.md`).
|
|
11
11
|
- Code change: goes through the same review/QA path as any other PR — Rio (`rio.md`) or the normal `/merge-pr` review, nothing skipped just because the change originated from an architecture review.
|
|
12
12
|
- **One QA reviewer per code PR.** Rio reviews it, covering both code review and live QA. Kai routes it (`kai.md` step 4). Don't also ask Aziz or another role for a code read. A second code review duplicates the first and adds a round (PR #1016 had both Aziz and Kit). The exception is a review the user asks for themselves.
|
|
13
13
|
- **Before pushing a fix round, answer every open review comment on the PR**, from every reviewer, in one push. This is `dev.md`'s rule of the same name, and it applies here unchanged.
|
|
@@ -21,7 +21,7 @@ The incidents behind the rules in this file are in [`docs/decisions/role-file-hi
|
|
|
21
21
|
- Community intake on outside-contributor PRs and issues: labels only, per "Community intake" below.
|
|
22
22
|
- Roadmap grooming (`docs/roadmap.md` + whichever roadmap-planning memory is currently active — check the memory index rather than assuming a specific version-numbered file)
|
|
23
23
|
- Live/manual tool testing — only possible here (or in a QA agent's own worktree, once it's checked out a branch — see `/team-member`)
|
|
24
|
-
- Merging PRs that carry the `qa-approved` label (`merge-pr`) — do not merge one that's missing
|
|
24
|
+
- Merging PRs that carry the `qa-approved` label, or Rio's `docs-qa-approved` on a docs-only PR (`rio.md`) (`merge-pr`) — do not merge one that's missing both, and do not perform the review/QA yourself; send it back to the relevant QA agent instead. Aziz's release-QA sign-off PR (`qa/vX.Y.Z-release-pass`) has no QA partner to label it: it merges only on a user go-ahead that names that PR or merging it (a request to cut the release isn't one). Record it by applying `qa-approved` and commenting on the PR with the user's words quoted. Ask for that go-ahead in your state report; don't wait for a label nobody is assigned to add (v0.9.2, PR #1051).
|
|
25
25
|
- Routing every non-lane PR to Rio (`rio.md` "Which PRs are Rio's": any team PR not from `ash`/`jay`, docs and code alike, except a prompt PR only Bob merges). Sky and Kit take only their partner Dev's PRs. Rio needs a go-ahead per PR. Once the user has directed a hand-off, message Rio naming the PR and saying the user directed it, which `rio.md` accepts. Otherwise ask the user to tell Rio. Don't route it to a second reviewer as well (PR #1016 had both Aziz and Kit). If no Rio session is running, ask the user to start one (`make team-rio`) rather than falling back to Sky or Kit. When the author pushes a fix to a PR Rio sent back, message Rio that it's a re-verification round, unless the author already did.
|
|
26
26
|
- Team-process PRs (edits to `CLAUDE.md`, `.claude/team-roles/*.md`, `.claude/commands/*.md`) are Bob's own merge track, not Kai's — Bob reviews, labels `prompt-qa-approved`, and merges those himself (see `.claude/team-roles/bob.md` step 4). This used to be Kai's job too; per direct user instruction, 2026-07-21, it isn't anymore. A code-doc hunk (`merge-pr.md` step 2) is the exception: it rides with its code PR, needs only `qa-approved`, and Kai merges it.
|
|
27
27
|
- Cutting a release once Aziz has signed off (`/release`)
|
|
@@ -30,6 +30,7 @@ Once there's a go-ahead, follow `qa.md` from step 1 under "One found" through st
|
|
|
30
30
|
- `<Name>` in the verdict line as `Rio`.
|
|
31
31
|
- `/notify-partner` in step 7 as: if the author's session is listed by `ListAgents`, send it the verdict line and comment URL with `SendMessage`. Either way, tell the user and Kai that it went back to the author.
|
|
32
32
|
- `/qa-kickoff`'s `<name>` as `rio`.
|
|
33
|
+
- `qa-approved` in step 8 as `docs-qa-approved` when every path in `gh pr view <number> --json files` is under `docs/` and none is under `docs/qa/` (user instruction, 2026-10-31); this is what "docs-only" means for the label. `docs-qa-approved` means each claim in the diff was checked against its source, the code at this head or GitHub's live state, with no live run. `qa-approved` on a `docs/qa/` PR means every touched test case was run live and its Result recorded (`qa.md` steps 4–5), the same as on a code PR. `/notify-kai` fires for either. In step 1, remove whichever of the two labels the PR carries, whatever its head changes now.
|
|
33
34
|
|
|
34
35
|
`qa.md`'s "One PR per session" rule binds Rio, including its QA-docs exception. Rio has no partner Dev, so the exception reads: once this session has reset to any PR's branch, it never resets to a non-QA-docs head of a different PR; that needs `/clear`.
|
|
35
36
|
|
|
@@ -27,7 +27,7 @@ All notable changes to this project are documented in this file.
|
|
|
27
27
|
- Bold inside italic (`*a **b** c*`) keeps both styles. `#hashtag` and `####### seven` stay paragraphs instead of becoming headings.
|
|
28
28
|
- A link or image whose path contains spaces (``, `[notes](./My Notes.md "Notes")`) still works, as it did before, although CommonMark itself would leave it as text.
|
|
29
29
|
- Two quotes separated by a blank line render as two quotes.
|
|
30
|
-
- A line of only `-` is an empty list item instead of a setext heading underline or literal text.
|
|
30
|
+
- A line of only `-` is an empty list item (an empty bullet, #1075, under Bug fixes) instead of a setext heading underline or literal text. Right under a paragraph's text it's still a heading underline, as in CommonMark and on GitHub: put a blank line before it to get an empty item.
|
|
31
31
|
- YAML front matter (`---` … `---` at the top) now renders as a rule and then a Heading 2 of its text, where it used to render as a rule, a paragraph and a rule. It's still shown either way (#1173).
|
|
32
32
|
- A list with a blank line between items, or with a paragraph or code block indented under an item, stays one list with every bullet and number, where Python-Markdown dropped some of those items out of the list (#1111, fixed by #1164). The numbering continues past a block inside a numbered item too (#1094, under Bug fixes).
|
|
33
33
|
- A line of `---` (or `===`) right under a list item's text makes that text a heading inside the item, as CommonMark reads a setext underline: `- a` then ` ---` is a bulleted Heading 2 "a" (#1094), not an item followed by a rule. Write the rule as `***` to keep the item and the rule.
|
|
@@ -35,6 +35,7 @@ All notable changes to this project are documented in this file.
|
|
|
35
35
|
|
|
36
36
|
### Bug fixes
|
|
37
37
|
|
|
38
|
+
- A list item with no text (a line of only `-` or `2.`, or an `<li></li>`) is an empty bullet instead of being dropped, so the list keeps every item and a numbered list every number. A list nested under an empty item is one level deeper, as is a code block, quote or horizontal rule that is the item's only content (a rule there used to be dropped). **Behavior change for HTML input:** an `<li>` that holds only whitespace or ` `, or that wraps only a nested list (`<li><ul>…</ul></li>`), is now an empty bullet with the nested list one level under it, where it used to produce nothing. Applies to `create_doc`, `write_doc_content`, `create_doc_from_file`, `update_doc_from_file` and `upload_file`'s Markdown Doc — #1075
|
|
38
39
|
- A numbered list keeps its numbering after a bulleted list nested in one of its items (`1. A`, ` - a`, `2. B` shows 2, not 1), at every level; a sublist nested in one of the other type used to split the outer list into separate lists. A sublist that follows another sublist of a different type under the same item starts its own numbering. Applies to `create_doc`, `write_doc_content`, `create_doc_from_file` and `update_doc_from_file` — #1072
|
|
39
40
|
- Two lists of the same type written one after the other, with a different marker (`-` then `*`, or `1.` then `1)`), render as two lists instead of one: the second numbered list starts again at 1, at the top level and as a second sublist under one item (`1. P`, ` 1. a`, ` 1) b` shows b as a., not b.). A numbered sublist that follows a deeper numbered list (`1. A`, ` - b`, ` 1. c`, ` 1. d`) no longer joins it. Applies to `create_doc`, `write_doc_content`, `create_doc_from_file`, `update_doc_from_file` and `upload_file`'s Markdown Doc — #1241
|
|
40
41
|
- A block inside a list item (a second paragraph, a code block, a quote, a heading, a table, a rule or an image indented under the item) stays inside it: it's indented to the item's text, with no bullet of its own, and the list continues past it, so `1. Clone:`, a code block, `2. Install.` shows 2, not 1. A quote inside an item is indented one step past the item's text, with its border. An item whose text is a heading (`- # Title`) is a bulleted heading instead of an unlisted heading. **Behavior change for HTML input:** text after a nested list, quote, code block, paragraph or rule inside an `<li>` is a paragraph indented under that item, where it used to become a new bullet (or the next number) of its own. Applies to `create_doc`, `write_doc_content`, `create_doc_from_file`, `update_doc_from_file` and `upload_file`'s Markdown Doc. `get_doc_as_markdown` still exports such a block at the margin and a bulleted heading as a plain item (#1302) — #1094
|
|
@@ -76,17 +76,17 @@ Each entry below says what a module owns and the invariants a future edit could
|
|
|
76
76
|
- `docs/layout.py` — tools (`create_header`, `create_footer`)
|
|
77
77
|
- `docs/comments.py` — tools (`list_doc_comments`, `add_doc_comment`, `resolve_doc_comment`) via the Drive `comments`/`replies` resource, not the Docs API
|
|
78
78
|
- `docs/named_ranges.py` — helper (`_create_named_range`) and tools (`create_named_range`, `create_bookmark`), extracted out of `content.py` (#371) since they're fully self-contained. The Docs API has no bookmark-creation endpoint — `create_bookmark` is a thin wrapper over `createNamedRange` spanning a single character; neither tool's output is a link target (only UI-created bookmarks/headings are).
|
|
79
|
-
- `docs/doc_to_ast.py` / `docs/ast_to_markdown.py` / `docs/markdown_export.py` — the read side (`get_doc_as_markdown`, opt-in `include_comments` for non-resolved comments via the Drive `comments` resource). It walks `documents().get()` into the same AST the write side uses and serializes that to Markdown, instead of cleaning up Google's styled HTML export (`docs/design/doc-to-markdown.md`). A paragraph is a fenced code block only when *every* run is code-styled (Courier New), so a paragraph holding only one inline code span renders as a block (documented in `docs/known-limitations.md`). Exception (#951): a fence can't hold a link, so a code paragraph with a linked run renders as linked inline code spans instead. A linked run that is only line breaks doesn't count, and neither does a linked image. Every image renders through `_render_image`, which keeps its link, and one inside a code paragraph renders outside the fence (`_render_code_block`). Links come from `_link_url`, shared by text runs and images, which rebuilds a heading or bookmark link (reported by ID, with no `url`) as a same-document URL. Empty-runs paragraphs in table cells are kept as spacers, and `_render_cell` converts `"\n"` to `<br>` *before* stripping. Emphasis markers go inside surrounding whitespace (CommonMark flanking). `_text_run_to_run` turns every `"\v"` (soft break) into `"\n"`, and a plain run's `"\n"` renders as `<br>` with edge breaks outside its link (#1057); `get_doc_structure`/`find_in_doc` still decode only Courier New runs (`decode_code_run_text`). A nested table renders a placeholder note. An ordered item renders its ordinal from `BulletItem.number`, which `document_to_ast` counts per `listId` and nesting level over body paragraphs, never per contiguous run, since a table or paragraph between two items doesn't restart a Docs list (#1208). `startNumber` 0 means 1 only for lettered and Roman levels. A sublist whose first number isn't 1 writes `1.` for that item, since CommonMark won't let it interrupt the parent's text. A block inside a list item (#1302, the inverse of #1094) is found by indent in `doc_to_ast._ListItemContext`: a non-bullet paragraph after an item with `indentStart == indentFirstLine` at that item's level's text indent (or a shallower level's), plus 36pt per quote level, gets that level as `list_depth`, with its quote depth counted from the text indent, not the margin. It tracks the `listId` open at each depth, since a sublist of the other type has its own (#1072). A table (no indent in the API) and a quote whose indent also reads as a deeper margin quote wait: they're inside an item only when the list goes on after them (an item of a list open at that depth, a sublist nested under the last item, or a plainly in-item block), else outside as read. `ast_to_markdown._OpenItems` indents such a block to its item's content column (`_item_prefix`'s width), never a fixed width, with the item's quote levels outside the indent whatever depth the block reads with. A bulleted `HEADING_N` paragraph that isn't a checkbox item is a `BulletItem` with `heading_level`, rendered `- # Title`; every other item's text goes through `_escape_leading_block_marker`. [History](docs/design/module-history.md#toolsdocsdoc_to_astpy--docsast_to_markdownpy--docsmarkdown_exportpy).
|
|
79
|
+
- `docs/doc_to_ast.py` / `docs/ast_to_markdown.py` / `docs/markdown_export.py` — the read side (`get_doc_as_markdown`, opt-in `include_comments` for non-resolved comments via the Drive `comments` resource). It walks `documents().get()` into the same AST the write side uses and serializes that to Markdown, instead of cleaning up Google's styled HTML export (`docs/design/doc-to-markdown.md`). A paragraph is a fenced code block only when *every* run is code-styled (Courier New), so a paragraph holding only one inline code span renders as a block (documented in `docs/known-limitations.md`). Exception (#951): a fence can't hold a link, so a code paragraph with a linked run renders as linked inline code spans instead. A linked run that is only line breaks doesn't count, and neither does a linked image. Every image renders through `_render_image`, which keeps its link, and one inside a code paragraph renders outside the fence (`_render_code_block`). Links come from `_link_url`, shared by text runs and images, which rebuilds a heading or bookmark link (reported by ID, with no `url`) as a same-document URL. Empty-runs paragraphs in table cells are kept as spacers, and `_render_cell` converts `"\n"` to `<br>` *before* stripping. Emphasis markers go inside surrounding whitespace (CommonMark flanking). Two adjacent quoted blocks are one Docs quote (one bar; separate quotes have the emitter's unquoted separator between them), so `_OpenItems.separator` makes the blank line between two nodes carry the quote levels both write at the margin (a block in a quoted list's item writes its item's), or the export reads as two quotes. An empty list item and its first block are joined by a newline, not a blank line: CommonMark ends an item that starts with a blank line (`_starts_empty_item`). `_text_run_to_run` turns every `"\v"` (soft break) into `"\n"`, and a plain run's `"\n"` renders as `<br>` with edge breaks outside its link (#1057); `get_doc_structure`/`find_in_doc` still decode only Courier New runs (`decode_code_run_text`). A nested table renders a placeholder note. An ordered item renders its ordinal from `BulletItem.number`, which `document_to_ast` counts per `listId` and nesting level over body paragraphs, never per contiguous run, since a table or paragraph between two items doesn't restart a Docs list (#1208). `startNumber` 0 means 1 only for lettered and Roman levels. A sublist whose first number isn't 1 writes `1.` for that item, since CommonMark won't let it interrupt the parent's text. A block inside a list item (#1302, the inverse of #1094) is found by indent in `doc_to_ast._ListItemContext`: a non-bullet paragraph after an item with `indentStart == indentFirstLine` at that item's level's text indent (or a shallower level's), plus 36pt per quote level, gets that level as `list_depth`, with its quote depth counted from the text indent, not the margin. It tracks the `listId` open at each depth, since a sublist of the other type has its own (#1072). A table (no indent in the API) and a quote whose indent also reads as a deeper margin quote wait: they're inside an item only when the list goes on after them (an item of a list open at that depth, a sublist nested under the last item, or a plainly in-item block), else outside as read. `ast_to_markdown._OpenItems` indents such a block to its item's content column (`_item_prefix`'s width), never a fixed width, with the item's quote levels outside the indent whatever depth the block reads with. A bulleted `HEADING_N` paragraph that isn't a checkbox item is a `BulletItem` with `heading_level`, rendered `- # Title`; every other item's text goes through `_escape_leading_block_marker`. [History](docs/design/module-history.md#toolsdocsdoc_to_astpy--docsast_to_markdownpy--docsmarkdown_exportpy).
|
|
80
80
|
- `docs/ast.py` — dataclass schema
|
|
81
81
|
- `docs/html_parser.py` — HTML→AST. [History](docs/design/module-history.md#toolsdocshtml_parserpy). Invariants:
|
|
82
82
|
- Bare top-level text gets an implicit paragraph. `_tag_depth` counts open non-block tags, excluding `_VOID_TAGS` (stdlib `HTMLParser` never closes a void tag written without a slash), so text inside only an inline tag stays a no-op. `_finalize()` flushes the block still open at end of input.
|
|
83
|
-
- `_emit_block_node(preserve_if_empty)`: a block's own first close keeps an empty node (`runs=[]`) as a paragraph boundary; a resumed frame's re-close (`_block_resumed`) still drops an empty result. A fresh `<p>` (only `<p>`, not `<li>` or headings, and not resumed) keeps whitespace-only runs, since ` ` lines are deliberate spacers. A bare `<hr>` appends an empty `Paragraph
|
|
83
|
+
- `_emit_block_node(preserve_if_empty)`: a block's own first close keeps an empty node (`runs=[]`) as a paragraph boundary; a resumed frame's re-close (`_block_resumed`) still drops an empty result. A fresh `<p>` (only `<p>`, not `<li>` or headings, and not resumed) keeps whitespace-only runs, since ` ` lines are deliberate spacers. A fresh `<li>` always emits its `BulletItem`, with `runs=[]` when it has no text (#1075): a Markdown bare `-`, `<li> </li>`, and an `<li>` wrapping only a nested list or block are empty bullets, as a browser shows their markers. A bare `<hr>` appends a rule, an empty `Paragraph` with `rule=True` (#1096). `<pre>` builds its node directly and applies the same fresh-vs-resumed rule itself, keeping a fresh `<pre>`'s whitespace.
|
|
84
84
|
- Any `</ol>` or `</ul>` pops `_list_ordered` by count, whatever type opened it, and must run *before* `_resume_interrupted_block`. List frames match by `list_depth`, not tag: the frame is popped once its depth is reached, but the outer block is resumed only on an exact tag match.
|
|
85
85
|
- `_resume_interrupted_block` flushes whatever block is open, unconditionally, before anything else.
|
|
86
86
|
- Every leaf-node construction (`Heading`, `Paragraph`, `BulletItem`, `NamedBlock`) must pass `**self._blockquote_fields()`, which sets `blockquote_depth` and `blockquote_path` from the open-`<blockquote>` id stack (`docs/design/blockquote-representation.md`). Without the path, two adjacent quotes are indistinguishable (#1098). A top-level `Table` gets `blockquote_depth` only, at `</table>`, for its indent (#1097). `_make_bullet_item` clamps depth to `>= 0` for an orphan `<li>`.
|
|
87
87
|
- A block inside a list item (#1094) is that block's own node with `list_depth`/`list_path` naming the item, from `_list_item_fields`, which every non-item leaf construction (and a top-level `Table`, at `</table>`) must pass. The item is the one whose later segment is open, else the innermost `<li>` frame on `_block_stack` whose list ids are exactly the ones open now (each `_BlockFrame` records the interrupted block's `_block_lists`), so a block loose in a list nested in the item isn't the item's. "Open now" is the open block's own `_block_lists`, not the live `_list_ids`, since a block left open until its list's `</ul>` is flushed after the pop (PR #1301 QA round 1). The walk skips a non-matching `<li>` frame instead of stopping at it: an unclosed item in a nested list leaves its frame behind after the `</ul>` (PR #1301 QA round 2). Match by ids, never by depth: a stale frame from a closed list has the depth of a later list (PR #1301 QA round 3). A resumed `<li>` segment (text after a nested list, quote, code block, paragraph or rule) is therefore a `Paragraph` inside the item, never a new `BulletItem`. A heading that opens an `<li>` (`- # Title`) is the item's own text: `BulletItem.heading_level`, the item emitted at the heading's close and its later segment resumed. Its tag stays on `_li_heading_tags` until that `</hN>`, so the end tag is consumed even when a nested block interrupted the item first; never let it reach the inline end-tag path, which would decrement `_tag_depth` for a start tag that never incremented it.
|
|
88
88
|
- In a table cell, a whitespace run holding a line break is dropped at a segment's start (the cell's start, or just after a nested table). At the end of the text so far it's held as runs with their own style and link (`_cell_held_runs`), and written only if content follows in the same segment, which ends at a nested `<table>` or `</td>` (#1073). Nothing inside a cell's `<pre>` is trimmed (`_cell_pre_depth`). Everything else in a cell parses as it did before; collapsing every source line break merged a cell's `<p>`s and `<pre>` lines (PR #1215 QA round 2), and whether a newline in cell text should collapse is #1221 (`docs/design/image-conversion.md`).
|
|
89
|
-
- `_interrupt_open_block` drops trailing whitespace holding a line break from the outgoing segment's unflushed source text: markdown-it writes `<li>a\n<ul>` for every nested block, and the `\n` would become an empty paragraph (#1116). A `<br>` goes into the run buffer as `_LineBreak`, never a bare `"\n"`, so that trim leaves it. A resumed segment likewise drops the line break at its start (`handle_data`), keeping an authored ` `. Neither trim runs in `<pre>` (`_in_pre`), where the break and indentation are the code's. An `<hr>` in
|
|
89
|
+
- `_interrupt_open_block` drops trailing whitespace holding a line break from the outgoing segment's unflushed source text: markdown-it writes `<li>a\n<ul>` for every nested block, and the `\n` would become an empty paragraph (#1116). A `<br>` goes into the run buffer as `_LineBreak`, never a bare `"\n"`, so that trim leaves it. A resumed segment likewise drops the line break at its start (`handle_data`), keeping an authored ` `. Neither trim runs in `<pre>` (`_in_pre`), where the break and indentation are the code's. An `<hr>` in any open block, outside `<pre>` and inline tags, interrupts and resumes it: after text, in a resumed segment, in a fresh `<li>` (an empty bullet, #1075), and in a fresh block with no text, whose empty first segment emits nothing, so `<p><hr></p>` is the rule alone (#1096).
|
|
90
90
|
- Known gap: a resumed block's genuine trailing ` ` is dropped (#444).
|
|
91
91
|
- `docs/emitter.py` — AST→Docs API requests, plus the multi-phase table fill (nested tables, cell styling). [History](docs/design/module-history.md#toolsdocsemitterpy). Invariants:
|
|
92
92
|
- Bullet depth is encoded as leading `"\t"` on each paragraph's text, and `createParagraphBullets` computes levels only within one call. So each top-level list gets exactly one call over its whole range, nested lists of either type included; one call per paragraph creates separate lists and breaks numbering. `_bullet_lists` (#1072) returns each top-level list with the lists nested in it that aren't merged into it: every list of the other type, and a same-type list that follows another sublist under the same item (which restarts). A top-level list's range spans every item nested in it, a trailing nested list's too, or that list's tabs go unconsumed. Each of those is then taken back out, parent before child (`_top_list_requests`: delete its bullets, zero its indent, re-insert its tabs, anchor-wrap it with its own preset), so the outer list keeps counting past it. A `createParagraphBullets` range containing an already-listed paragraph joins the unlisted ones to that paragraph's list (confirmed live), so the outer call can't come last. A range whose preceding paragraph is in a same-preset list joins that list too (confirmed live, #1241), so a nested list's anchor wrap puts a barrier paragraph before its anchor (`barrier=True`). Each `BulletItem` carries `list_path`, the ids of its enclosing `<ul>`/`<ol>` lists (`html_parser._push_list`), captured when its block segment opens (`_block_lists`), since an unclosed `<li>` is flushed after `</ul>` pops. An open list that doesn't enclose an item is closed first (`_encloses`), and a shallower item rejoins the block's first list only from a list enclosing it (`_rejoins_root`), so two adjacent same-type lists stay two Docs lists at any depth; an item without ids groups by depth and type alone. A nested list re-inserts and re-consumes its own tabs, so each item's tabs are consumed once, net.
|
|
@@ -96,6 +96,7 @@ Each entry below says what a module owns and the invariants a future edit could
|
|
|
96
96
|
- `insertTable` gives the table its indent, which no API field can reset afterward, and every empty cell its text style, from the paragraph at the insertion point. So each table gets a placeholder paragraph in the phase-1 text, reset to plain after the bullet pass by `_table_placeholder_requests` (a table between two same-preset list items sits inside their one bullet range; a quoted table keeps its quote's indent via `Table.blockquote_depth`, which `_quoted` still ignores). The table is inserted there, and the placeholder, pushed past the table, is deleted by the `deleteContentRange` right after the `insertTable` (`_inserted_table_length`). Never insert a table at the start of the next block's text: it takes that block's indent and first-character style (#1097). `_positional_insert_tail_start` keeps that delete in the positional tail by its place after an `insertTable`.
|
|
97
97
|
- `_strip_bullet_leading_tabs` removes a literal leading tab from a bullet's own text (it would read as depth) and returns new `Run`/`Image` objects; it must never mutate caller-owned AST nodes. Dropping an authored leading tab is a deliberate, documented loss.
|
|
98
98
|
- Blockquote nodes get a gray `borderLeft` and `indentStart` = `indentFirstLine` = 36pt × depth (`indentFirstLine` is absolute, not relative to `indentStart`). `createParagraphBullets` overwrites both indents, so a quoted `BulletItem`'s request runs after the whole bullet pass and before the table/image inserts, at the list level's own indents (`list_level_indents`, level capped at 8 as Docs caps `nestingLevel`) plus the quote's. Every position used after the bullet pass maps through `_after_bullet_pass`. `doc_to_ast.py` subtracts the level's indent when inferring depth.
|
|
99
|
+
- A rule (`Paragraph.rule`, #1096) is an empty 6pt paragraph with a gray `borderBottom`, since the API can't insert a `horizontalRule`. It also sets `borderBetween`: Docs joins adjacent paragraphs with the same borders and draws `borderBottom` only under the last, so two rules in a row drew one line (confirmed live). A quoted rule gets no `spaceBelow` and a 4pt line instead: a paragraph's spacing isn't covered by the quote bar when its neighbours' borders differ, so any gap split one quote into two on screen (PR #1326 QA round 1). `_rule_requests` must come before a quote's edge spacing for the same range, and a rule inside a list item is drawn after the bullet pass (`deferred`), like its indent. The read side recognizes the stand-in by its whole signature (`is_rule_style`: bottom and matching between-border, no top or right), never a bottom border alone, which an empty line in a bordered box also has; `_build_blank_para_before_table_collapses` uses the same test to skip a rule before a table. `doc_to_ast` splits a paragraph at each native `horizontalRule` (`_split_at_horizontal_rules`; Drive's import puts one in the same paragraph as text, a list item's included), keeping the text's own type and putting a line after a list item's text inside that item. `ast_to_markdown` writes a rule `---`, or `***` as the first line, where `---` opens front matter.
|
|
99
100
|
- A code-styled paragraph's internal `"\n"` breaks become `"\v"` (`_is_code_paragraph`) so a fenced block stays one Docs paragraph; `doc_to_ast.py` reverses it.
|
|
100
101
|
- Table-cell images (#1073) go in during `fill_tables`, not phase 1, from the URIs in `CellImages`. `fill_tables` requires one, and every cell-fill `batchUpdate` goes through `CellImages.execute`. `_run_group_fill_requests` writes a cell's text and styles as if no image were there, then each image (through `CellImages.insert_requests`) at the offset of the text before it, latest first. `execute` replaces an unfetchable image with its fallback text and resends through `batch_retry.send_dropping_failed_images`, the loop the body's retry also uses, and splits a batch only at a failed image, never elsewhere: an earlier cell's text moves every later position. Its request bookkeeping holds the request dicts and is cleared after each batch, so an `id()` key can't outlive its request. `_text_offset_since_last_table` counts what each image took (`CellImages.doc_length`): one index embedded, its fallback text's UTF-16 length when a never-resolved or dropped image was written as text (#1099). `CellImages.embedded` grows as each batch lands, and `_apply_doc_content` gives every resolved cell image missing from it an `error` after the fill and on any `Exception` out of the edit, phase 1 included, but not on a cancellation, whose last batch can still land (`docs/design/image-conversion.md`).
|
|
101
102
|
- Docs joins the left borders of adjacent paragraphs with the same border and indents into one bar, whatever their spacing. So `_with_quote_separators` puts an unbordered empty paragraph, collapsed by `_collapse_paragraph_requests`, between two adjacent quoted nodes whose `blockquote_path`s aren't one a prefix of the other (#1098). `_block_spacing` gives a code block 8pt above and below, and a quote 8pt where it meets content outside it. A separator is spaced on one side only (below the quote before it), and a `Heading` or TITLE/SUBTITLE `NamedBlock` gets no quote-edge space, since an explicit value replaces its named style's own. `_spacing_requests` puts `spaceAbove` on a node's first Docs paragraph and `spaceBelow` on its last, since a node with a `"\n"` in its text spans several. A quoted `BulletItem`'s spacing is emitted after the bullet pass, like its quote styling. `_build_blank_para_before_table_collapses` resets every empty paragraph before a table to plain, a backstop since the table placeholder (above). It deletes the bullet first, because `deleteParagraphBullets` adds indent, then clears indents and border. It leaves the paragraph between two tables at full height, so they don't touch.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: mcp-gee-sweet
|
|
3
|
-
Version: 0.9.6.
|
|
3
|
+
Version: 0.9.6.dev136
|
|
4
4
|
Summary: MCP server for Google Workspace — Sheets, Drive, Docs (HTML or Markdown), Calendar, and Gmail.
|
|
5
5
|
Project-URL: Homepage, https://github.com/khuisman/mcp-gee-sweet
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/khuisman/mcp-gee-sweet/issues
|
{mcp_gee_sweet-0.9.6.dev132 → mcp_gee_sweet-0.9.6.dev136}/docs/decisions/role-file-history.md
RENAMED
|
@@ -308,6 +308,10 @@ On 2026-10-28, four docs-only QA PRs (#1270, #1271, #1274, #1276, none of them a
|
|
|
308
308
|
|
|
309
309
|
Until 2026-10-28, `kai.md` sent each non-lane PR (Aziz's, Amy's, Joy's, Kai's) to whichever of Sky or Kit had no partner PR in review. That day four non-lane `docs/qa/` PRs (#1270, #1271, #1274, #1276) queued behind Sky's lane-A PR (#1272) and Kit's lane-B PR (#1283). Kit reviewed #1270 and sent it back, which bound its session to #1270 under the one-PR rule. When Jay opened #1283, Kit had to `/clear`, so #1270's re-verification had to move to another session. Every hand-off also needed the user to type a go-ahead in a QA window, since `qa.md` accepts no peer's go-ahead for a non-partner PR. The team opened PRs faster than it merged them. The maintainer asked for a QA persona that owns every non-lane PR, so Sky and Kit stay on their partners. Rio takes Kai's hand-off as the go-ahead when it names the PR and says the user directed it, the same rule as `amy.md`'s.
|
|
310
310
|
|
|
311
|
+
### Docs-only PRs: `docs-qa-approved`, no `/code-review` (2026-10-31)
|
|
312
|
+
|
|
313
|
+
Rio's first pass on PR #1318, a roadmap-only edit of Kai's, ran `/qa-kickoff` as written: it asked the user to run `/code-review`, and the user asked why a docs change needed one. Rio instead checked each roadmap line against the issues' and PRs' live GitHub state, approved, and applied the usual `qa-approved`. The user corrected that to `docs-qa-approved`. Two rules came out of it: `qa-kickoff.md` skips `/code-review` when every changed path is under `docs/` and has QA check the diff's claims against their sources instead, and `rio.md` applies `docs-qa-approved` to such a PR, with `merge-pr.md`, `notify-kai.md`, `kai.md`, `joy.md`, and `amy.md` updated to match. In Bob's review (PR #1320) the maintainer decided that a `docs/qa/` PR keeps `qa-approved`: its cases are run live, the way code is verified, while `docs-qa-approved` vouches only for claims checked against their sources. The `/code-review` skip still covers all of `docs/`. Bob also caught that step 1 has to remove whichever label is on the PR, since a later push can change whether the head is docs-only.
|
|
314
|
+
|
|
311
315
|
## `aziz.md`
|
|
312
316
|
|
|
313
317
|
### Server slots during a release pass
|
|
@@ -147,7 +147,7 @@ Inventory of where markdown-it's HTML differs from Python-Markdown's, and what h
|
|
|
147
147
|
| Shape | Python-Markdown | markdown-it | Handling |
|
|
148
148
|
|---|---|---|---|
|
|
149
149
|
| Tight item with a nested block | `<li>a<ul>` | `<li>a\n<ul>` (also before `<pre>`, `<table>`, `<blockquote>`) | **Changed:** `_interrupt_open_block` drops trailing whitespace holding a line break from the raw text before the block. It was reaching the Docs API as an empty paragraph under every parent item. A `<br>`'s own break is kept. |
|
|
150
|
-
| Rule inside an item | (never produced) | `<li>item\n<hr />\n</li>` | **Changed:** an `<hr>` after text in an open block, or in a resumed segment (after a nested list or quote in the item), ends that segment, emits the rule's empty paragraph, and resumes the block. `<li><hr>` with no text
|
|
150
|
+
| Rule inside an item | (never produced) | `<li>item\n<hr />\n</li>` | **Changed:** an `<hr>` after text in an open block, or in a resumed segment (after a nested list or quote in the item), ends that segment, emits the rule's empty paragraph, and resumes the block. `<li><hr>` with no text is an empty bullet with the rule inside the item (#1075). |
|
|
151
151
|
| Text after a block in an item | (never produced) | `<hr />\nmore</li>` | **Changed:** a resumed segment drops the line break at its start, as the break before a block is dropped. An authored ` ` there isn't ASCII whitespace and stays (#444). |
|
|
152
152
|
| Loose item | `<li>\n<p>a</p>\n</li>` | same | Unchanged here: handled by community PR #1164 (#1111), merged into `develop` before this PR. markdown-it produces it more often, since it attaches an indented paragraph or code block to the item instead of dropping it out of the list. |
|
|
153
153
|
| Strikethrough | (none) | `<s>` | Already handled (`_INLINE_STRIKE`). |
|
|
@@ -155,7 +155,7 @@ Inventory of where markdown-it's HTML differs from Python-Markdown's, and what h
|
|
|
155
155
|
| Code block language | `class="language-x"` | same | Unchanged. |
|
|
156
156
|
| Hard break | `<br />\n` | same | Unchanged; the double break it produces is #1117. Now reachable from a trailing `\` too. |
|
|
157
157
|
| Two quotes | one `<blockquote>`, two `<p>` | two `<blockquote>` | Renders as two quotes (#1098's emitter work). |
|
|
158
|
-
| Empty item | (not produced) | `<li></li>` |
|
|
158
|
+
| Empty item | (not produced) | `<li></li>` | An empty bullet (#1075). |
|
|
159
159
|
| Output | no trailing newline | ends in `\n` | Harmless; one exact-match test updated. |
|
|
160
160
|
|
|
161
161
|
## Behavior changes for existing callers
|
|
@@ -56,25 +56,6 @@ cell.
|
|
|
56
56
|
|
|
57
57
|
---
|
|
58
58
|
|
|
59
|
-
### An empty list item (a bare `-` line) is dropped
|
|
60
|
-
|
|
61
|
-
**What:** In Markdown input, a list item with no text, a line of only `-`, leaves no bullet in the
|
|
62
|
-
Doc. The items around it keep theirs, and a list nested under it keeps its level:
|
|
63
|
-
`"- item one\n-\n- item three\n"` renders two bullets, not three.
|
|
64
|
-
|
|
65
|
-
**Why:** The Markdown parser reads it as an empty item (`<li></li>`), as CommonMark says. The
|
|
66
|
-
HTML→AST step then drops a list item with no content, the rule that keeps a stray
|
|
67
|
-
`<li> </li>` or an `<li>` wrapping only a nested list from becoming an empty bullet. Before
|
|
68
|
-
the switch to a CommonMark parser (#1116), Python-Markdown didn't recognize a bare `-` at all:
|
|
69
|
-
it turned the list into a paragraph of literal text, or read the `-` as a setext heading
|
|
70
|
-
underline (#692).
|
|
71
|
-
|
|
72
|
-
**Workaround:** None in Markdown: an item holding only a non-breaking space (`- ` followed by
|
|
73
|
-
U+00A0) is dropped by the same rule. Give the item some text. Tracked in #1075. Related:
|
|
74
|
-
`docs/qa/tests/docs_markdown.md` TC-MD301.
|
|
75
|
-
|
|
76
|
-
---
|
|
77
|
-
|
|
78
59
|
### Markdown input doesn't read footnotes, definition lists, or other Python-Markdown `extra` syntax
|
|
79
60
|
|
|
80
61
|
**What:** Markdown passed to `create_doc`/`write_doc_content` (`content_format='markdown'`),
|
|
@@ -110,15 +91,19 @@ needs Markdown inside it as HTML instead.
|
|
|
110
91
|
**What:** A table inside a list's last item (`1. a\n\n | x |\n |---|\n`) is written to the
|
|
111
92
|
Doc indented under the item, but `get_doc_as_markdown` exports it at the margin, after the list.
|
|
112
93
|
A quote that ends a list's last item (`- a\n\n > q\n`) exports as a deeper quote at the margin
|
|
113
|
-
(`> > q`).
|
|
114
|
-
list
|
|
115
|
-
|
|
94
|
+
(`> > q`). So does a paragraph, code block, heading, or rule inside the last item of a *quoted*
|
|
95
|
+
list (`> - a\n>\n> b\n` exports `b` as `> > b`). Any of these exports inside its item when the
|
|
96
|
+
list goes on after it: a later item of the list, a sublist nested under the item (of either
|
|
97
|
+
type), or a paragraph indented in the item. A paragraph, code block, or heading inside an item of
|
|
98
|
+
an unquoted list always exports inside it.
|
|
116
99
|
|
|
117
100
|
**Why:** The export finds a block inside an item from its indent (#1302). A table's indent isn't
|
|
118
101
|
reported anywhere in the Docs API: the JSON of a table inside an item matches one at the margin
|
|
119
102
|
(checked live). A quote's is, but a quote inside an item sits exactly where a deeper quote at the
|
|
120
103
|
margin would (a quote in a top-level item is at 72pt, like a margin `> >`), so the indent can't
|
|
121
|
-
tell them apart.
|
|
104
|
+
tell them apart. A block inside a quoted list's item is written the same way, at the item's text
|
|
105
|
+
indent plus the quote's and with the quote's border, which is exactly where a deeper quote at the
|
|
106
|
+
margin goes. Such a block counts as inside an item only when the list goes on after it, which
|
|
122
107
|
it never does after a list's last item. Reading an ambiguous quote as the margin quote keeps every
|
|
123
108
|
quote level; reading it into the item would drop one.
|
|
124
109
|
|
|
@@ -153,6 +138,27 @@ lines join into one paragraph. Decided in #1242.
|
|
|
153
138
|
|
|
154
139
|
---
|
|
155
140
|
|
|
141
|
+
### A horizontal rule is a bordered paragraph, not a Docs horizontal line
|
|
142
|
+
|
|
143
|
+
**What:** A Markdown thematic break (`---`, `***`, `___`) or an HTML `<hr>` written by `create_doc`,
|
|
144
|
+
`write_doc_content`, `create_doc_from_file`, `update_doc_from_file`, or `upload_file` (Markdown
|
|
145
|
+
source) appears as a thin gray line, but in Docs it's an empty paragraph with a bottom border
|
|
146
|
+
(6pt, or 4pt inside a quote), not the element Insert > Horizontal line adds, so editing it in Docs
|
|
147
|
+
behaves like editing a paragraph. Inside a quote the line sits closer to the text below it than
|
|
148
|
+
to the text above: space below it would break the quote bar. `get_doc_as_markdown` reads both
|
|
149
|
+
kinds of line back as `---` (`***` when it's the document's first line, where `---` would open
|
|
150
|
+
front matter). A native line that shares a list item's paragraph but comes before its text
|
|
151
|
+
exports at the margin, ending the list there. An `<hr>` inside a table cell is dropped: a cell
|
|
152
|
+
holds no paragraph styling the converter writes (#1327).
|
|
153
|
+
|
|
154
|
+
**Why:** The Docs API has no request that inserts a horizontal line (#1096).
|
|
155
|
+
|
|
156
|
+
**Workaround:** For a native line, use Insert > Horizontal line in the Docs UI, or convert the
|
|
157
|
+
file with `upload_local_file(convert=True)`, whose Drive import draws native lines (with the other
|
|
158
|
+
differences listed under Google Drive below).
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
156
162
|
### `create_bookmark` doesn't create a bookmark Docs lists
|
|
157
163
|
|
|
158
164
|
**What:** `create_bookmark` creates a one-character named range. It doesn't appear under
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
<li>Top ordered 2</li>
|
|
42
42
|
</ol>
|
|
43
43
|
|
|
44
|
-
<h2>Case 4: two levels of empty parent li
|
|
44
|
+
<h2>Case 4: two levels of empty parent li</h2>
|
|
45
45
|
<ul>
|
|
46
46
|
<li>
|
|
47
47
|
<ul>
|
|
@@ -54,3 +54,21 @@
|
|
|
54
54
|
</ul>
|
|
55
55
|
</li>
|
|
56
56
|
</ul>
|
|
57
|
+
|
|
58
|
+
<h2>Case 5: nested list with no parent item, isolated min_depth=1 run</h2>
|
|
59
|
+
<ul>
|
|
60
|
+
<ul>
|
|
61
|
+
<li>Parentless child E1</li>
|
|
62
|
+
<li>Parentless child E2</li>
|
|
63
|
+
</ul>
|
|
64
|
+
</ul>
|
|
65
|
+
|
|
66
|
+
<h2>Case 6: two levels of nested list with no parent item, isolated min_depth=2 run</h2>
|
|
67
|
+
<ul>
|
|
68
|
+
<ul>
|
|
69
|
+
<ul>
|
|
70
|
+
<li>Parentless child F2a</li>
|
|
71
|
+
<li>Parentless child F2b</li>
|
|
72
|
+
</ul>
|
|
73
|
+
</ul>
|
|
74
|
+
</ul>
|
|
@@ -22,3 +22,18 @@
|
|
|
22
22
|
1. Nested ordered 1.1
|
|
23
23
|
2. Nested ordered 1.2
|
|
24
24
|
2. Top ordered 2
|
|
25
|
+
|
|
26
|
+
## Case 4: empty items between items
|
|
27
|
+
|
|
28
|
+
- Bullet before
|
|
29
|
+
-
|
|
30
|
+
- Bullet after
|
|
31
|
+
|
|
32
|
+
1. Number one
|
|
33
|
+
2.
|
|
34
|
+
3. Number three
|
|
35
|
+
|
|
36
|
+
- Rule item before
|
|
37
|
+
-
|
|
38
|
+
---
|
|
39
|
+
- Rule item after
|