freeharness 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE +108 -0
- package/README.md +134 -0
- package/canonical/HARVEST.yaml +858 -0
- package/canonical/PROVENANCE.yaml +740 -0
- package/canonical/agents/README.md +95 -0
- package/canonical/agents/agentic-architect.md +18 -0
- package/canonical/agents/database-reviewer.md +41 -0
- package/canonical/agents/explorer-ai-engineer-analyst.md +65 -0
- package/canonical/agents/pr-reviewer.md +96 -0
- package/canonical/agents/python-reviewer.md +55 -0
- package/canonical/agents/report-formatter.md +19 -0
- package/canonical/agents/security-reviewer.md +53 -0
- package/canonical/agents/test-writer.md +34 -0
- package/canonical/commands/fh-context.md +37 -0
- package/canonical/evals/promptfoo.redteam.yaml +108 -0
- package/canonical/hooks/cost-prices.json +14 -0
- package/canonical/hooks/freeharness-auto-memory.mjs +158 -0
- package/canonical/hooks/freeharness-config-guard.mjs +162 -0
- package/canonical/hooks/freeharness-context-monitor.mjs +198 -0
- package/canonical/hooks/freeharness-converge.mjs +227 -0
- package/canonical/hooks/freeharness-cost-tracker.mjs +1027 -0
- package/canonical/hooks/freeharness-memory-guard.mjs +57 -0
- package/canonical/hooks/freeharness-output-pruner.mjs +333 -0
- package/canonical/hooks/freeharness-precompact.mjs +323 -0
- package/canonical/hooks/freeharness-repeat-tool.mjs +208 -0
- package/canonical/hooks/freeharness-security-guidance.mjs +164 -0
- package/canonical/hooks/freeharness-session-start +583 -0
- package/canonical/hooks/hooks.auto-memory.claude-code.json +16 -0
- package/canonical/hooks/hooks.claude-code.json +17 -0
- package/canonical/hooks/hooks.config-guard.claude-code.json +16 -0
- package/canonical/hooks/hooks.context-monitor.claude-code.json +15 -0
- package/canonical/hooks/hooks.converge.claude-code.json +15 -0
- package/canonical/hooks/hooks.cost-tracker.claude-code.json +37 -0
- package/canonical/hooks/hooks.memory-guard.claude-code.json +16 -0
- package/canonical/hooks/hooks.output-pruner.claude-code.json +16 -0
- package/canonical/hooks/hooks.precompact.claude-code.json +15 -0
- package/canonical/hooks/hooks.repeat-tool.claude-code.json +25 -0
- package/canonical/hooks/hooks.security-guidance.claude-code.json +16 -0
- package/canonical/mcp/servers.json +20 -0
- package/canonical/openspec/config.base.yaml +89 -0
- package/canonical/openspec/schema.spec-driven.yaml +277 -0
- package/canonical/openspec/templates/data-contract.md +36 -0
- package/canonical/openspec/templates/design.md +84 -0
- package/canonical/openspec/templates/eval-plan.md +33 -0
- package/canonical/openspec/templates/follow-ups.md +2 -0
- package/canonical/openspec/templates/proposal.md +45 -0
- package/canonical/openspec/templates/spec.md +42 -0
- package/canonical/openspec/templates/tasks.md +38 -0
- package/canonical/profiles/local-llamacpp.LOCAL-MODELS.md +47 -0
- package/canonical/profiles/local-llamacpp.json +27 -0
- package/canonical/profiles/local-ollama.json +20 -0
- package/canonical/profiles/mcp.json +91 -0
- package/canonical/rules/CLAUDE.md +78 -0
- package/canonical/rules/project-CLAUDE.template.md +62 -0
- package/canonical/rules/routing.md +20 -0
- package/canonical/rules/safety.md +41 -0
- package/canonical/settings/settings.cache-hygiene.claude-code.json +5 -0
- package/canonical/skills/agent-evaluation/SKILL.md +102 -0
- package/canonical/skills/agent-evaluation/assets/evaluation_report_template.md +206 -0
- package/canonical/skills/agent-evaluation/evals/cases.yaml +106 -0
- package/canonical/skills/agent-evaluation/references/dataset-preparation.md +351 -0
- package/canonical/skills/agent-evaluation/references/scorers-constraints.md +165 -0
- package/canonical/skills/agent-evaluation/references/scorers.md +431 -0
- package/canonical/skills/agent-evaluation/references/setup-guide.md +252 -0
- package/canonical/skills/agent-evaluation/references/tracing-integration.md +164 -0
- package/canonical/skills/agent-evaluation/references/troubleshooting.md +514 -0
- package/canonical/skills/agent-evaluation/scripts/analyze_results.py +462 -0
- package/canonical/skills/agent-evaluation/scripts/create_dataset_template.py +382 -0
- package/canonical/skills/agent-evaluation/scripts/list_datasets.py +273 -0
- package/canonical/skills/agent-evaluation/scripts/run_evaluation_template.py +309 -0
- package/canonical/skills/agent-evaluation/scripts/setup_mlflow.py +353 -0
- package/canonical/skills/agent-evaluation/scripts/utils/__init__.py +27 -0
- package/canonical/skills/agent-evaluation/scripts/utils/env_validation.py +123 -0
- package/canonical/skills/agent-evaluation/scripts/utils/tracing_utils.py +108 -0
- package/canonical/skills/agent-evaluation/scripts/validate_agent_tracing.py +148 -0
- package/canonical/skills/agent-evaluation/scripts/validate_auth.py +240 -0
- package/canonical/skills/agent-evaluation/scripts/validate_environment.py +185 -0
- package/canonical/skills/agent-evaluation/scripts/validate_tracing_runtime.py +318 -0
- package/canonical/skills/agentic-architecture/SKILL.md +41 -0
- package/canonical/skills/agentic-architecture/evals/cases.yaml +94 -0
- package/canonical/skills/agentic-architecture/reference/context-engineering.md +75 -0
- package/canonical/skills/agentic-architecture/reference/patterns.md +76 -0
- package/canonical/skills/agentic-architecture/reference/reliability-observability.md +94 -0
- package/canonical/skills/agentic-architecture/reference/review-framework.md +59 -0
- package/canonical/skills/code-review/SKILL.md +52 -0
- package/canonical/skills/code-review/evals/cases.yaml +197 -0
- package/canonical/skills/git-workflow/SKILL.md +41 -0
- package/canonical/skills/git-workflow/evals/cases.yaml +92 -0
- package/canonical/skills/local-code/SKILL.md +24 -0
- package/canonical/skills/local-code/evals/cases.yaml +85 -0
- package/canonical/skills/local-code/scripts/query_llama.py +68 -0
- package/canonical/skills/report-formatting/SKILL.md +62 -0
- package/canonical/skills/report-formatting/evals/cases.yaml +83 -0
- package/canonical/skills/report-formatting/reference/ARCHITECTURE.md +135 -0
- package/canonical/skills/report-formatting/reference/HELPERS.md +120 -0
- package/canonical/skills/report-formatting/reference/PPTX.md +136 -0
- package/canonical/skills/report-formatting/reference/RELEASE.md +99 -0
- package/canonical/skills/report-formatting/reference/TEMPLATES.md +48 -0
- package/canonical/skills/report-formatting/reference/authoring.md +66 -0
- package/canonical/skills/report-formatting/scripts/architecture-template.md +271 -0
- package/canonical/skills/report-formatting/scripts/assets/claro-logo.png +0 -0
- package/canonical/skills/report-formatting/scripts/assets/claro-wordmark.svg +1 -0
- package/canonical/skills/report-formatting/scripts/build-architecture.js +57 -0
- package/canonical/skills/report-formatting/scripts/build-md-claro.js +224 -0
- package/canonical/skills/report-formatting/scripts/build-release.js +51 -0
- package/canonical/skills/report-formatting/scripts/check-env.js +58 -0
- package/canonical/skills/report-formatting/scripts/docmodel.js +283 -0
- package/canonical/skills/report-formatting/scripts/example-build.js +119 -0
- package/canonical/skills/report-formatting/scripts/example_build_ArchitectureReview_docx.js +195 -0
- package/canonical/skills/report-formatting/scripts/example_build_ExecutiveReport_docx.js +114 -0
- package/canonical/skills/report-formatting/scripts/package.json +17 -0
- package/canonical/skills/report-formatting/scripts/pptx/example_build_StatusReport_pptx.py +223 -0
- package/canonical/skills/report-formatting/scripts/pptx/example_build_WeeklyStatus_pptx.py +245 -0
- package/canonical/skills/report-formatting/scripts/pptx/pptx_office.py +144 -0
- package/canonical/skills/report-formatting/scripts/pptx/requirements.txt +7 -0
- package/canonical/skills/report-formatting/scripts/pptx/status_report_blocks.py +193 -0
- package/canonical/skills/report-formatting/scripts/pptx/theme_claro_pptx.py +473 -0
- package/canonical/skills/report-formatting/scripts/release-template.md +80 -0
- package/canonical/skills/report-formatting/scripts/render-mermaid.js +105 -0
- package/canonical/skills/report-formatting/scripts/theme-claro.js +403 -0
- package/canonical/skills/subagent-driven-development/SKILL.md +60 -0
- package/canonical/skills/subagent-driven-development/evals/cases.yaml +208 -0
- package/canonical/skills/subagent-driven-development/reference/brief.md +91 -0
- package/canonical/skills/subagent-driven-development/reference/handoff.md +118 -0
- package/canonical/skills/subagent-driven-development/scripts/validate-handoff.mjs +850 -0
- package/canonical/skills/systematic-debugging/SKILL.md +44 -0
- package/canonical/skills/systematic-debugging/evals/cases.yaml +90 -0
- package/canonical/skills/test-driven-development/SKILL.md +42 -0
- package/canonical/skills/test-driven-development/evals/cases.yaml +86 -0
- package/canonical/skills/test-driven-development/reference/writing-good-tests.md +52 -0
- package/canonical/skills/verification-before-completion/SKILL.md +53 -0
- package/canonical/skills/verification-before-completion/evals/cases.yaml +107 -0
- package/dist/adapters/content/language-lint.d.ts +46 -0
- package/dist/adapters/content/language-lint.js +191 -0
- package/dist/adapters/harness/claude-code.d.ts +57 -0
- package/dist/adapters/harness/claude-code.js +385 -0
- package/dist/adapters/harness/index.d.ts +3 -0
- package/dist/adapters/harness/index.js +17 -0
- package/dist/adapters/harness/opencode.d.ts +7 -0
- package/dist/adapters/harness/opencode.js +166 -0
- package/dist/adapters/harness/plugin.d.ts +22 -0
- package/dist/adapters/harness/plugin.js +257 -0
- package/dist/adapters/memory/doctor.d.ts +480 -0
- package/dist/adapters/memory/doctor.js +1217 -0
- package/dist/adapters/memory/vendored.d.ts +150 -0
- package/dist/adapters/memory/vendored.js +487 -0
- package/dist/adapters/package/node.d.ts +9 -0
- package/dist/adapters/package/node.js +20 -0
- package/dist/adapters/prompt/readline.d.ts +19 -0
- package/dist/adapters/prompt/readline.js +53 -0
- package/dist/adapters/sync/diff.d.ts +43 -0
- package/dist/adapters/sync/diff.js +380 -0
- package/dist/cli/cleanup.d.ts +86 -0
- package/dist/cli/cleanup.js +382 -0
- package/dist/cli/cost.d.ts +304 -0
- package/dist/cli/cost.js +501 -0
- package/dist/cli/doctor.d.ts +205 -0
- package/dist/cli/doctor.js +654 -0
- package/dist/cli/executor.d.ts +5 -0
- package/dist/cli/executor.js +48 -0
- package/dist/cli/plugin-validate.d.ts +37 -0
- package/dist/cli/plugin-validate.js +256 -0
- package/dist/cli/prefix.d.ts +68 -0
- package/dist/cli/prefix.js +218 -0
- package/dist/cli/profile.d.ts +170 -0
- package/dist/cli/profile.js +285 -0
- package/dist/cli/runner.d.ts +10 -0
- package/dist/cli/runner.js +27 -0
- package/dist/cli/uninstall.d.ts +65 -0
- package/dist/cli/uninstall.js +147 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +989 -0
- package/dist/infra/dogfood.d.ts +31 -0
- package/dist/infra/dogfood.js +51 -0
- package/dist/infra/fsutil.d.ts +40 -0
- package/dist/infra/fsutil.js +143 -0
- package/dist/infra/manifest.d.ts +76 -0
- package/dist/infra/manifest.js +92 -0
- package/dist/infra/paths.d.ts +19 -0
- package/dist/infra/paths.js +74 -0
- package/dist/infra/routing.d.ts +4 -0
- package/dist/infra/routing.js +7 -0
- package/node_modules/@freeharness/core/dist/context.d.ts +30 -0
- package/node_modules/@freeharness/core/dist/context.js +1 -0
- package/node_modules/@freeharness/core/dist/index.d.ts +5 -0
- package/node_modules/@freeharness/core/dist/index.js +6 -0
- package/node_modules/@freeharness/core/dist/planner.d.ts +13 -0
- package/node_modules/@freeharness/core/dist/planner.js +18 -0
- package/node_modules/@freeharness/core/dist/ports.d.ts +90 -0
- package/node_modules/@freeharness/core/dist/ports.js +1 -0
- package/node_modules/@freeharness/core/dist/registry.d.ts +41 -0
- package/node_modules/@freeharness/core/dist/registry.js +124 -0
- package/node_modules/@freeharness/core/dist/tiers.d.ts +30 -0
- package/node_modules/@freeharness/core/dist/tiers.js +99 -0
- package/node_modules/@freeharness/core/package.json +34 -0
- package/node_modules/@freeharness/sdd/PROVENANCE.yaml +175 -0
- package/node_modules/@freeharness/sdd/dist/src/bin/openspec.d.ts +2 -0
- package/node_modules/@freeharness/sdd/dist/src/bin/openspec.js +166 -0
- package/node_modules/@freeharness/sdd/dist/src/index.d.ts +14 -0
- package/node_modules/@freeharness/sdd/dist/src/index.js +11 -0
- package/node_modules/@freeharness/sdd/dist/src/init.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/src/init.js +190 -0
- package/node_modules/@freeharness/sdd/dist/src/root-resolver.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/src/root-resolver.js +32 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/archive.d.ts +81 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/archive.js +483 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/context.d.ts +4 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/context.js +48 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.d.ts +57 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.js +279 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/instructions.d.ts +67 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/instructions.js +460 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/list.d.ts +5 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/list.js +95 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/new-change.d.ts +6 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/new-change.js +150 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/schemas.d.ts +4 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/schemas.js +23 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/shared.d.ts +56 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/shared.js +140 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/status.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/status.js +85 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/validate.d.ts +6 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/validate.js +229 -0
- package/node_modules/@freeharness/sdd/dist/src/validate-change.d.ts +40 -0
- package/node_modules/@freeharness/sdd/dist/src/validate-change.js +114 -0
- package/node_modules/@freeharness/sdd/dist/src/validate.d.ts +24 -0
- package/node_modules/@freeharness/sdd/dist/src/validate.js +72 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.d.ts +130 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.js +981 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.d.ts +46 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.js +128 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.d.ts +26 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.js +32 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.d.ts +50 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.js +394 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.d.ts +15 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.js +49 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.d.ts +71 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.js +164 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.d.ts +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.js +21 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.d.ts +102 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.js +230 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.d.ts +18 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.js +138 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.d.ts +82 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.js +333 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.js +110 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.d.ts +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.js +32 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.d.ts +33 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.js +149 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.js +49 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.js +31 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.d.ts +10 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.js +10 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.js +26 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.d.ts +28 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.js +41 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.d.ts +23 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.js +25 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.d.ts +72 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.js +76 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.js +53 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.d.ts +62 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.js +7 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.d.ts +35 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.js +47 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.d.ts +33 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.js +55 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.d.ts +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.js +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.d.ts +48 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.js +99 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.d.ts +19 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.js +18 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.d.ts +18 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.js +4 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.d.ts +19 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.js +207 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.js +409 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.js +673 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.js +230 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.js +550 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.js +107 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.js +228 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.js +147 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.js +571 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.js +322 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.d.ts +7 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.js +7 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.js +518 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.js +176 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.js +344 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.js +54 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.d.ts +35 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.js +171 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.d.ts +27 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.js +210 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.d.ts +14 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.js +48 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.d.ts +22 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.js +186 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.d.ts +65 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.js +409 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.d.ts +55 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.js +98 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.js +77 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.d.ts +44 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.js +116 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.js +17 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.d.ts +72 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.js +30 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.d.ts +3 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.js +3 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.d.ts +17 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.js +14 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.js +114 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.d.ts +45 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.js +105 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.d.ts +15 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.js +56 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.d.ts +17 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.js +1 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.d.ts +94 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.js +756 -0
- package/node_modules/@freeharness/sdd/package.json +57 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/LICENSE.upstream +22 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/schema.upstream.yaml +232 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/README.md +19 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-apply-change/SKILL.md +187 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-archive-change/SKILL.md +181 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-bulk-archive-change/SKILL.md +338 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-continue-change/SKILL.md +117 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-explore/SKILL.md +342 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-ff-change/SKILL.md +116 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-new-change/SKILL.md +76 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-onboard/SKILL.md +560 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-propose/SKILL.md +162 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-sync-specs/SKILL.md +261 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-update-change/SKILL.md +90 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-verify-change/SKILL.md +174 -0
- package/package.json +70 -0
- package/provenance/canonical.PROVENANCE.yaml +740 -0
- package/provenance/claude-mem.LICENSE.upstream +202 -0
- package/provenance/memory.PROVENANCE.yaml +399 -0
- package/provenance/sdd.PROVENANCE.yaml +175 -0
- package/vendor-licenses/caveman.LICENSE +27 -0
- package/vendor-licenses/deepseek-harness.LICENSE +21 -0
- package/vendor-licenses/ecc.LICENSE +21 -0
- package/vendor-licenses/pi.LICENSE +21 -0
- package/vendor-licenses/superpowers.LICENSE +21 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Self-contained pptx office ops for report-formatting (no Anthropic container
|
|
3
|
+
dependency). A .pptx is an OOXML zip; this provides unpack/pack/clean/render.
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
python pptx_office.py unpack <in.pptx> <dir>
|
|
7
|
+
python pptx_office.py pack <dir> <out.pptx>
|
|
8
|
+
python pptx_office.py clean <dir>
|
|
9
|
+
python pptx_office.py render <in.pptx> [outdir] # needs soffice + pdftoppm
|
|
10
|
+
"""
|
|
11
|
+
import os
|
|
12
|
+
import re
|
|
13
|
+
import sys
|
|
14
|
+
import shutil
|
|
15
|
+
import zipfile
|
|
16
|
+
import subprocess
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def unpack(pptx, out_dir):
|
|
20
|
+
"""Extract a .pptx (OOXML zip) into out_dir, replacing it if it exists.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
pptx: Path to the source .pptx file.
|
|
24
|
+
out_dir: Directory to extract into; removed first if present.
|
|
25
|
+
"""
|
|
26
|
+
if os.path.isdir(out_dir):
|
|
27
|
+
shutil.rmtree(out_dir)
|
|
28
|
+
os.makedirs(out_dir, exist_ok=True)
|
|
29
|
+
with zipfile.ZipFile(pptx) as z:
|
|
30
|
+
z.extractall(out_dir)
|
|
31
|
+
print(f"unpacked {pptx} -> {out_dir}")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def pack(in_dir, out_pptx):
|
|
35
|
+
"""Zip the OOXML tree in in_dir into out_pptx ([Content_Types].xml first).
|
|
36
|
+
|
|
37
|
+
Overwrites out_pptx if it exists.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
in_dir: Directory holding the unpacked OOXML parts.
|
|
41
|
+
out_pptx: Destination .pptx path.
|
|
42
|
+
"""
|
|
43
|
+
files = []
|
|
44
|
+
for root, _dirs, names in os.walk(in_dir):
|
|
45
|
+
for n in names:
|
|
46
|
+
full = os.path.join(root, n)
|
|
47
|
+
arc = os.path.relpath(full, in_dir).replace(os.sep, "/")
|
|
48
|
+
files.append((full, arc))
|
|
49
|
+
# [Content_Types].xml conventionally first.
|
|
50
|
+
files.sort(key=lambda fa: (fa[1] != "[Content_Types].xml", fa[1]))
|
|
51
|
+
if os.path.exists(out_pptx):
|
|
52
|
+
os.remove(out_pptx)
|
|
53
|
+
with zipfile.ZipFile(out_pptx, "w", zipfile.ZIP_DEFLATED) as z:
|
|
54
|
+
for full, arc in files:
|
|
55
|
+
z.write(full, arc)
|
|
56
|
+
print(f"packed {in_dir} -> {out_pptx} ({len(files)} parts)")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def clean(in_dir):
|
|
60
|
+
"""Remove slide parts not referenced by presentation.xml.rels.
|
|
61
|
+
|
|
62
|
+
Also removes their rels and matching notesSlides. Minimal orphan sweep;
|
|
63
|
+
deletes files from in_dir in place.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
in_dir: Directory holding the unpacked OOXML parts.
|
|
67
|
+
"""
|
|
68
|
+
rels = os.path.join(in_dir, "ppt", "_rels", "presentation.xml.rels")
|
|
69
|
+
if not os.path.isfile(rels):
|
|
70
|
+
print("no presentation.xml.rels; nothing to clean")
|
|
71
|
+
return
|
|
72
|
+
txt = open(rels, encoding="utf-8").read()
|
|
73
|
+
referenced = set(re.findall(r'Target="(slides/slide\d+\.xml)"', txt))
|
|
74
|
+
slides_dir = os.path.join(in_dir, "ppt", "slides")
|
|
75
|
+
removed = 0
|
|
76
|
+
if os.path.isdir(slides_dir):
|
|
77
|
+
for n in os.listdir(slides_dir):
|
|
78
|
+
m = re.match(r"slide\d+\.xml$", n)
|
|
79
|
+
if not m:
|
|
80
|
+
continue
|
|
81
|
+
if f"slides/{n}" not in referenced:
|
|
82
|
+
os.remove(os.path.join(slides_dir, n))
|
|
83
|
+
rel = os.path.join(slides_dir, "_rels", n + ".rels")
|
|
84
|
+
if os.path.isfile(rel):
|
|
85
|
+
os.remove(rel)
|
|
86
|
+
removed += 1
|
|
87
|
+
print(f"clean: removed {removed} orphan slide part(s)")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def render(pptx, outdir="."):
|
|
91
|
+
"""Render a .pptx to per-page JPEGs (soffice -> pdf -> pdftoppm).
|
|
92
|
+
|
|
93
|
+
Best-effort QA; prints the generated JPEG paths.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
pptx: Path to the source .pptx.
|
|
97
|
+
outdir: Output directory for the pdf and jpegs.
|
|
98
|
+
|
|
99
|
+
Raises:
|
|
100
|
+
subprocess.CalledProcessError: If soffice or pdftoppm fails.
|
|
101
|
+
"""
|
|
102
|
+
os.makedirs(outdir, exist_ok=True)
|
|
103
|
+
subprocess.run(
|
|
104
|
+
["soffice", "--headless", "--convert-to", "pdf", "--outdir", outdir, pptx],
|
|
105
|
+
check=True,
|
|
106
|
+
)
|
|
107
|
+
pdf = os.path.join(outdir, os.path.splitext(os.path.basename(pptx))[0] + ".pdf")
|
|
108
|
+
subprocess.run(
|
|
109
|
+
["pdftoppm", "-jpeg", "-r", "130", pdf, os.path.join(outdir, "slide")],
|
|
110
|
+
check=True,
|
|
111
|
+
)
|
|
112
|
+
jpegs = sorted(f for f in os.listdir(outdir) if f.startswith("slide") and f.endswith(".jpg"))
|
|
113
|
+
print("\n".join(os.path.join(outdir, j) for j in jpegs))
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def main(argv):
|
|
117
|
+
"""Dispatch the CLI subcommand and return a process exit code.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
argv: Argument vector (argv[1] is the subcommand).
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
0 on success, 1 on usage error.
|
|
124
|
+
"""
|
|
125
|
+
if len(argv) < 2:
|
|
126
|
+
print(__doc__)
|
|
127
|
+
return 1
|
|
128
|
+
cmd = argv[1]
|
|
129
|
+
if cmd == "unpack" and len(argv) == 4:
|
|
130
|
+
unpack(argv[2], argv[3])
|
|
131
|
+
elif cmd == "pack" and len(argv) == 4:
|
|
132
|
+
pack(argv[2], argv[3])
|
|
133
|
+
elif cmd == "clean" and len(argv) == 3:
|
|
134
|
+
clean(argv[2])
|
|
135
|
+
elif cmd == "render" and len(argv) in (3, 4):
|
|
136
|
+
render(argv[2], argv[3] if len(argv) == 4 else ".")
|
|
137
|
+
else:
|
|
138
|
+
print(__doc__)
|
|
139
|
+
return 1
|
|
140
|
+
return 0
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if __name__ == "__main__":
|
|
144
|
+
sys.exit(main(sys.argv))
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Python deps for the .pptx track of report-formatting.
|
|
2
|
+
# Install: pip install -r requirements.txt --break-system-packages
|
|
3
|
+
# System tools (not pip): soffice (LibreOffice headless) + pdftoppm (poppler) for QA render.
|
|
4
|
+
python-pptx>=1.0.0
|
|
5
|
+
lxml>=5.0.0
|
|
6
|
+
Pillow>=10.0.0
|
|
7
|
+
defusedxml>=0.7.1
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Reusable status-report slide builders (Claro theme), for the report-formatter
|
|
3
|
+
agent. Generic — no project-specific data. Import alongside theme_claro_pptx:
|
|
4
|
+
|
|
5
|
+
import theme_claro_pptx as T
|
|
6
|
+
import status_report_blocks as B
|
|
7
|
+
from pptx import Presentation
|
|
8
|
+
|
|
9
|
+
prs = Presentation("deck.pptx") # or Presentation() for a new deck
|
|
10
|
+
B.build_heatmap(prs.slides[i], title=..., rows=...) # clears + rebuilds slide i
|
|
11
|
+
B.build_gantt(prs.slides[j], title=..., activities=...)
|
|
12
|
+
|
|
13
|
+
Both functions CLEAR the target slide and rebuild it, so they work for new blank
|
|
14
|
+
slides and for in-place rebuilds. Tested against the STT status report (Jun/2026).
|
|
15
|
+
|
|
16
|
+
Two blocks:
|
|
17
|
+
- build_heatmap: período × estágio status grid (Concluído/Em Execução/Pendente/
|
|
18
|
+
Parcial/Backlog), optional trailing data column (e.g. "Backlog (TIDs)").
|
|
19
|
+
- build_gantt: Claro "Cronograma / Próximos Passos" — red header bar, dark week
|
|
20
|
+
columns, per-row accent + category chip + priority bar, category legend.
|
|
21
|
+
"""
|
|
22
|
+
import os
|
|
23
|
+
import sys
|
|
24
|
+
|
|
25
|
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
26
|
+
import theme_claro_pptx as T # noqa: E402
|
|
27
|
+
from pptx.util import Inches # noqa: E402
|
|
28
|
+
from pptx.dml.color import RGBColor # noqa: E402
|
|
29
|
+
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR # noqa: E402
|
|
30
|
+
|
|
31
|
+
# Status palette for the heatmap (key -> fill, icon, label).
|
|
32
|
+
PARCIAL = RGBColor(0xD4, 0xA0, 0x17) # gold — partial / incomplete data
|
|
33
|
+
STATUS = {
|
|
34
|
+
"done": (T.STATUS_DONE, "✓", "Concluído"),
|
|
35
|
+
"inprogress": (T.STATUS_INPROGRESS, "▶", "Em Execução"),
|
|
36
|
+
"pending": (T.STATUS_PENDING, "○", "Pendente"),
|
|
37
|
+
"parcial": (PARCIAL, "◑", "Parcial"),
|
|
38
|
+
"backlog": (T.STATUS_BACKLOG, "–", "Backlog"),
|
|
39
|
+
}
|
|
40
|
+
FULL_LEGEND = ["done", "inprogress", "pending", "parcial", "backlog"]
|
|
41
|
+
DEFAULT_STAGES = ["Download Áudio", "Transcrição", "Carga LakeHouse", "Validação"]
|
|
42
|
+
PRIO_DISPLAY = {"Alta": "Prioridade Alta", "Média": "Prioridade Média", "Baixa": "Prioridade Baixa"}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def build_heatmap(slide, *, title, subtitle, banner, rows, stages=None,
|
|
46
|
+
backlog_col=True, data_header="Backlog (TIDs)",
|
|
47
|
+
legend_keys=None, page=None, total=None):
|
|
48
|
+
"""Build a período × estágio status heatmap; clears and rebuilds `slide`.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
slide: Target slide; cleared and rebuilt in place.
|
|
52
|
+
title: Header title.
|
|
53
|
+
subtitle: Header subtitle.
|
|
54
|
+
banner: Banner strip text below the header.
|
|
55
|
+
rows: List of (label, [status_key per stage], data_str|None); data_str
|
|
56
|
+
fills the optional trailing column when backlog_col is True.
|
|
57
|
+
stages: Column captions (default: the four STT stages).
|
|
58
|
+
backlog_col: If True, add a trailing data column.
|
|
59
|
+
data_header: Caption for the trailing data column.
|
|
60
|
+
legend_keys: Subset/order of STATUS keys to show (default: FULL_LEGEND).
|
|
61
|
+
page: Footer page number, or None to omit the footer.
|
|
62
|
+
total: Footer total page count (defaults to `page`).
|
|
63
|
+
"""
|
|
64
|
+
stages = stages or DEFAULT_STAGES
|
|
65
|
+
legend_keys = legend_keys or FULL_LEGEND
|
|
66
|
+
T.clear_slide_shapes(slide)
|
|
67
|
+
T.add_page_header(slide, title, subtitle)
|
|
68
|
+
T.add_rect(slide, Inches(0.45), Inches(1.32), Inches(12.4), Inches(0.4), T.VERY_LIGHT_GRAY)
|
|
69
|
+
T.add_text(slide, Inches(0.6), Inches(1.36), Inches(12.1), Inches(0.32), banner,
|
|
70
|
+
size=11, bold=True, color=T.CLARO_RED_DARK)
|
|
71
|
+
n = len(rows)
|
|
72
|
+
if backlog_col:
|
|
73
|
+
x_lab, w_lab = Inches(0.45), Inches(1.55)
|
|
74
|
+
x0, cw = Inches(2.05), Inches(2.0)
|
|
75
|
+
x_bk, w_bk = x0 + cw * len(stages) + Inches(0.05), Inches(2.45)
|
|
76
|
+
else:
|
|
77
|
+
x_lab, w_lab = Inches(0.45), Inches(1.9)
|
|
78
|
+
x0 = Inches(2.45)
|
|
79
|
+
cw = (Inches(12.85) - x0) / len(stages)
|
|
80
|
+
x_bk = None
|
|
81
|
+
y_hdr = Inches(1.95)
|
|
82
|
+
ch = Inches(0.45) if n <= 8 else Inches(0.33)
|
|
83
|
+
gap = Inches(0.08) if n <= 8 else Inches(0.035)
|
|
84
|
+
T.add_text(slide, x_lab, y_hdr, w_lab, Inches(0.3), "Período", size=10, bold=True, color=T.MID_GRAY)
|
|
85
|
+
for j, st in enumerate(stages):
|
|
86
|
+
T.add_text(slide, x0 + cw * j, y_hdr, cw, Inches(0.3), st, size=10, bold=True,
|
|
87
|
+
color=T.MID_GRAY, align=PP_ALIGN.CENTER)
|
|
88
|
+
if backlog_col:
|
|
89
|
+
T.add_text(slide, x_bk, y_hdr, w_bk, Inches(0.3), data_header, size=10,
|
|
90
|
+
bold=True, color=T.MID_GRAY, align=PP_ALIGN.CENTER)
|
|
91
|
+
y0 = y_hdr + Inches(0.35)
|
|
92
|
+
for i, (label, statuses, extra) in enumerate(rows):
|
|
93
|
+
y = y0 + i * (ch + gap)
|
|
94
|
+
T.add_rect(slide, x_lab, y, w_lab, ch, T.VERY_LIGHT_GRAY)
|
|
95
|
+
T.add_text(slide, x_lab + Inches(0.1), y, w_lab - Inches(0.1), ch, label,
|
|
96
|
+
size=10, bold=True, color=T.DARK_GRAY, anchor=MSO_ANCHOR.MIDDLE)
|
|
97
|
+
for j, key in enumerate(statuses):
|
|
98
|
+
fill, icon, _ = STATUS[key]
|
|
99
|
+
T.add_filled_text(slide, x0 + cw * j, y, cw - Inches(0.1), ch, icon, fill=fill, size=13)
|
|
100
|
+
if backlog_col:
|
|
101
|
+
T.add_rect(slide, x_bk, y, w_bk, ch, T.LIGHT_GRAY)
|
|
102
|
+
T.add_text(slide, x_bk, y, w_bk, ch, extra or "—", size=11, bold=True,
|
|
103
|
+
color=T.DARK_GRAY, align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
|
|
104
|
+
ly = y0 + n * (ch + gap) + Inches(0.12)
|
|
105
|
+
T.add_text(slide, Inches(0.45), ly, Inches(1.0), Inches(0.3), "Legenda:", size=9,
|
|
106
|
+
bold=True, color=T.MID_GRAY)
|
|
107
|
+
lx = Inches(0.45) + Inches(1.0)
|
|
108
|
+
for key in legend_keys:
|
|
109
|
+
fill, icon, lab = STATUS[key]
|
|
110
|
+
T.add_filled_text(slide, lx, ly, Inches(0.32), Inches(0.28), icon, fill=fill, size=10)
|
|
111
|
+
T.add_text(slide, lx + Inches(0.36), ly, Inches(2.0), Inches(0.3), lab, size=9,
|
|
112
|
+
color=T.DARK_GRAY, anchor=MSO_ANCHOR.MIDDLE)
|
|
113
|
+
lx = lx + Inches(0.36) + Inches(min(len(lab) * 0.09 + 0.3, 2.0))
|
|
114
|
+
if page is not None:
|
|
115
|
+
T.add_page_footer(slide, page, total or page)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def build_gantt(slide, *, title, subtitle, activities, week_labels,
|
|
119
|
+
page=None, total=None, header_left="Atividade / Frente"):
|
|
120
|
+
"""Build the Claro 'Cronograma / Próximos Passos' gantt on `slide`.
|
|
121
|
+
|
|
122
|
+
Clears and rebuilds the slide in place.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
slide: Target slide; cleared and rebuilt in place.
|
|
126
|
+
title: Header title.
|
|
127
|
+
subtitle: Header subtitle.
|
|
128
|
+
activities: List of {name, cat, start, end, prio}; `cat` is a key in
|
|
129
|
+
T.CAT_COLOR, start/end are 1-based week indices, prio in {Alta,
|
|
130
|
+
Média, Baixa}.
|
|
131
|
+
week_labels: One label per week column (use "Mes\\nSn").
|
|
132
|
+
page: Footer page number, or None to omit the footer.
|
|
133
|
+
total: Footer total page count (defaults to `page`).
|
|
134
|
+
header_left: Caption for the top-left header cell.
|
|
135
|
+
"""
|
|
136
|
+
n_weeks = len(week_labels)
|
|
137
|
+
HDR_X, HDR_Y, HDR_W, HDR_H = Inches(0.45), Inches(1.55), Inches(4.2), Inches(0.48)
|
|
138
|
+
ACT_X, ACT_W = Inches(0.6), Inches(2.8)
|
|
139
|
+
CAT_X, CAT_W, CAT_H = Inches(3.4), Inches(1.15), Inches(0.24)
|
|
140
|
+
ACC_X, ACC_W = Inches(0.45), Inches(0.08)
|
|
141
|
+
GRID_X = Inches(4.65)
|
|
142
|
+
GRID_W = Inches(13.333) - GRID_X - Inches(0.45)
|
|
143
|
+
COL_W = GRID_W / n_weeks
|
|
144
|
+
ROW_Y0 = HDR_Y + HDR_H + Inches(0.04)
|
|
145
|
+
ROW_H, ROW_GAP = Inches(0.38), Inches(0.07)
|
|
146
|
+
BAR_H = Inches(0.22)
|
|
147
|
+
BAR_PADY = (ROW_H - BAR_H) / 2
|
|
148
|
+
|
|
149
|
+
T.clear_slide_shapes(slide)
|
|
150
|
+
T.add_page_header(slide, title, subtitle)
|
|
151
|
+
T.add_filled_text(slide, HDR_X, HDR_Y, HDR_W, HDR_H, header_left,
|
|
152
|
+
fill=T.CLARO_RED, tcolor=T.WHITE, size=10, bold=True,
|
|
153
|
+
align=PP_ALIGN.LEFT, anchor=MSO_ANCHOR.MIDDLE)
|
|
154
|
+
for w in range(n_weeks):
|
|
155
|
+
cx = GRID_X + COL_W * w
|
|
156
|
+
T.add_filled_text(slide, cx, HDR_Y, COL_W - Inches(0.01), HDR_H, week_labels[w],
|
|
157
|
+
fill=T.DARK_GRAY, tcolor=T.WHITE, size=9, bold=True,
|
|
158
|
+
align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE)
|
|
159
|
+
for i, a in enumerate(activities):
|
|
160
|
+
y = ROW_Y0 + i * (ROW_H + ROW_GAP)
|
|
161
|
+
color = T.CAT_COLOR[a["cat"]]
|
|
162
|
+
for w in range(n_weeks):
|
|
163
|
+
cx = GRID_X + COL_W * w
|
|
164
|
+
T.add_rect(slide, cx, y, COL_W - Inches(0.01), ROW_H, T.VERY_LIGHT_GRAY)
|
|
165
|
+
T.add_rect(slide, HDR_X, y, HDR_W, ROW_H, T.WHITE)
|
|
166
|
+
T.add_rect(slide, ACC_X, y, ACC_W, ROW_H, color)
|
|
167
|
+
T.add_text(slide, ACT_X, y, ACT_W, ROW_H, a["name"], size=7.5,
|
|
168
|
+
color=T.DARK_GRAY, anchor=MSO_ANCHOR.MIDDLE)
|
|
169
|
+
chip_y = y + (ROW_H - CAT_H) / 2
|
|
170
|
+
T.add_filled_text(slide, CAT_X, chip_y, CAT_W, CAT_H, a["cat"], fill=color,
|
|
171
|
+
tcolor=T.WHITE, size=7.5, bold=True, align=PP_ALIGN.CENTER,
|
|
172
|
+
anchor=MSO_ANCHOR.MIDDLE, corner=True)
|
|
173
|
+
bx = GRID_X + COL_W * (a["start"] - 1) + Inches(0.03)
|
|
174
|
+
bw = COL_W * (a["end"] - a["start"] + 1) - Inches(0.06)
|
|
175
|
+
T.add_filled_text(slide, bx, y + BAR_PADY, bw, BAR_H,
|
|
176
|
+
PRIO_DISPLAY.get(a["prio"], a["prio"]), fill=color,
|
|
177
|
+
tcolor=T.WHITE, size=7.5, bold=True, align=PP_ALIGN.CENTER,
|
|
178
|
+
anchor=MSO_ANCHOR.MIDDLE, corner=True)
|
|
179
|
+
ly = ROW_Y0 + len(activities) * (ROW_H + ROW_GAP) + Inches(0.14)
|
|
180
|
+
T.add_text(slide, Inches(0.45), ly, Inches(1.4), Inches(0.3), "Categorias:",
|
|
181
|
+
size=9, bold=True, color=T.MID_GRAY)
|
|
182
|
+
lx = Inches(1.5)
|
|
183
|
+
seen = []
|
|
184
|
+
for a in activities:
|
|
185
|
+
if a["cat"] not in seen:
|
|
186
|
+
seen.append(a["cat"])
|
|
187
|
+
for cat in seen:
|
|
188
|
+
T.add_rect(slide, lx, ly + Inches(0.05), Inches(0.2), Inches(0.2), T.CAT_COLOR[cat])
|
|
189
|
+
T.add_text(slide, lx + Inches(0.25), ly, Inches(1.6), Inches(0.3), cat, size=9,
|
|
190
|
+
color=T.DARK_GRAY, anchor=MSO_ANCHOR.MIDDLE)
|
|
191
|
+
lx = lx + Inches(0.25 + min(len(cat) * 0.085 + 0.22, 1.6))
|
|
192
|
+
if page is not None:
|
|
193
|
+
T.add_page_footer(slide, page, total or page)
|