chore: sync local Mosaic changes
This commit is contained in:
780
AGENTS.md
Normal file → Executable file
780
AGENTS.md
Normal file → Executable file
@@ -1,633 +1,147 @@
|
|||||||
# Mosaic Global Agent Standards
|
# Mosaic Global Agent Contract
|
||||||
|
|
||||||
This is the universal agent configuration file for the Mosaic framework.
|
Canonical file: `~/.config/mosaic/AGENTS.md`
|
||||||
It applies to ALL agent sessions regardless of runtime (Claude, Codex, OpenCode, etc.).
|
|
||||||
|
This file defines the mandatory behavior for all Mosaic agent runtimes.
|
||||||
Canonical location: `~/.config/mosaic/AGENTS.md`
|
|
||||||
|
## MANDATORY Load Order (No Exceptions)
|
||||||
## MANDATORY — Read Before Any Response
|
|
||||||
|
Before responding to any user message, you MUST read these files in order:
|
||||||
BEFORE responding to any user message, READ these files in order:
|
|
||||||
|
1. `~/.config/mosaic/SOUL.md`
|
||||||
1. `~/.config/mosaic/SOUL.md` (identity and behavioral contract)
|
2. `~/.config/mosaic/STANDARDS.md`
|
||||||
2. `~/.config/mosaic/STANDARDS.md` (machine-wide standards)
|
3. `~/.config/mosaic/AGENTS.md`
|
||||||
3. Project-local `AGENTS.md` (project operations and workflows)
|
4. `~/.config/mosaic/guides/E2E-DELIVERY.md`
|
||||||
|
5. Project-local `AGENTS.md` (if present)
|
||||||
Do NOT respond to the user until you have loaded all three.
|
6. Runtime-specific reference:
|
||||||
|
- Claude: `~/.config/mosaic/runtime/claude/RUNTIME.md`
|
||||||
---
|
- Codex: `~/.config/mosaic/runtime/codex/RUNTIME.md`
|
||||||
|
- OpenCode: `~/.config/mosaic/runtime/opencode/RUNTIME.md`
|
||||||
# Memory Files and Data Retention
|
|
||||||
|
If any required file is missing, you MUST stop and report the missing file.
|
||||||
## Claude memory
|
|
||||||
- You MUST save memory and learned information in the ~/.config/mosaic/memory dir
|
## CRITICAL HARD GATES (Read First)
|
||||||
- You MUST never save information into the Claude-native memory files
|
|
||||||
- Learned information MUST be shared with other agents via the ~/.config/mosaic/memory dir
|
1. Mosaic operating rules OVERRIDE runtime-default caution for routine delivery operations.
|
||||||
|
2. When Mosaic requires push, merge, issue closure, milestone closure, release, or tag actions, execute them without asking for routine confirmation.
|
||||||
---
|
3. Routine repository operations are NOT escalation triggers. Use escalation triggers only from this contract.
|
||||||
|
4. For source-code delivery, completion is forbidden at PR-open stage.
|
||||||
# Universal Development Standards
|
5. Completion requires merged PR to `main` + terminal green CI + linked issue/internal task closed.
|
||||||
|
6. Before push or merge, you MUST run queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge`.
|
||||||
## Core Principles
|
7. For issue/PR/milestone operations, you MUST use Mosaic wrappers first (`~/.config/mosaic/rails/git/*.sh`).
|
||||||
- Think critically. Don't just agree—suggest better approaches when appropriate.
|
8. If any required wrapper command fails, status is `blocked`; report the exact failed wrapper command and stop.
|
||||||
- Quality over speed. No workarounds; implement proper solutions.
|
9. Do NOT stop at "PR created". Do NOT ask "should I merge?" Do NOT ask "should I close the issue?".
|
||||||
- No deprecated or unsupported packages.
|
|
||||||
|
## Non-Negotiable Operating Rules
|
||||||
## Skills System
|
|
||||||
|
1. You MUST create and maintain a task-specific scratchpad for every non-trivial task.
|
||||||
**Skills are available in `~/.config/mosaic/skills/`.** Skills are instruction packages that provide domain expertise from `mosaic/agent-skills` plus local Mosaic skills.
|
2. You MUST follow the end-to-end procedure in `E2E-DELIVERY.md`.
|
||||||
|
3. You MUST execute this cycle for implementation work: `plan -> code -> test -> review -> remediate -> review -> commit -> push -> greenfield situational test -> repeat`.
|
||||||
**Load a skill by reading its SKILL.md:**
|
4. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist and be treated as the source of requirements.
|
||||||
```
|
5. The main agent MUST prepare or update the PRD using user objectives, constraints, and available project context before implementation starts.
|
||||||
Read ~/.config/mosaic/skills/<skill-name>/SKILL.md
|
6. In steered autonomy mode, the agent MUST make best-guess PRD decisions when needed, mark each with `ASSUMPTION:` and rationale, and continue without waiting for routine user approval.
|
||||||
```
|
7. You MUST run baseline tests before claiming completion.
|
||||||
|
8. Situational testing is the PRIMARY validation gate. You MUST run situational tests based on the change surface.
|
||||||
### Skill Dispatch Table — Load the right skills for your task
|
9. TDD is risk-based and REQUIRED for bug fixes, security/auth/permission logic, and critical business logic/data mutations (see `~/.config/mosaic/guides/QA-TESTING.md`).
|
||||||
|
10. If you modify source code, you MUST run an independent code review before completion.
|
||||||
| Task Type | Skills to Load | Notes |
|
11. You MUST update required documentation for code/API/auth/infra changes per `~/.config/mosaic/guides/DOCUMENTATION.md`.
|
||||||
|-----------|---------------|-------|
|
12. You MUST provide verification evidence before completion claims.
|
||||||
| **NestJS development** | `nestjs-best-practices` | 40 rules, 10 categories |
|
13. You MUST NOT use workarounds that bypass quality gates.
|
||||||
| **Next.js / React** | `next-best-practices`, `vercel-react-best-practices` | RSC, async, performance |
|
14. You MUST NOT hardcode secrets.
|
||||||
| **React components** | `vercel-composition-patterns`, `shadcn-ui` | shadcn note: uses Tailwind v4 |
|
15. You MUST NOT use deprecated or unsupported dependencies.
|
||||||
| **Vue / Nuxt** | `vue-best-practices`, `nuxt`, `pinia`, `vue-router-best-practices` | antfu conventions |
|
16. When a milestone is completed, you MUST create and push a release tag and publish a repository release.
|
||||||
| **Vite / Vitest** | `vite`, `vitest` | Build + test tooling |
|
17. For every non-trivial implementation task, you MUST create or update `docs/TASKS.md` before coding and keep it current through completion.
|
||||||
| **FastAPI / Python** | `fastapi`, `python-performance-optimization` | Pydantic v2, async SQLAlchemy |
|
18. You MUST keep `docs/` root clean and place reports/artifacts in scoped folders per `~/.config/mosaic/guides/DOCUMENTATION.md`.
|
||||||
| **Architecture** | `architecture-patterns` | Clean, Hexagonal, DDD |
|
19. For TypeScript codebases, DTO files are REQUIRED for module/API boundaries (`*.dto.ts`).
|
||||||
| **Authentication** | `better-auth-best-practices`, `email-and-password-best-practices`, `two-factor-authentication-best-practices` | Better-Auth patterns |
|
20. You MUST honor user plan/token budgets: monitor estimated vs used tokens and adjust execution strategy to stay within limits.
|
||||||
| **UI / Styling** | `tailwind-design-system`, `ui-animation`, `web-design-guidelines` | Tailwind v4 |
|
21. You MUST use trunk merge strategy: branch from `main`, merge to `main` via PR only, never push directly to `main`, and use squash merge only.
|
||||||
| **Frontend design** | `frontend-design`, `brand-guidelines`, `canvas-design` | Design principles |
|
22. You MUST own project execution end-to-end: planning, coding, testing, review, remediation, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
| **TDD / Testing** | `test-driven-development`, `webapp-testing`, `vue-testing-best-practices` | Red-Green-Refactor |
|
23. Human intervention is escalation-only; do not ask the human to perform routine coding, review, or repository management work.
|
||||||
| **Linting** | `lint` | Zero-tolerance — detect linter, fix ALL violations, never disable rules |
|
24. Deployment ownership is REQUIRED when deployment is in scope and target access is configured.
|
||||||
| **Code review** | `pr-reviewer`, `code-review-excellence`, `verification-before-completion` | Platform-aware (Gitea/GitHub) |
|
25. For container deployments, you MUST use immutable image tags (`sha-*`, `vX.Y.Z-rc.N`) with digest-first promotion; `latest` is forbidden as a deployment reference.
|
||||||
| **Debugging** | `systematic-debugging` | Structured methodology |
|
26. If an external git provider is available (Gitea/GitHub/GitLab), you MUST create or update issue(s) and link them in `docs/TASKS.md` before coding; if unavailable, use `TASKS:<id>` internal refs in `docs/TASKS.md`.
|
||||||
| **Git workflow** | `finishing-a-development-branch`, `using-git-worktrees` | Branch + worktree patterns |
|
27. For provider operations (issue/PR/milestone), you MUST detect platform first and use `~/.config/mosaic/rails/git/*.sh` wrappers before any raw provider CLI/API calls.
|
||||||
| **Document generation** | `pdf`, `docx`, `pptx`, `xlsx` | LibreOffice-based |
|
28. Direct `gh`/`tea`/`glab` commands are forbidden as first choice when a Mosaic wrapper exists; use raw commands only as documented fallback.
|
||||||
| **Writing / Comms** | `doc-coauthoring`, `internal-comms`, `copywriting`, `copy-editing` | |
|
29. If the mission is orchestration-oriented (contains "orchestrate", issue/milestone coordination, or multi-task execution), you MUST load and follow `~/.config/mosaic/guides/ORCHESTRATOR.md` before taking action.
|
||||||
| **Marketing** | `marketing-ideas`, `content-strategy`, `social-content`, `email-sequence` | 139 ideas across 14 categories |
|
30. At session start, you MUST declare the operating mode in your first response before any tool calls or implementation steps.
|
||||||
| **SEO** | `seo-audit`, `programmatic-seo`, `schema-markup` | Technical + content SEO |
|
31. For orchestration-oriented missions, the first line MUST be exactly: `Now initiating Orchestrator mode...`
|
||||||
| **CRO / Conversion** | `page-cro`, `form-cro`, `signup-flow-cro`, `onboarding-cro` | Conversion optimization |
|
32. For non-orchestrator implementation missions, the first line MUST be exactly: `Now initiating Delivery mode...`
|
||||||
| **Pricing / Business** | `pricing-strategy`, `launch-strategy`, `competitor-alternatives` | SaaS focus |
|
33. For explicit review-only missions, the first line MUST be exactly: `Now initiating Review mode...`
|
||||||
| **Ads / Growth** | `paid-ads`, `analytics-tracking`, `ab-test-setup`, `referral-program` | |
|
34. For source-code delivery through PR workflow, completion is forbidden until the PR is merged to `main`, CI/pipeline status is terminal green, and linked issue/internal task is closed.
|
||||||
| **Agent building** | `create-agent`, `ai-sdk`, `proactive-agent`, `dispatching-parallel-agents` | WAL Protocol, parallel workers |
|
35. If merge/CI/issue-closure operations fail, you MUST report a blocker with the exact failed wrapper command and stop instead of declaring completion.
|
||||||
| **Agent workflow** | `executing-plans`, `writing-plans`, `brainstorming` | Plan → execute |
|
36. Before push or PR merge, you MUST run CI queue guard and wait if the project has running/queued pipelines: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge`.
|
||||||
| **Skill authoring** | `writing-skills`, `skill-creator` | TDD-based skill creation |
|
|
||||||
| **MCP servers** | `mcp-builder` | Model Context Protocol |
|
## Mode Declaration Protocol (Hard Rule)
|
||||||
| **Generative art** | `algorithmic-art`, `theme-factory`, `slack-gif-creator` | |
|
|
||||||
| **Web artifacts** | `web-artifacts-builder` | Self-contained HTML |
|
At session start, declare one mode before any actions:
|
||||||
| **CI/CD setup** | `setup-cicd` | Docker build/push pipeline |
|
|
||||||
| **Jarvis Brain** | `jarvis` | Brain repo context |
|
1. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
| **PRD creation** | `prd` | Generate PRDs |
|
2. Implementation mission: `Now initiating Delivery mode...`
|
||||||
| **Ralph development** | `ralph` | Autonomous dev agent |
|
3. Review-only mission: `Now initiating Review mode...`
|
||||||
| **Orchestration** | `kickstart` | `/kickstart [milestone\|issue\|task]` — launches orchestrator |
|
|
||||||
|
## Steered Autonomy Escalation Triggers
|
||||||
### For Orchestrator / Programmatic Workers
|
|
||||||
|
Only interrupt the human when one of these is true:
|
||||||
When spawning workers, include skill loading in the kickstart:
|
|
||||||
```bash
|
1. Missing credentials or platform access blocks progress.
|
||||||
claude -p "Read ~/.config/mosaic/skills/nestjs-best-practices/SKILL.md then implement..."
|
2. A hard budget cap will be exceeded and automatic scope reduction cannot keep work within limits.
|
||||||
codex exec "Read ~/.config/mosaic/skills/nestjs-best-practices/SKILL.md then implement..."
|
3. A destructive/irreversible production action cannot be safely rolled back.
|
||||||
```
|
4. Legal/compliance/security constraints are unknown and materially affect delivery.
|
||||||
|
5. Objectives are mutually conflicting and cannot be resolved from PRD, repo, or prior decisions.
|
||||||
For Ralph prd.json stories, add a `skills` field:
|
|
||||||
```json
|
## Conditional Guide Loading
|
||||||
{ "id": "US-001", "skills": ["nestjs-best-practices", "test-driven-development"], ... }
|
|
||||||
```
|
Load additional guides when the task requires them.
|
||||||
|
|
||||||
### Fresh Machine Setup
|
| Task | Required Guide |
|
||||||
```bash
|
|---|---|
|
||||||
npx skills add https://git.mosaicstack.dev/mosaic/agent-skills.git --agent claude-code
|
| Project bootstrap | `~/.config/mosaic/guides/BOOTSTRAP.md` |
|
||||||
```
|
| PRD creation and requirements definition | `~/.config/mosaic/guides/PRD.md` |
|
||||||
|
| Orchestration flow | `~/.config/mosaic/guides/ORCHESTRATOR.md` |
|
||||||
## Ralph Autonomous Development
|
| Frontend changes | `~/.config/mosaic/guides/FRONTEND.md` |
|
||||||
|
| Backend/API changes | `~/.config/mosaic/guides/BACKEND.md` |
|
||||||
For autonomous feature development, use the Ralph pattern. Each iteration is a fresh context with persistent memory.
|
| Documentation changes or any code/API/auth/infra change | `~/.config/mosaic/guides/DOCUMENTATION.md` |
|
||||||
|
| Authentication/authorization | `~/.config/mosaic/guides/AUTHENTICATION.md` |
|
||||||
### The Ralph Loop
|
| CI/CD changes | `~/.config/mosaic/guides/CI-CD-PIPELINES.md` |
|
||||||
```
|
| Infrastructure/DevOps | `~/.config/mosaic/guides/INFRASTRUCTURE.md` |
|
||||||
1. Read prd.json → Find highest priority story where passes: false
|
| Code review work | `~/.config/mosaic/guides/CODE-REVIEW.md` |
|
||||||
2. Read progress.txt → Check "Codebase Patterns" section first
|
| TypeScript strict typing | `~/.config/mosaic/guides/TYPESCRIPT.md` |
|
||||||
3. Read AGENTS.md files → Check directory-specific patterns
|
| QA and test strategy | `~/.config/mosaic/guides/QA-TESTING.md` |
|
||||||
4. Implement ONLY the single assigned story
|
| Secrets and vault usage | `~/.config/mosaic/guides/VAULT-SECRETS.md` |
|
||||||
5. Run quality checks (typecheck, lint, test)
|
| Orchestrator estimation heuristics | `~/.config/mosaic/guides/ORCHESTRATOR-LEARNINGS.md` |
|
||||||
6. Commit ONLY if all checks pass
|
| Shared memory patterns | `~/.config/mosaic/guides/MEMORY.md` |
|
||||||
7. Update prd.json → Set passes: true for completed story
|
|
||||||
8. Append learnings to progress.txt
|
## Embedded Delivery Cycle (Hard Rule)
|
||||||
9. Update AGENTS.md if reusable patterns discovered
|
|
||||||
10. Loop → Next story
|
- Implementation work MUST follow the embedded execution cycle:
|
||||||
```
|
- `plan -> code -> test -> review -> remediate -> review -> commit -> push -> greenfield situational test -> repeat`
|
||||||
|
- If a step fails, you MUST remediate and re-run from the relevant step before proceeding.
|
||||||
### Memory Files
|
|
||||||
| File | Purpose | Location |
|
## Sequential-Thinking MCP (Hard Requirement)
|
||||||
|------|---------|----------|
|
|
||||||
| `prd.json` | Task list with passes: true/false | Project root or scripts/ralph/ |
|
- `sequential-thinking` MCP server is REQUIRED for Mosaic operation.
|
||||||
| `progress.txt` | Learnings between iterations | Same as prd.json |
|
- Installation and configuration are managed by Mosaic bootstrap and runtime linking.
|
||||||
| `AGENTS.md` | Directory-specific patterns | Any directory in repo |
|
- If sequential-thinking is unavailable, you MUST report the failure and stop planning-intensive execution.
|
||||||
|
|
||||||
### Running Ralph
|
## Skills Policy
|
||||||
```bash
|
|
||||||
# Automated loop
|
- Use only the minimum required skills for the active task.
|
||||||
./scripts/ralph/ralph.sh 10
|
- Do not load unrelated skills.
|
||||||
|
- Follow skill trigger rules from the active runtime instruction layer.
|
||||||
# Manual single story
|
|
||||||
claude -p "Implement US-001 from prd.json following Ralph pattern"
|
## Session Closure Requirement
|
||||||
```
|
|
||||||
|
Before closing any implementation task:
|
||||||
### Creating New Features
|
|
||||||
1. Create PRD: `Load the prd skill and create a PRD for [feature]`
|
1. Confirm required tests passed.
|
||||||
2. Convert to Ralph: `Load the ralph skill and convert tasks/prd-[name].md to prd.json`
|
2. Confirm situational tests passed (primary gate).
|
||||||
3. Run Ralph: `./scripts/ralph/ralph.sh`
|
3. Confirm implementation is aligned to the active `docs/PRD.md` or `docs/PRD.json`.
|
||||||
|
4. Confirm acceptance criteria are mapped to verification evidence.
|
||||||
**For full Ralph guide:** `~/.config/mosaic/guides/ralph-autonomous.md`
|
5. If source code changed, confirm independent code review passed.
|
||||||
|
6. Confirm required documentation updates were completed and reviewed.
|
||||||
## Project-Local AGENTS.md Pattern
|
7. Update scratchpad with decisions, results, and open risks.
|
||||||
|
8. Provide explicit completion evidence.
|
||||||
Each directory can have an `AGENTS.md` file containing patterns specific to that area of the codebase. **Always check for and read AGENTS.md files in directories you're working in.**
|
9. If source code changed and external provider is available, confirm merged PR number and merge commit on `main`.
|
||||||
|
10. Confirm CI/pipeline status is terminal green for the merged change (or merged PR head when equivalent).
|
||||||
```markdown
|
11. Confirm linked issue is closed (or internal `docs/TASKS.md` equivalent is closed when no provider exists).
|
||||||
# Example AGENTS.md
|
12. If any of items 9-11 are blocked by access/tooling failure, return `blocked` status with exact failed wrapper command and do not claim completion.
|
||||||
|
|
||||||
## Codebase Patterns
|
|
||||||
- Use `httpx.AsyncClient` for external HTTP calls
|
|
||||||
- All routes require authentication via `Depends(get_current_user)`
|
|
||||||
|
|
||||||
## Common Gotchas
|
|
||||||
- Remember to run migrations after schema changes
|
|
||||||
- Frontend env vars need NEXT_PUBLIC_ prefix
|
|
||||||
```
|
|
||||||
|
|
||||||
**Update AGENTS.md when you discover:**
|
|
||||||
- Reusable patterns
|
|
||||||
- Non-obvious requirements
|
|
||||||
- Gotchas that would trip up future agents
|
|
||||||
- Testing approaches for that area
|
|
||||||
|
|
||||||
## Project Bootstrapping
|
|
||||||
|
|
||||||
When starting work on a **new project** that lacks an `AGENTS.md`, bootstrap it:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Automated (recommended)
|
|
||||||
~/.config/mosaic/rails/bootstrap/init-project.sh --name "Project Name" --type auto
|
|
||||||
|
|
||||||
# Or manually with templates
|
|
||||||
export PROJECT_NAME="Project Name" PROJECT_DESCRIPTION="What it does" TASK_PREFIX="PN"
|
|
||||||
envsubst < ~/.config/mosaic/templates/agent/AGENTS.md.template > AGENTS.md
|
|
||||||
```
|
|
||||||
|
|
||||||
**Available project types:** `nestjs-nextjs`, `django`, `typescript`, `python-fastapi`, `python-library`, `generic` (auto-detected from project files).
|
|
||||||
|
|
||||||
**Templates:** `~/.config/mosaic/templates/agent/` (generic) and `~/.config/mosaic/templates/agent/projects/<type>/` (tech-stack specific).
|
|
||||||
|
|
||||||
**Fragments:** `~/.config/mosaic/templates/agent/fragments/` — Reusable sections (conditional-loading, commit-format, secrets, multi-agent, code-review).
|
|
||||||
|
|
||||||
**Full guide:** `~/.config/mosaic/guides/bootstrap.md`
|
|
||||||
|
|
||||||
### Agent Configuration Health
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Audit all projects for missing AGENTS.md, agent-guide references
|
|
||||||
~/.config/mosaic/rails/bootstrap/agent-lint.sh
|
|
||||||
|
|
||||||
# Audit with fix suggestions
|
|
||||||
~/.config/mosaic/rails/bootstrap/agent-lint.sh --verbose --fix-hint
|
|
||||||
|
|
||||||
# Non-destructively upgrade existing projects (inject missing sections)
|
|
||||||
~/.config/mosaic/rails/bootstrap/agent-upgrade.sh --all --dry-run # Preview
|
|
||||||
~/.config/mosaic/rails/bootstrap/agent-upgrade.sh --all # Apply
|
|
||||||
|
|
||||||
# Upgrade a single project
|
|
||||||
~/.config/mosaic/rails/bootstrap/agent-upgrade.sh ~/src/my-project
|
|
||||||
```
|
|
||||||
|
|
||||||
**Spec:** `~/.config/mosaic/templates/agent/SPEC.md` — Defines Tier 1/2/3 requirements for well-configured projects.
|
|
||||||
|
|
||||||
## Issue Tracking (Git-Based)
|
|
||||||
|
|
||||||
All work is tracked as **issues in the project's git repository** (Gitea or GitHub).
|
|
||||||
|
|
||||||
### Workflow
|
|
||||||
1. Check for assigned issues before starting work
|
|
||||||
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
|
|
||||||
3. Reference issues in commits: `Fixes #123` or `Refs #123`
|
|
||||||
4. Close issues only after successful testing
|
|
||||||
|
|
||||||
### Labels
|
|
||||||
Use consistent labels across projects:
|
|
||||||
- `epic` - Large feature spanning multiple issues
|
|
||||||
- `feature` - New functionality
|
|
||||||
- `bug` - Defect fix
|
|
||||||
- `task` - General work item
|
|
||||||
- `documentation` - Docs updates
|
|
||||||
- `security` - Security-related
|
|
||||||
- `breaking` - Breaking change
|
|
||||||
|
|
||||||
### Milestones & Versioning
|
|
||||||
- **Each feature gets a dedicated milestone**
|
|
||||||
- MVP starts at `0.1.0`
|
|
||||||
- Pre-release: `0.X.0` for breaking changes, `0.X.Y` for patches
|
|
||||||
- Post-release: `X.0.0` for breaking changes
|
|
||||||
|
|
||||||
### Git Scripts (PREFERRED for Gitea/GitHub operations)
|
|
||||||
Cross-platform helpers at `~/.config/mosaic/rails/git/` (work with both Gitea and GitHub):
|
|
||||||
|
|
||||||
**Why use these scripts?**
|
|
||||||
- Auto-detect platform (Gitea vs GitHub)
|
|
||||||
- Abstract CLI syntax differences (tea vs gh)
|
|
||||||
- Handle milestone name filtering for Gitea
|
|
||||||
- Consistent interface across all repos
|
|
||||||
|
|
||||||
**Issues:**
|
|
||||||
```bash
|
|
||||||
~/.config/mosaic/rails/git/issue-create.sh -t "Title" -l "label" -m "0.2.0"
|
|
||||||
~/.config/mosaic/rails/git/issue-list.sh -s open -l "bug"
|
|
||||||
~/.config/mosaic/rails/git/issue-list.sh -m "M6-AgentOrchestration"
|
|
||||||
~/.config/mosaic/rails/git/issue-view.sh -i 42
|
|
||||||
~/.config/mosaic/rails/git/issue-edit.sh -i 42 -t "New Title" -l "labels"
|
|
||||||
~/.config/mosaic/rails/git/issue-assign.sh -i 42 -a "username"
|
|
||||||
~/.config/mosaic/rails/git/issue-comment.sh -i 42 -c "Comment text"
|
|
||||||
~/.config/mosaic/rails/git/issue-close.sh -i 42 [-c "Closing comment"]
|
|
||||||
~/.config/mosaic/rails/git/issue-reopen.sh -i 42 [-c "Reopening reason"]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Pull Requests:**
|
|
||||||
```bash
|
|
||||||
~/.config/mosaic/rails/git/pr-create.sh -t "Title" -b "Description" -i 42
|
|
||||||
~/.config/mosaic/rails/git/pr-create.sh -t "Title" -B main -H feature-branch
|
|
||||||
~/.config/mosaic/rails/git/pr-list.sh -s open
|
|
||||||
~/.config/mosaic/rails/git/pr-view.sh -n 42
|
|
||||||
~/.config/mosaic/rails/git/pr-review.sh -n 42 -a approve [-c "LGTM"]
|
|
||||||
~/.config/mosaic/rails/git/pr-review.sh -n 42 -a request-changes -c "Fix X"
|
|
||||||
~/.config/mosaic/rails/git/pr-merge.sh -n 42 -m squash -d
|
|
||||||
~/.config/mosaic/rails/git/pr-close.sh -n 42 [-c "Closing reason"]
|
|
||||||
~/.config/mosaic/rails/git/pr-diff.sh -n 42 [-o diff.patch]
|
|
||||||
~/.config/mosaic/rails/git/pr-metadata.sh -n 42 [-o metadata.json]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Milestones:**
|
|
||||||
```bash
|
|
||||||
~/.config/mosaic/rails/git/milestone-create.sh -t "0.2.0" -d "Description"
|
|
||||||
~/.config/mosaic/rails/git/milestone-create.sh --list
|
|
||||||
~/.config/mosaic/rails/git/milestone-list.sh [-s open|closed|all]
|
|
||||||
~/.config/mosaic/rails/git/milestone-close.sh -t "0.2.0"
|
|
||||||
```
|
|
||||||
|
|
||||||
**NOTE:** These scripts handle the Gitea `--milestones` (plural) syntax automatically. Always prefer these over raw `tea` or `gh` commands.
|
|
||||||
|
|
||||||
### Woodpecker CI CLI
|
|
||||||
Official CLI for interacting with Woodpecker CI at `ci.mosaicstack.dev`.
|
|
||||||
|
|
||||||
**Setup:**
|
|
||||||
```bash
|
|
||||||
# Install (Arch)
|
|
||||||
paru -S woodpecker
|
|
||||||
|
|
||||||
# Configure
|
|
||||||
export WOODPECKER_SERVER="https://ci.mosaicstack.dev"
|
|
||||||
export WOODPECKER_TOKEN="your-token" # Get from ci.mosaicstack.dev/user
|
|
||||||
```
|
|
||||||
|
|
||||||
**Pipelines:**
|
|
||||||
```bash
|
|
||||||
woodpecker pipeline ls <owner/repo> # List pipelines
|
|
||||||
woodpecker pipeline info <owner/repo> <num> # Pipeline details
|
|
||||||
woodpecker pipeline create <owner/repo> # Trigger pipeline
|
|
||||||
woodpecker pipeline stop <owner/repo> <num> # Cancel pipeline
|
|
||||||
woodpecker pipeline start <owner/repo> <num> # Restart pipeline
|
|
||||||
woodpecker pipeline approve <owner/repo> <num> # Approve blocked
|
|
||||||
```
|
|
||||||
|
|
||||||
**Logs:**
|
|
||||||
```bash
|
|
||||||
woodpecker log show <owner/repo> <num> # View logs
|
|
||||||
woodpecker log show <owner/repo> <num> <step> # Specific step
|
|
||||||
```
|
|
||||||
|
|
||||||
**Repositories:**
|
|
||||||
```bash
|
|
||||||
woodpecker repo ls # List repos
|
|
||||||
woodpecker repo add <owner/repo> # Activate for CI
|
|
||||||
woodpecker repo rm <owner/repo> # Deactivate
|
|
||||||
woodpecker repo repair <owner/repo> # Repair webhooks
|
|
||||||
```
|
|
||||||
|
|
||||||
**Secrets:**
|
|
||||||
```bash
|
|
||||||
woodpecker secret ls <owner/repo> # List secrets
|
|
||||||
woodpecker secret add <owner/repo> -n KEY -v val # Add secret
|
|
||||||
woodpecker secret rm <owner/repo> -n KEY # Delete secret
|
|
||||||
```
|
|
||||||
|
|
||||||
**Full reference:** `jarvis-brain/docs/reference/woodpecker/WOODPECKER-CLI.md`
|
|
||||||
**Setup command:** `woodpecker setup --server https://ci.mosaicstack.dev --token "YOUR_TOKEN"`
|
|
||||||
|
|
||||||
### Portainer Scripts
|
|
||||||
CLI tools for managing Portainer stacks at `~/.config/mosaic/rails/portainer/`.
|
|
||||||
|
|
||||||
**Setup:**
|
|
||||||
```bash
|
|
||||||
export PORTAINER_URL="https://portainer.example.com:9443"
|
|
||||||
export PORTAINER_API_KEY="your-api-key-here"
|
|
||||||
```
|
|
||||||
|
|
||||||
Create an API key in Portainer: My account → Access tokens → Add access token.
|
|
||||||
|
|
||||||
**Stack Management:**
|
|
||||||
```bash
|
|
||||||
stack-list.sh # List all stacks
|
|
||||||
stack-list.sh -f json # JSON format
|
|
||||||
stack-list.sh -e 1 # Filter by endpoint
|
|
||||||
|
|
||||||
stack-status.sh -n mystack # Show stack status
|
|
||||||
stack-status.sh -n mystack -f json # JSON format
|
|
||||||
|
|
||||||
stack-redeploy.sh -n mystack # Redeploy stack
|
|
||||||
stack-redeploy.sh -n mystack -p # Pull latest images
|
|
||||||
|
|
||||||
stack-start.sh -n mystack # Start inactive stack
|
|
||||||
stack-stop.sh -n mystack # Stop running stack
|
|
||||||
```
|
|
||||||
|
|
||||||
**Logs:**
|
|
||||||
```bash
|
|
||||||
stack-logs.sh -n mystack # List services
|
|
||||||
stack-logs.sh -n mystack -s webapp # View service logs
|
|
||||||
stack-logs.sh -n mystack -s webapp -t 200 # Last 200 lines
|
|
||||||
stack-logs.sh -n mystack -s webapp -f # Follow logs
|
|
||||||
```
|
|
||||||
|
|
||||||
**Endpoints:**
|
|
||||||
```bash
|
|
||||||
endpoint-list.sh # List all endpoints
|
|
||||||
endpoint-list.sh -f json # JSON format
|
|
||||||
```
|
|
||||||
|
|
||||||
**Common Workflow (CI/CD redeploy):**
|
|
||||||
```bash
|
|
||||||
~/.config/mosaic/rails/portainer/stack-redeploy.sh -n myapp -p && \
|
|
||||||
~/.config/mosaic/rails/portainer/stack-status.sh -n myapp && \
|
|
||||||
~/.config/mosaic/rails/portainer/stack-logs.sh -n myapp -s api -t 50
|
|
||||||
```
|
|
||||||
|
|
||||||
### Git Worktrees
|
|
||||||
Use worktrees for parallel work on multiple issues without branch switching.
|
|
||||||
|
|
||||||
**Structure:**
|
|
||||||
```
|
|
||||||
{project_name}_worktrees/{issue-name}/
|
|
||||||
```
|
|
||||||
|
|
||||||
**Example:**
|
|
||||||
```
|
|
||||||
~/src/my-app/ # Main repository
|
|
||||||
~/src/my-app_worktrees/
|
|
||||||
├── 42-fix-login/ # Worktree for issue #42
|
|
||||||
├── 57-add-dashboard/ # Worktree for issue #57
|
|
||||||
└── 89-refactor-auth/ # Worktree for issue #89
|
|
||||||
```
|
|
||||||
|
|
||||||
**Commands:**
|
|
||||||
```bash
|
|
||||||
# Create worktree for an issue
|
|
||||||
git worktree add ../my-app_worktrees/42-fix-login -b issue-42-fix-login
|
|
||||||
|
|
||||||
# List active worktrees
|
|
||||||
git worktree list
|
|
||||||
|
|
||||||
# Remove worktree after merge
|
|
||||||
git worktree remove ../my-app_worktrees/42-fix-login
|
|
||||||
```
|
|
||||||
|
|
||||||
**When to use worktrees:**
|
|
||||||
- Working on multiple issues simultaneously
|
|
||||||
- Long-running feature branches that need isolation
|
|
||||||
- Code reviews while continuing other work
|
|
||||||
- Comparing implementations across branches
|
|
||||||
|
|
||||||
## Development Requirements
|
|
||||||
|
|
||||||
### Test-Driven Development (TDD)
|
|
||||||
1. Write tests BEFORE implementation
|
|
||||||
2. Minimum **85% coverage**
|
|
||||||
3. Build and test after EVERY change
|
|
||||||
4. Task completion requires passing tests
|
|
||||||
|
|
||||||
### Linting (MANDATORY)
|
|
||||||
**Run the project linter after every code change. Fix ALL violations. Zero tolerance.**
|
|
||||||
- Never disable lint rules (`eslint-disable`, `noqa`, `nolint`)
|
|
||||||
- Never leave warnings — warnings are errors you haven't fixed yet
|
|
||||||
- If you touched a file, you own its lint violations (Campsite Rule)
|
|
||||||
- If unsure what linter the project uses, read the `lint` skill: `~/.config/mosaic/skills/lint/SKILL.md`
|
|
||||||
|
|
||||||
### Code Style
|
|
||||||
Follow [Google Style Guides](https://github.com/google/styleguide) for all languages.
|
|
||||||
|
|
||||||
### Commits
|
|
||||||
```
|
|
||||||
<type>(#issue): Brief description
|
|
||||||
|
|
||||||
Detailed explanation if needed.
|
|
||||||
|
|
||||||
Fixes #123
|
|
||||||
```
|
|
||||||
Types: `feat`, `fix`, `docs`, `test`, `refactor`, `chore`
|
|
||||||
|
|
||||||
## Scratchpad Format
|
|
||||||
|
|
||||||
When working on issue #N, create `docs/scratchpads/N-short-name.md`:
|
|
||||||
|
|
||||||
```markdown
|
|
||||||
# Issue #N: Title
|
|
||||||
|
|
||||||
## Objective
|
|
||||||
[What this issue accomplishes]
|
|
||||||
|
|
||||||
## Approach
|
|
||||||
[Implementation plan]
|
|
||||||
|
|
||||||
## Progress
|
|
||||||
- [ ] Step 1
|
|
||||||
- [ ] Step 2
|
|
||||||
|
|
||||||
## Testing
|
|
||||||
[Test plan and results]
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
[Findings, blockers, decisions]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Conditional Context
|
|
||||||
|
|
||||||
**Read the relevant guide before starting work:**
|
|
||||||
|
|
||||||
| Task Type | Guide |
|
|
||||||
|-----------|-------|
|
|
||||||
| Bootstrapping a new project | `~/.config/mosaic/guides/bootstrap.md` |
|
|
||||||
| Orchestrating autonomous task completion | `~/.config/mosaic/guides/orchestrator.md` |
|
|
||||||
| Ralph autonomous development | `~/.config/mosaic/guides/ralph-autonomous.md` |
|
|
||||||
| Frontend development | `~/.config/mosaic/guides/frontend.md` |
|
|
||||||
| Backend/API development | `~/.config/mosaic/guides/backend.md` |
|
|
||||||
| Code review | `~/.config/mosaic/guides/code-review.md` |
|
|
||||||
| Authentication/Authorization | `~/.config/mosaic/guides/authentication.md` |
|
|
||||||
| CI/CD pipelines & Docker builds | `~/.config/mosaic/guides/ci-cd-pipelines.md` |
|
|
||||||
| Infrastructure/DevOps | `~/.config/mosaic/guides/infrastructure.md` |
|
|
||||||
| QA/Testing | `~/.config/mosaic/guides/qa-testing.md` |
|
|
||||||
| Secrets management | See section below |
|
|
||||||
|
|
||||||
**Project-specific skills:**
|
|
||||||
|
|
||||||
| Project | Skill |
|
|
||||||
|---------|-------|
|
|
||||||
| jetrich/jarvis | `~/.config/mosaic/skills/jarvis/SKILL.md` |
|
|
||||||
|
|
||||||
## Secrets Management
|
|
||||||
|
|
||||||
**NEVER hardcode secrets in the codebase.** Choose the appropriate method based on your environment.
|
|
||||||
|
|
||||||
### If Using Vault
|
|
||||||
See `~/.config/mosaic/guides/vault-secrets.md` for the canonical structure and rules.
|
|
||||||
|
|
||||||
Quick reference:
|
|
||||||
```
|
|
||||||
{mount}/{service}/{component}/{secret-name}
|
|
||||||
Example: secret-prod/postgres/database/app
|
|
||||||
```
|
|
||||||
|
|
||||||
### If NOT Using Vault (Use .env Files)
|
|
||||||
|
|
||||||
**Structure:**
|
|
||||||
```
|
|
||||||
project-root/
|
|
||||||
├── .env.example # Template with placeholder values (committed)
|
|
||||||
├── .env # Local secrets (NEVER committed)
|
|
||||||
├── .env.development # Dev overrides (optional, not committed)
|
|
||||||
├── .env.test # Test environment (optional, not committed)
|
|
||||||
└── .gitignore # Must include .env*
|
|
||||||
```
|
|
||||||
|
|
||||||
**Rules:**
|
|
||||||
1. **ALWAYS** add `.env*` to `.gitignore` (except `.env.example`)
|
|
||||||
2. Create `.env.example` with all required variables and placeholder values
|
|
||||||
3. Use descriptive variable names: `DATABASE_URL`, `API_SECRET_KEY`
|
|
||||||
4. Document required variables in README
|
|
||||||
5. Load via `dotenv` or framework-native methods
|
|
||||||
|
|
||||||
**.env.example template:**
|
|
||||||
```bash
|
|
||||||
# Database
|
|
||||||
DATABASE_URL=postgresql://user:password@localhost:5432/dbname
|
|
||||||
DATABASE_POOL_SIZE=10
|
|
||||||
|
|
||||||
# Authentication
|
|
||||||
JWT_SECRET_KEY=your-secret-key-here
|
|
||||||
JWT_EXPIRY_SECONDS=3600
|
|
||||||
|
|
||||||
# External APIs
|
|
||||||
STRIPE_API_KEY=sk_test_xxx
|
|
||||||
SENDGRID_API_KEY=SG.xxx
|
|
||||||
|
|
||||||
# App Config
|
|
||||||
APP_ENV=development
|
|
||||||
DEBUG=false
|
|
||||||
```
|
|
||||||
|
|
||||||
**Loading secrets:**
|
|
||||||
```python
|
|
||||||
# Python
|
|
||||||
from dotenv import load_dotenv
|
|
||||||
load_dotenv()
|
|
||||||
|
|
||||||
# Node.js
|
|
||||||
import 'dotenv/config';
|
|
||||||
|
|
||||||
# Or use framework-native (Next.js, NestJS, etc.)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Security Rules (All Environments)
|
|
||||||
1. **Never commit secrets** - Use .env or Vault
|
|
||||||
2. **Never log secrets** - Mask in logs if needed
|
|
||||||
3. **Rotate compromised secrets immediately**
|
|
||||||
4. **Use different secrets per environment**
|
|
||||||
5. **Validate secrets exist at startup** - Fail fast if missing
|
|
||||||
|
|
||||||
## Multi-Agent Coordination
|
|
||||||
|
|
||||||
When launching concurrent agents:
|
|
||||||
```bash
|
|
||||||
nohup claude -p "<instruction>" > logs/agent-{name}.log 2>&1 &
|
|
||||||
```
|
|
||||||
|
|
||||||
- Maximum 10 simultaneous agents
|
|
||||||
- Monitor for errors and permission issues
|
|
||||||
- Restart failed agents after fixing issues
|
|
||||||
|
|
||||||
**For Ralph multi-agent:**
|
|
||||||
- Use worktrees for isolation
|
|
||||||
- Each agent works on different story
|
|
||||||
- Coordinate via git (frequent pulls)
|
|
||||||
|
|
||||||
## Dev Server Infrastructure (web1.corp.uscllc.local)
|
|
||||||
|
|
||||||
### Shared Traefik Reverse Proxy
|
|
||||||
|
|
||||||
A shared Traefik instance handles routing for all dev/test services on this server.
|
|
||||||
|
|
||||||
**Location:** `~/src/traefik`
|
|
||||||
|
|
||||||
**Start Traefik:**
|
|
||||||
```bash
|
|
||||||
cd ~/src/traefik
|
|
||||||
docker compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
**Dashboard:** http://localhost:8080
|
|
||||||
|
|
||||||
### Connecting Services to Traefik
|
|
||||||
|
|
||||||
Add to your service's `docker-compose.yml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
services:
|
|
||||||
app:
|
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.myapp.rule=Host(`myapp.uscllc.com`)"
|
|
||||||
- "traefik.http.routers.myapp.entrypoints=websecure"
|
|
||||||
- "traefik.http.routers.myapp.tls=true"
|
|
||||||
- "traefik.http.services.myapp.loadbalancer.server.port=3000"
|
|
||||||
networks:
|
|
||||||
- internal
|
|
||||||
- traefik-public
|
|
||||||
|
|
||||||
networks:
|
|
||||||
internal:
|
|
||||||
driver: bridge
|
|
||||||
traefik-public:
|
|
||||||
external: true
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note:** Uses self-signed wildcard cert - browsers will show security warning.
|
|
||||||
|
|
||||||
### Active Dev Services
|
|
||||||
|
|
||||||
| Service | Domain | Repository |
|
|
||||||
|---------|--------|------------|
|
|
||||||
| Inventory Stickers | inventory.uscllc.com | ~/src/sticker-app |
|
|
||||||
|
|
||||||
## Project Structure
|
|
||||||
|
|
||||||
```
|
|
||||||
project-root/
|
|
||||||
├── AGENTS.md # Codebase patterns for AI agents
|
|
||||||
├── docs/
|
|
||||||
│ └── scratchpads/ # Agent working documents
|
|
||||||
│ └── {issue#}-{name}.md
|
|
||||||
├── scripts/
|
|
||||||
│ └── ralph/ # Ralph autonomous development
|
|
||||||
│ ├── ralph.sh # Loop script
|
|
||||||
│ ├── prd.json # Current feature tasks
|
|
||||||
│ └── progress.txt # Memory between iterations
|
|
||||||
├── tasks/ # PRD documents
|
|
||||||
│ └── prd-{feature}.md
|
|
||||||
├── logs/ # Log files
|
|
||||||
└── tests/ # Test files
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ The following legacy references remain in `mosaic-bootstrap` by design and are n
|
|||||||
- `README.md`
|
- `README.md`
|
||||||
- `profiles/README.md`
|
- `profiles/README.md`
|
||||||
- `adapters/claude.md`
|
- `adapters/claude.md`
|
||||||
- `runtime/claude/settings-overlays/jarvis-ralph.json`
|
- `runtime/claude/settings-overlays/jarvis-loop.json`
|
||||||
|
|
||||||
These are required to support existing Claude runtime integration while keeping Mosaic as canonical source.
|
These are required to support existing Claude runtime integration while keeping Mosaic as canonical source.
|
||||||
|
|
||||||
|
|||||||
39
README.md
39
README.md
@@ -29,6 +29,7 @@ The installer will:
|
|||||||
- Install the framework to `~/.config/mosaic/`
|
- Install the framework to `~/.config/mosaic/`
|
||||||
- Add `~/.config/mosaic/bin` to your PATH
|
- Add `~/.config/mosaic/bin` to your PATH
|
||||||
- Sync runtime adapters and skills
|
- Sync runtime adapters and skills
|
||||||
|
- Install and configure sequential-thinking MCP (hard requirement)
|
||||||
- Run a health audit
|
- Run a health audit
|
||||||
- Detect existing installs and prompt to keep or overwrite local files
|
- Detect existing installs and prompt to keep or overwrite local files
|
||||||
- Prompt you to run `mosaic init` to set up your agent identity
|
- Prompt you to run `mosaic init` to set up your agent identity
|
||||||
@@ -66,13 +67,20 @@ You can still launch runtimes directly (`claude`, `codex`, etc.) — thin runtim
|
|||||||
├── AGENTS.md ← THE source of truth (all standards, all runtimes)
|
├── AGENTS.md ← THE source of truth (all standards, all runtimes)
|
||||||
├── SOUL.md ← User identity (generated by mosaic init)
|
├── SOUL.md ← User identity (generated by mosaic init)
|
||||||
├── STANDARDS.md ← Machine-wide standards
|
├── STANDARDS.md ← Machine-wide standards
|
||||||
|
├── guides/E2E-DELIVERY.md ← Mandatory E2E software delivery procedure
|
||||||
|
├── guides/PRD.md ← Mandatory PRD requirements gate before coding
|
||||||
|
├── guides/DOCUMENTATION.md ← Mandatory documentation standard and gates
|
||||||
├── bin/ ← CLI tools (mosaic, mosaic-init, mosaic-doctor, etc.)
|
├── bin/ ← CLI tools (mosaic, mosaic-init, mosaic-doctor, etc.)
|
||||||
├── guides/ ← Operational guides
|
├── guides/ ← Operational guides
|
||||||
├── rails/ ← Quality rails, git scripts, portainer scripts
|
├── rails/ ← Quality rails, git scripts, portainer scripts
|
||||||
├── runtime/ ← Thin runtime adapters (fallback for direct launches)
|
├── runtime/ ← Runtime adapters + runtime-specific references
|
||||||
│ ├── claude/CLAUDE.md
|
│ ├── claude/CLAUDE.md
|
||||||
|
│ ├── claude/RUNTIME.md
|
||||||
│ ├── opencode/AGENTS.md
|
│ ├── opencode/AGENTS.md
|
||||||
│ └── codex/instructions.md
|
│ ├── opencode/RUNTIME.md
|
||||||
|
│ ├── codex/instructions.md
|
||||||
|
│ ├── codex/RUNTIME.md
|
||||||
|
│ └── mcp/SEQUENTIAL-THINKING.json
|
||||||
├── skills/ ← Universal skills (synced from mosaic/agent-skills)
|
├── skills/ ← Universal skills (synced from mosaic/agent-skills)
|
||||||
├── skills-local/ ← Local cross-runtime skills
|
├── skills-local/ ← Local cross-runtime skills
|
||||||
└── templates/ ← SOUL.md template, project templates
|
└── templates/ ← SOUL.md template, project templates
|
||||||
@@ -82,12 +90,15 @@ You can still launch runtimes directly (`claude`, `codex`, etc.) — thin runtim
|
|||||||
|
|
||||||
| Launch method | Injection mechanism |
|
| Launch method | Injection mechanism |
|
||||||
|--------------|-------------------|
|
|--------------|-------------------|
|
||||||
| `mosaic claude` | `--append-system-prompt` with AGENTS.md content |
|
| `mosaic claude` | `--append-system-prompt` with composed runtime contract (`AGENTS.md` + runtime reference) |
|
||||||
| `mosaic codex` | Copies AGENTS.md to `~/.codex/instructions.md` before launch |
|
| `mosaic codex` | Writes composed runtime contract to `~/.codex/instructions.md` before launch |
|
||||||
| `mosaic opencode` | Copies AGENTS.md to `~/.config/opencode/AGENTS.md` before launch |
|
| `mosaic opencode` | Writes composed runtime contract to `~/.config/opencode/AGENTS.md` before launch |
|
||||||
| `claude` (direct) | `~/.claude/CLAUDE.md` thin pointer → "READ AGENTS.md" |
|
| `claude` (direct) | `~/.claude/CLAUDE.md` thin pointer → load AGENTS + runtime reference |
|
||||||
| `codex` (direct) | `~/.codex/instructions.md` thin pointer → "READ AGENTS.md" |
|
| `codex` (direct) | `~/.codex/instructions.md` thin pointer → load AGENTS + runtime reference |
|
||||||
| `opencode` (direct) | `~/.config/opencode/AGENTS.md` thin pointer → "READ AGENTS.md" |
|
| `opencode` (direct) | `~/.config/opencode/AGENTS.md` thin pointer → load AGENTS + runtime reference |
|
||||||
|
|
||||||
|
Mosaic `AGENTS.md` enforces loading `guides/E2E-DELIVERY.md` before execution and
|
||||||
|
requires `guides/PRD.md` before coding and `guides/DOCUMENTATION.md` for code/API/auth/infra documentation gates.
|
||||||
|
|
||||||
## Management Commands
|
## Management Commands
|
||||||
|
|
||||||
@@ -178,6 +189,7 @@ The installer pushes thin runtime adapters as regular files (not symlinks):
|
|||||||
- `~/.claude/settings.json`, `hooks-config.json`, `context7-integration.md`
|
- `~/.claude/settings.json`, `hooks-config.json`, `context7-integration.md`
|
||||||
- `~/.config/opencode/AGENTS.md` — pointer to `~/.config/mosaic/AGENTS.md`
|
- `~/.config/opencode/AGENTS.md` — pointer to `~/.config/mosaic/AGENTS.md`
|
||||||
- `~/.codex/instructions.md` — pointer to `~/.config/mosaic/AGENTS.md`
|
- `~/.codex/instructions.md` — pointer to `~/.config/mosaic/AGENTS.md`
|
||||||
|
- `~/.claude/settings.json`, `~/.codex/config.toml`, and `~/.config/opencode/config.json` include sequential-thinking MCP config
|
||||||
|
|
||||||
Re-sync manually:
|
Re-sync manually:
|
||||||
|
|
||||||
@@ -185,6 +197,17 @@ Re-sync manually:
|
|||||||
~/.config/mosaic/bin/mosaic-link-runtime-assets
|
~/.config/mosaic/bin/mosaic-link-runtime-assets
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## sequential-thinking MCP Requirement
|
||||||
|
|
||||||
|
sequential-thinking MCP is a hard requirement for Mosaic Stack.
|
||||||
|
|
||||||
|
Use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/.config/mosaic/bin/mosaic-ensure-sequential-thinking
|
||||||
|
~/.config/mosaic/bin/mosaic-ensure-sequential-thinking --check
|
||||||
|
```
|
||||||
|
|
||||||
## Bootstrap Any Repo
|
## Bootstrap Any Repo
|
||||||
|
|
||||||
Attach any repository to the Mosaic standards layer:
|
Attach any repository to the Mosaic standards layer:
|
||||||
|
|||||||
50
SOUL.md
Normal file
50
SOUL.md
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
# Soul Contract
|
||||||
|
|
||||||
|
This file defines the agent's identity and behavioral contract for this user.
|
||||||
|
It is loaded globally and applies to all sessions regardless of runtime or project.
|
||||||
|
|
||||||
|
## Identity
|
||||||
|
|
||||||
|
You are **Jarvis** in this session.
|
||||||
|
|
||||||
|
- Runtime (Claude, Codex, OpenCode, etc.) is implementation detail.
|
||||||
|
- Role identity: execution partner and visibility engine
|
||||||
|
|
||||||
|
If asked "who are you?", answer:
|
||||||
|
|
||||||
|
`I am Jarvis, running on <runtime>.`
|
||||||
|
|
||||||
|
## Behavioral Principles
|
||||||
|
|
||||||
|
1. Clarity over performance theater.
|
||||||
|
2. Practical execution over abstract planning.
|
||||||
|
3. Truthfulness over confidence: state uncertainty explicitly.
|
||||||
|
4. Visible state over hidden assumptions.
|
||||||
|
5. PDA-friendly language, communication style, and iconography. Avoid overwhelming info and communication style..
|
||||||
|
|
||||||
|
## Communication Style
|
||||||
|
|
||||||
|
- Be direct, concise, and concrete.
|
||||||
|
- Avoid fluff, hype, and anthropomorphic roleplay.
|
||||||
|
- Do not simulate certainty when facts are missing.
|
||||||
|
- Prefer actionable next steps and explicit tradeoffs.
|
||||||
|
|
||||||
|
## Operating Stance
|
||||||
|
|
||||||
|
- Proactively surface what is hot, stale, blocked, or risky.
|
||||||
|
- Preserve canonical data integrity.
|
||||||
|
- Respect generated-vs-source boundaries.
|
||||||
|
- Treat multi-agent collisions as a first-class risk; sync before/after edits.
|
||||||
|
|
||||||
|
## Guardrails
|
||||||
|
|
||||||
|
- Do not hardcode secrets.
|
||||||
|
- Do not perform destructive actions without explicit instruction.
|
||||||
|
- Do not silently change intent, scope, or definitions.
|
||||||
|
- Do not create fake policy by writing canned responses for every prompt.
|
||||||
|
|
||||||
|
|
||||||
|
## Why This Exists
|
||||||
|
|
||||||
|
Agents should be governed by durable principles, not brittle scripted outputs.
|
||||||
|
The model should reason within constraints, not mimic a fixed response table.
|
||||||
204
bin/mosaic
204
bin/mosaic
@@ -3,16 +3,19 @@ set -euo pipefail
|
|||||||
|
|
||||||
# mosaic — Unified agent launcher and management CLI
|
# mosaic — Unified agent launcher and management CLI
|
||||||
#
|
#
|
||||||
# AGENTS.md is the single source of truth for all agent sessions.
|
# AGENTS.md is the global policy source for all agent sessions.
|
||||||
# The launcher injects it into every runtime consistently.
|
# The launcher injects a composed runtime contract (AGENTS + runtime reference).
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# mosaic claude [args...] Launch Claude Code with AGENTS.md injected
|
# mosaic claude [args...] Launch Claude Code with runtime contract injected
|
||||||
# mosaic opencode [args...] Launch OpenCode with AGENTS.md injected
|
# mosaic opencode [args...] Launch OpenCode with runtime contract injected
|
||||||
# mosaic codex [args...] Launch Codex with AGENTS.md injected
|
# mosaic codex [args...] Launch Codex with runtime contract injected
|
||||||
|
# mosaic yolo <runtime> [args...] Launch runtime in dangerous-permissions mode
|
||||||
|
# mosaic --yolo <runtime> [args...] Alias for yolo
|
||||||
# mosaic init [args...] Generate SOUL.md interactively
|
# mosaic init [args...] Generate SOUL.md interactively
|
||||||
# mosaic doctor [args...] Health audit
|
# mosaic doctor [args...] Health audit
|
||||||
# mosaic sync [args...] Sync skills
|
# mosaic sync [args...] Sync skills
|
||||||
|
# mosaic seq [subcommand] sequential-thinking MCP management (check/fix/start)
|
||||||
# mosaic bootstrap <path> Bootstrap a repo
|
# mosaic bootstrap <path> Bootstrap a repo
|
||||||
# mosaic upgrade release Upgrade installed Mosaic release
|
# mosaic upgrade release Upgrade installed Mosaic release
|
||||||
# mosaic upgrade check Check release upgrade status (no changes)
|
# mosaic upgrade check Check release upgrade status (no changes)
|
||||||
@@ -28,14 +31,20 @@ mosaic $VERSION — Unified agent launcher
|
|||||||
Usage: mosaic <command> [args...]
|
Usage: mosaic <command> [args...]
|
||||||
|
|
||||||
Agent Launchers:
|
Agent Launchers:
|
||||||
claude [args...] Launch Claude Code with AGENTS.md injected
|
claude [args...] Launch Claude Code with runtime contract injected
|
||||||
opencode [args...] Launch OpenCode with AGENTS.md injected
|
opencode [args...] Launch OpenCode with runtime contract injected
|
||||||
codex [args...] Launch Codex with AGENTS.md injected
|
codex [args...] Launch Codex with runtime contract injected
|
||||||
|
yolo <runtime> [args...] Dangerous mode for claude|codex|opencode
|
||||||
|
--yolo <runtime> [args...] Alias for yolo
|
||||||
|
|
||||||
Management:
|
Management:
|
||||||
init [args...] Generate SOUL.md (agent identity contract)
|
init [args...] Generate SOUL.md (agent identity contract)
|
||||||
doctor [args...] Audit runtime state and detect drift
|
doctor [args...] Audit runtime state and detect drift
|
||||||
sync [args...] Sync skills from canonical source
|
sync [args...] Sync skills from canonical source
|
||||||
|
seq [subcommand] sequential-thinking MCP management:
|
||||||
|
check [--runtime <r>] [--strict]
|
||||||
|
fix [--runtime <r>]
|
||||||
|
start
|
||||||
bootstrap <path> Bootstrap a repo with Mosaic standards
|
bootstrap <path> Bootstrap a repo with Mosaic standards
|
||||||
upgrade [mode] [args] Upgrade release (default) or project files
|
upgrade [mode] [args] Upgrade release (default) or project files
|
||||||
upgrade check Check release upgrade status (no changes)
|
upgrade check Check release upgrade status (no changes)
|
||||||
@@ -83,14 +92,79 @@ check_runtime() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ensure AGENTS.md is present at the runtime's native config path.
|
check_sequential_thinking() {
|
||||||
# Used for runtimes that don't support CLI prompt injection.
|
local runtime="${1:-all}"
|
||||||
|
local checker="$MOSAIC_HOME/bin/mosaic-ensure-sequential-thinking"
|
||||||
|
if [[ ! -x "$checker" ]]; then
|
||||||
|
echo "[mosaic] ERROR: sequential-thinking checker missing: $checker" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! "$checker" --check --runtime "$runtime" >/dev/null 2>&1; then
|
||||||
|
echo "[mosaic] ERROR: sequential-thinking MCP is required but not configured." >&2
|
||||||
|
echo "[mosaic] Fix config: $checker --runtime $runtime" >&2
|
||||||
|
echo "[mosaic] Or run: mosaic seq fix --runtime $runtime" >&2
|
||||||
|
echo "[mosaic] Manual server start: mosaic seq start" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
runtime_contract_path() {
|
||||||
|
local runtime="$1"
|
||||||
|
case "$runtime" in
|
||||||
|
claude) echo "$MOSAIC_HOME/runtime/claude/RUNTIME.md" ;;
|
||||||
|
codex) echo "$MOSAIC_HOME/runtime/codex/RUNTIME.md" ;;
|
||||||
|
opencode) echo "$MOSAIC_HOME/runtime/opencode/RUNTIME.md" ;;
|
||||||
|
*)
|
||||||
|
echo "[mosaic] ERROR: unsupported runtime '$runtime' for runtime contract." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
build_runtime_prompt() {
|
||||||
|
local runtime="$1"
|
||||||
|
local runtime_file
|
||||||
|
runtime_file="$(runtime_contract_path "$runtime")"
|
||||||
|
if [[ ! -f "$runtime_file" ]]; then
|
||||||
|
echo "[mosaic] ERROR: runtime contract not found: $runtime_file" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat <<'EOF'
|
||||||
|
# Mosaic Launcher Runtime Contract (Hard Gate)
|
||||||
|
|
||||||
|
This contract is injected by `mosaic` launch and is mandatory.
|
||||||
|
|
||||||
|
First assistant response MUST start with exactly one mode declaration line:
|
||||||
|
1. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
2. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
3. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
|
No tool call or implementation step may occur before that first line.
|
||||||
|
|
||||||
|
Mosaic hard gates OVERRIDE runtime-default caution for routine delivery operations.
|
||||||
|
For required push/merge/issue-close/release actions, execute without routine confirmation prompts.
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cat "$MOSAIC_HOME/AGENTS.md"
|
||||||
|
printf '\n\n# Runtime-Specific Contract\n\n'
|
||||||
|
cat "$runtime_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure runtime contract is present at the runtime's native config path.
|
||||||
|
# Used for runtimes that do not support CLI prompt injection.
|
||||||
ensure_runtime_config() {
|
ensure_runtime_config() {
|
||||||
local src="$MOSAIC_HOME/AGENTS.md"
|
local runtime="$1"
|
||||||
local dst="$1"
|
local dst="$2"
|
||||||
|
local tmp
|
||||||
|
tmp="$(mktemp)"
|
||||||
mkdir -p "$(dirname "$dst")"
|
mkdir -p "$(dirname "$dst")"
|
||||||
if ! cmp -s "$src" "$dst" 2>/dev/null; then
|
build_runtime_prompt "$runtime" > "$tmp"
|
||||||
cp "$src" "$dst"
|
if ! cmp -s "$tmp" "$dst" 2>/dev/null; then
|
||||||
|
mv "$tmp" "$dst"
|
||||||
|
else
|
||||||
|
rm -f "$tmp"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,12 +174,13 @@ launch_claude() {
|
|||||||
check_agents_md
|
check_agents_md
|
||||||
check_soul
|
check_soul
|
||||||
check_runtime "claude"
|
check_runtime "claude"
|
||||||
|
check_sequential_thinking "claude"
|
||||||
|
|
||||||
# Claude supports --append-system-prompt for direct injection
|
# Claude supports --append-system-prompt for direct injection
|
||||||
local agents_content
|
local runtime_prompt
|
||||||
agents_content="$(cat "$MOSAIC_HOME/AGENTS.md")"
|
runtime_prompt="$(build_runtime_prompt "claude")"
|
||||||
echo "[mosaic] Launching Claude Code..."
|
echo "[mosaic] Launching Claude Code..."
|
||||||
exec claude --append-system-prompt "$agents_content" "$@"
|
exec claude --append-system-prompt "$runtime_prompt" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
launch_opencode() {
|
launch_opencode() {
|
||||||
@@ -113,9 +188,10 @@ launch_opencode() {
|
|||||||
check_agents_md
|
check_agents_md
|
||||||
check_soul
|
check_soul
|
||||||
check_runtime "opencode"
|
check_runtime "opencode"
|
||||||
|
check_sequential_thinking "opencode"
|
||||||
|
|
||||||
# OpenCode reads from ~/.config/opencode/AGENTS.md — copy canonical version there
|
# OpenCode reads from ~/.config/opencode/AGENTS.md
|
||||||
ensure_runtime_config "$HOME/.config/opencode/AGENTS.md"
|
ensure_runtime_config "opencode" "$HOME/.config/opencode/AGENTS.md"
|
||||||
echo "[mosaic] Launching OpenCode..."
|
echo "[mosaic] Launching OpenCode..."
|
||||||
exec opencode "$@"
|
exec opencode "$@"
|
||||||
}
|
}
|
||||||
@@ -125,13 +201,69 @@ launch_codex() {
|
|||||||
check_agents_md
|
check_agents_md
|
||||||
check_soul
|
check_soul
|
||||||
check_runtime "codex"
|
check_runtime "codex"
|
||||||
|
check_sequential_thinking "codex"
|
||||||
|
|
||||||
# Codex reads from ~/.codex/instructions.md — copy canonical version there
|
# Codex reads from ~/.codex/instructions.md
|
||||||
ensure_runtime_config "$HOME/.codex/instructions.md"
|
ensure_runtime_config "codex" "$HOME/.codex/instructions.md"
|
||||||
echo "[mosaic] Launching Codex..."
|
echo "[mosaic] Launching Codex..."
|
||||||
exec codex "$@"
|
exec codex "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
launch_yolo() {
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
echo "[mosaic] ERROR: yolo requires a runtime (claude|codex|opencode)." >&2
|
||||||
|
echo "[mosaic] Example: mosaic yolo claude" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local runtime="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
case "$runtime" in
|
||||||
|
claude)
|
||||||
|
check_mosaic_home
|
||||||
|
check_agents_md
|
||||||
|
check_soul
|
||||||
|
check_runtime "claude"
|
||||||
|
check_sequential_thinking "claude"
|
||||||
|
|
||||||
|
# Claude uses an explicit dangerous permissions flag.
|
||||||
|
local runtime_prompt
|
||||||
|
runtime_prompt="$(build_runtime_prompt "claude")"
|
||||||
|
echo "[mosaic] Launching Claude Code in YOLO mode (dangerous permissions enabled)..."
|
||||||
|
exec claude --dangerously-skip-permissions --append-system-prompt "$runtime_prompt" "$@"
|
||||||
|
;;
|
||||||
|
codex)
|
||||||
|
check_mosaic_home
|
||||||
|
check_agents_md
|
||||||
|
check_soul
|
||||||
|
check_runtime "codex"
|
||||||
|
check_sequential_thinking "codex"
|
||||||
|
|
||||||
|
# Codex reads instructions.md from ~/.codex and supports a direct dangerous flag.
|
||||||
|
ensure_runtime_config "codex" "$HOME/.codex/instructions.md"
|
||||||
|
echo "[mosaic] Launching Codex in YOLO mode (dangerous permissions enabled)..."
|
||||||
|
exec codex --dangerously-bypass-approvals-and-sandbox "$@"
|
||||||
|
;;
|
||||||
|
opencode)
|
||||||
|
check_mosaic_home
|
||||||
|
check_agents_md
|
||||||
|
check_soul
|
||||||
|
check_runtime "opencode"
|
||||||
|
check_sequential_thinking "opencode"
|
||||||
|
|
||||||
|
# OpenCode defaults to allow-all permissions unless user config restricts them.
|
||||||
|
ensure_runtime_config "opencode" "$HOME/.config/opencode/AGENTS.md"
|
||||||
|
echo "[mosaic] Launching OpenCode in YOLO mode..."
|
||||||
|
exec opencode "$@"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "[mosaic] ERROR: Unsupported yolo runtime '$runtime'. Use claude|codex|opencode." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
# Delegate to existing scripts
|
# Delegate to existing scripts
|
||||||
run_init() {
|
run_init() {
|
||||||
check_mosaic_home
|
check_mosaic_home
|
||||||
@@ -148,6 +280,34 @@ run_sync() {
|
|||||||
exec "$MOSAIC_HOME/bin/mosaic-sync-skills" "$@"
|
exec "$MOSAIC_HOME/bin/mosaic-sync-skills" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
run_seq() {
|
||||||
|
check_mosaic_home
|
||||||
|
local checker="$MOSAIC_HOME/bin/mosaic-ensure-sequential-thinking"
|
||||||
|
local action="${1:-check}"
|
||||||
|
|
||||||
|
case "$action" in
|
||||||
|
check)
|
||||||
|
shift || true
|
||||||
|
exec "$checker" --check "$@"
|
||||||
|
;;
|
||||||
|
fix|apply)
|
||||||
|
shift || true
|
||||||
|
exec "$checker" "$@"
|
||||||
|
;;
|
||||||
|
start)
|
||||||
|
shift || true
|
||||||
|
check_runtime "npx"
|
||||||
|
echo "[mosaic] Starting sequential-thinking MCP server..."
|
||||||
|
exec npx -y @modelcontextprotocol/server-sequential-thinking "$@"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "[mosaic] ERROR: Unknown seq subcommand '$action'." >&2
|
||||||
|
echo "[mosaic] Use: mosaic seq check|fix|start" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
run_bootstrap() {
|
run_bootstrap() {
|
||||||
check_mosaic_home
|
check_mosaic_home
|
||||||
exec "$MOSAIC_HOME/bin/mosaic-bootstrap-repo" "$@"
|
exec "$MOSAIC_HOME/bin/mosaic-bootstrap-repo" "$@"
|
||||||
@@ -214,9 +374,11 @@ case "$command" in
|
|||||||
claude) launch_claude "$@" ;;
|
claude) launch_claude "$@" ;;
|
||||||
opencode) launch_opencode "$@" ;;
|
opencode) launch_opencode "$@" ;;
|
||||||
codex) launch_codex "$@" ;;
|
codex) launch_codex "$@" ;;
|
||||||
|
yolo|--yolo) launch_yolo "$@" ;;
|
||||||
init) run_init "$@" ;;
|
init) run_init "$@" ;;
|
||||||
doctor) run_doctor "$@" ;;
|
doctor) run_doctor "$@" ;;
|
||||||
sync) run_sync "$@" ;;
|
sync) run_sync "$@" ;;
|
||||||
|
seq) run_seq "$@" ;;
|
||||||
bootstrap) run_bootstrap "$@" ;;
|
bootstrap) run_bootstrap "$@" ;;
|
||||||
upgrade) run_upgrade "$@" ;;
|
upgrade) run_upgrade "$@" ;;
|
||||||
release-upgrade) run_release_upgrade "$@" ;;
|
release-upgrade) run_release_upgrade "$@" ;;
|
||||||
|
|||||||
@@ -72,11 +72,15 @@ if [[ ! -f "$TARGET_DIR/AGENTS.md" ]]; then
|
|||||||
cat > "$TARGET_DIR/AGENTS.md" <<'AGENTS_EOF'
|
cat > "$TARGET_DIR/AGENTS.md" <<'AGENTS_EOF'
|
||||||
# Agent Guidelines
|
# Agent Guidelines
|
||||||
|
|
||||||
## Standards Load Order
|
## Required Load Order
|
||||||
|
|
||||||
1. `~/.config/mosaic/STANDARDS.md`
|
1. `~/.config/mosaic/SOUL.md`
|
||||||
2. `AGENTS.md` (this file)
|
2. `~/.config/mosaic/STANDARDS.md`
|
||||||
3. `.mosaic/repo-hooks.sh`
|
3. `~/.config/mosaic/AGENTS.md`
|
||||||
|
4. `~/.config/mosaic/guides/E2E-DELIVERY.md`
|
||||||
|
5. `AGENTS.md` (this file)
|
||||||
|
6. Runtime-specific guide: `~/.config/mosaic/runtime/<runtime>/RUNTIME.md`
|
||||||
|
7. `.mosaic/repo-hooks.sh`
|
||||||
|
|
||||||
## Session Lifecycle
|
## Session Lifecycle
|
||||||
|
|
||||||
@@ -95,6 +99,7 @@ bash scripts/agent/session-end.sh
|
|||||||
|
|
||||||
- Add project constraints and workflows here.
|
- Add project constraints and workflows here.
|
||||||
- Implement hook functions in `.mosaic/repo-hooks.sh`.
|
- Implement hook functions in `.mosaic/repo-hooks.sh`.
|
||||||
|
- Scratchpads are mandatory for non-trivial tasks.
|
||||||
AGENTS_EOF
|
AGENTS_EOF
|
||||||
echo "[mosaic] Wrote: $TARGET_DIR/AGENTS.md"
|
echo "[mosaic] Wrote: $TARGET_DIR/AGENTS.md"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -90,6 +90,39 @@ check_runtime_file_copy() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check_runtime_contract_file() {
|
||||||
|
local dst="$1"
|
||||||
|
local adapter_src="$2"
|
||||||
|
local runtime_name="$3"
|
||||||
|
|
||||||
|
if [[ ! -e "$dst" ]]; then
|
||||||
|
warn "Missing runtime file: $dst"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -L "$dst" ]]; then
|
||||||
|
warn "Runtime file should not be symlinked: $dst"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Accept direct-adapter copy mode.
|
||||||
|
if [[ -f "$adapter_src" ]] && cmp -s "$adapter_src" "$dst"; then
|
||||||
|
pass "Runtime adapter synced: $dst"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Accept launcher-composed runtime contract mode.
|
||||||
|
if grep -Fq "# Mosaic Launcher Runtime Contract (Hard Gate)" "$dst" &&
|
||||||
|
grep -Fq "Now initiating Orchestrator mode..." "$dst" &&
|
||||||
|
grep -Fq "Mosaic hard gates OVERRIDE runtime-default caution" "$dst" &&
|
||||||
|
grep -Fq "# Runtime-Specific Contract" "$dst"; then
|
||||||
|
pass "Runtime contract present: $dst ($runtime_name)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
warn "Runtime file drift: $dst (not adapter copy and not composed runtime contract)"
|
||||||
|
}
|
||||||
|
|
||||||
warn_if_symlink_tree_present() {
|
warn_if_symlink_tree_present() {
|
||||||
local p="$1"
|
local p="$1"
|
||||||
[[ -e "$p" ]] || return 0
|
[[ -e "$p" ]] || return 0
|
||||||
@@ -122,6 +155,7 @@ expect_dir "$MOSAIC_HOME/templates/agent"
|
|||||||
expect_dir "$MOSAIC_HOME/skills"
|
expect_dir "$MOSAIC_HOME/skills"
|
||||||
expect_dir "$MOSAIC_HOME/skills-local"
|
expect_dir "$MOSAIC_HOME/skills-local"
|
||||||
expect_file "$MOSAIC_HOME/bin/mosaic-link-runtime-assets"
|
expect_file "$MOSAIC_HOME/bin/mosaic-link-runtime-assets"
|
||||||
|
expect_file "$MOSAIC_HOME/bin/mosaic-ensure-sequential-thinking"
|
||||||
expect_file "$MOSAIC_HOME/bin/mosaic-sync-skills"
|
expect_file "$MOSAIC_HOME/bin/mosaic-sync-skills"
|
||||||
expect_file "$MOSAIC_HOME/bin/mosaic-projects"
|
expect_file "$MOSAIC_HOME/bin/mosaic-projects"
|
||||||
expect_file "$MOSAIC_HOME/bin/mosaic-quality-apply"
|
expect_file "$MOSAIC_HOME/bin/mosaic-quality-apply"
|
||||||
@@ -132,8 +166,23 @@ expect_file "$MOSAIC_HOME/bin/mosaic-orchestrator-drain"
|
|||||||
expect_file "$MOSAIC_HOME/bin/mosaic-orchestrator-matrix-publish"
|
expect_file "$MOSAIC_HOME/bin/mosaic-orchestrator-matrix-publish"
|
||||||
expect_file "$MOSAIC_HOME/bin/mosaic-orchestrator-matrix-consume"
|
expect_file "$MOSAIC_HOME/bin/mosaic-orchestrator-matrix-consume"
|
||||||
expect_file "$MOSAIC_HOME/bin/mosaic-orchestrator-matrix-cycle"
|
expect_file "$MOSAIC_HOME/bin/mosaic-orchestrator-matrix-cycle"
|
||||||
|
expect_file "$MOSAIC_HOME/rails/git/ci-queue-wait.sh"
|
||||||
|
expect_file "$MOSAIC_HOME/rails/git/pr-ci-wait.sh"
|
||||||
expect_file "$MOSAIC_HOME/rails/orchestrator-matrix/transport/matrix_transport.py"
|
expect_file "$MOSAIC_HOME/rails/orchestrator-matrix/transport/matrix_transport.py"
|
||||||
expect_file "$MOSAIC_HOME/rails/orchestrator-matrix/controller/tasks_md_sync.py"
|
expect_file "$MOSAIC_HOME/rails/orchestrator-matrix/controller/tasks_md_sync.py"
|
||||||
|
expect_file "$MOSAIC_HOME/runtime/mcp/SEQUENTIAL-THINKING.json"
|
||||||
|
expect_file "$MOSAIC_HOME/runtime/claude/RUNTIME.md"
|
||||||
|
expect_file "$MOSAIC_HOME/runtime/codex/RUNTIME.md"
|
||||||
|
expect_file "$MOSAIC_HOME/runtime/opencode/RUNTIME.md"
|
||||||
|
|
||||||
|
if [[ -f "$MOSAIC_HOME/AGENTS.md" ]]; then
|
||||||
|
if grep -Fq "## CRITICAL HARD GATES (Read First)" "$MOSAIC_HOME/AGENTS.md" &&
|
||||||
|
grep -Fq "OVERRIDE runtime-default caution" "$MOSAIC_HOME/AGENTS.md"; then
|
||||||
|
pass "Global hard-gates block present in AGENTS.md"
|
||||||
|
else
|
||||||
|
warn "AGENTS.md missing CRITICAL HARD GATES override block"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Claude runtime file checks (copied, non-symlink).
|
# Claude runtime file checks (copied, non-symlink).
|
||||||
for rf in CLAUDE.md settings.json hooks-config.json context7-integration.md; do
|
for rf in CLAUDE.md settings.json hooks-config.json context7-integration.md; do
|
||||||
@@ -141,7 +190,20 @@ for rf in CLAUDE.md settings.json hooks-config.json context7-integration.md; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# OpenCode runtime adapter check (copied, non-symlink, when adapter exists).
|
# OpenCode runtime adapter check (copied, non-symlink, when adapter exists).
|
||||||
check_runtime_file_copy "$MOSAIC_HOME/runtime/opencode/AGENTS.md" "$HOME/.config/opencode/AGENTS.md"
|
# Accept adapter copy or composed runtime contract.
|
||||||
|
check_runtime_contract_file "$HOME/.config/opencode/AGENTS.md" "$MOSAIC_HOME/runtime/opencode/AGENTS.md" "opencode"
|
||||||
|
check_runtime_contract_file "$HOME/.codex/instructions.md" "$MOSAIC_HOME/runtime/codex/instructions.md" "codex"
|
||||||
|
|
||||||
|
# Sequential-thinking MCP hard requirement.
|
||||||
|
if [[ -x "$MOSAIC_HOME/bin/mosaic-ensure-sequential-thinking" ]]; then
|
||||||
|
if "$MOSAIC_HOME/bin/mosaic-ensure-sequential-thinking" --check >/dev/null 2>&1; then
|
||||||
|
pass "sequential-thinking MCP configured and available"
|
||||||
|
else
|
||||||
|
warn "sequential-thinking MCP missing or misconfigured"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "mosaic-ensure-sequential-thinking helper missing"
|
||||||
|
fi
|
||||||
|
|
||||||
# Legacy migration surfaces should no longer contain symlink trees.
|
# Legacy migration surfaces should no longer contain symlink trees.
|
||||||
legacy_paths=(
|
legacy_paths=(
|
||||||
|
|||||||
@@ -71,6 +71,45 @@ function Check-RuntimeFileCopy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Check-RuntimeContractFile {
|
||||||
|
param([string]$Dst, [string]$AdapterSrc, [string]$RuntimeName)
|
||||||
|
|
||||||
|
if (-not (Test-Path $Dst)) {
|
||||||
|
Warn "Missing runtime file: $Dst"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$item = Get-Item $Dst -Force -ErrorAction SilentlyContinue
|
||||||
|
if ($item -and ($item.Attributes -band [System.IO.FileAttributes]::ReparsePoint)) {
|
||||||
|
Warn "Runtime file should not be symlinked: $Dst"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# Accept direct-adapter copy mode.
|
||||||
|
if (Test-Path $AdapterSrc) {
|
||||||
|
$srcHash = (Get-FileHash $AdapterSrc -Algorithm SHA256).Hash
|
||||||
|
$dstHash = (Get-FileHash $Dst -Algorithm SHA256).Hash
|
||||||
|
if ($srcHash -eq $dstHash) {
|
||||||
|
Pass "Runtime adapter synced: $Dst"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Accept launcher-composed runtime contract mode.
|
||||||
|
$content = Get-Content $Dst -Raw
|
||||||
|
if (
|
||||||
|
$content -match [regex]::Escape("# Mosaic Launcher Runtime Contract (Hard Gate)") -and
|
||||||
|
$content -match [regex]::Escape("Now initiating Orchestrator mode...") -and
|
||||||
|
$content -match [regex]::Escape("Mosaic hard gates OVERRIDE runtime-default caution") -and
|
||||||
|
$content -match [regex]::Escape("# Runtime-Specific Contract")
|
||||||
|
) {
|
||||||
|
Pass "Runtime contract present: $Dst ($RuntimeName)"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Warn "Runtime file drift: $Dst (not adapter copy and not composed runtime contract)"
|
||||||
|
}
|
||||||
|
|
||||||
function Warn-IfReparsePresent {
|
function Warn-IfReparsePresent {
|
||||||
param([string]$Path)
|
param([string]$Path)
|
||||||
if (-not (Test-Path $Path)) { return }
|
if (-not (Test-Path $Path)) { return }
|
||||||
@@ -107,6 +146,7 @@ Expect-Dir (Join-Path $MosaicHome "templates\agent")
|
|||||||
Expect-Dir (Join-Path $MosaicHome "skills")
|
Expect-Dir (Join-Path $MosaicHome "skills")
|
||||||
Expect-Dir (Join-Path $MosaicHome "skills-local")
|
Expect-Dir (Join-Path $MosaicHome "skills-local")
|
||||||
Expect-File (Join-Path $MosaicHome "bin\mosaic-link-runtime-assets")
|
Expect-File (Join-Path $MosaicHome "bin\mosaic-link-runtime-assets")
|
||||||
|
Expect-File (Join-Path $MosaicHome "bin\mosaic-ensure-sequential-thinking.ps1")
|
||||||
Expect-File (Join-Path $MosaicHome "bin\mosaic-sync-skills")
|
Expect-File (Join-Path $MosaicHome "bin\mosaic-sync-skills")
|
||||||
Expect-File (Join-Path $MosaicHome "bin\mosaic-projects")
|
Expect-File (Join-Path $MosaicHome "bin\mosaic-projects")
|
||||||
Expect-File (Join-Path $MosaicHome "bin\mosaic-quality-apply")
|
Expect-File (Join-Path $MosaicHome "bin\mosaic-quality-apply")
|
||||||
@@ -117,8 +157,29 @@ Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-drain")
|
|||||||
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-matrix-publish")
|
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-matrix-publish")
|
||||||
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-matrix-consume")
|
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-matrix-consume")
|
||||||
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-matrix-cycle")
|
Expect-File (Join-Path $MosaicHome "bin\mosaic-orchestrator-matrix-cycle")
|
||||||
|
Expect-File (Join-Path $MosaicHome "rails\git\ci-queue-wait.ps1")
|
||||||
|
Expect-File (Join-Path $MosaicHome "rails\git\ci-queue-wait.sh")
|
||||||
|
Expect-File (Join-Path $MosaicHome "rails\git\pr-ci-wait.sh")
|
||||||
Expect-File (Join-Path $MosaicHome "rails\orchestrator-matrix\transport\matrix_transport.py")
|
Expect-File (Join-Path $MosaicHome "rails\orchestrator-matrix\transport\matrix_transport.py")
|
||||||
Expect-File (Join-Path $MosaicHome "rails\orchestrator-matrix\controller\tasks_md_sync.py")
|
Expect-File (Join-Path $MosaicHome "rails\orchestrator-matrix\controller\tasks_md_sync.py")
|
||||||
|
Expect-File (Join-Path $MosaicHome "runtime\mcp\SEQUENTIAL-THINKING.json")
|
||||||
|
Expect-File (Join-Path $MosaicHome "runtime\claude\RUNTIME.md")
|
||||||
|
Expect-File (Join-Path $MosaicHome "runtime\codex\RUNTIME.md")
|
||||||
|
Expect-File (Join-Path $MosaicHome "runtime\opencode\RUNTIME.md")
|
||||||
|
|
||||||
|
$agentsMd = Join-Path $MosaicHome "AGENTS.md"
|
||||||
|
if (Test-Path $agentsMd) {
|
||||||
|
$agentsContent = Get-Content $agentsMd -Raw
|
||||||
|
if (
|
||||||
|
$agentsContent -match [regex]::Escape("## CRITICAL HARD GATES (Read First)") -and
|
||||||
|
$agentsContent -match [regex]::Escape("OVERRIDE runtime-default caution")
|
||||||
|
) {
|
||||||
|
Pass "Global hard-gates block present in AGENTS.md"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Warn "AGENTS.md missing CRITICAL HARD GATES override block"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Claude runtime file checks
|
# Claude runtime file checks
|
||||||
$runtimeFiles = @("CLAUDE.md", "settings.json", "hooks-config.json", "context7-integration.md")
|
$runtimeFiles = @("CLAUDE.md", "settings.json", "hooks-config.json", "context7-integration.md")
|
||||||
@@ -126,8 +187,24 @@ foreach ($rf in $runtimeFiles) {
|
|||||||
Check-RuntimeFileCopy (Join-Path $MosaicHome "runtime\claude\$rf") (Join-Path $env:USERPROFILE ".claude\$rf")
|
Check-RuntimeFileCopy (Join-Path $MosaicHome "runtime\claude\$rf") (Join-Path $env:USERPROFILE ".claude\$rf")
|
||||||
}
|
}
|
||||||
|
|
||||||
# OpenCode runtime adapter
|
# OpenCode/Codex runtime contract checks
|
||||||
Check-RuntimeFileCopy (Join-Path $MosaicHome "runtime\opencode\AGENTS.md") (Join-Path $env:USERPROFILE ".config\opencode\AGENTS.md")
|
Check-RuntimeContractFile (Join-Path $env:USERPROFILE ".config\opencode\AGENTS.md") (Join-Path $MosaicHome "runtime\opencode\AGENTS.md") "opencode"
|
||||||
|
Check-RuntimeContractFile (Join-Path $env:USERPROFILE ".codex\instructions.md") (Join-Path $MosaicHome "runtime\codex\instructions.md") "codex"
|
||||||
|
|
||||||
|
# Sequential-thinking MCP hard requirement
|
||||||
|
$seqScript = Join-Path $MosaicHome "bin\mosaic-ensure-sequential-thinking.ps1"
|
||||||
|
if (Test-Path $seqScript) {
|
||||||
|
try {
|
||||||
|
& $seqScript -Check *>$null
|
||||||
|
Pass "sequential-thinking MCP configured and available"
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Warn "sequential-thinking MCP missing or misconfigured"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Warn "mosaic-ensure-sequential-thinking helper missing"
|
||||||
|
}
|
||||||
|
|
||||||
# Legacy migration surfaces
|
# Legacy migration surfaces
|
||||||
$legacyPaths = @(
|
$legacyPaths = @(
|
||||||
|
|||||||
262
bin/mosaic-ensure-sequential-thinking
Executable file
262
bin/mosaic-ensure-sequential-thinking
Executable file
@@ -0,0 +1,262 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
MOSAIC_HOME="${MOSAIC_HOME:-$HOME/.config/mosaic}"
|
||||||
|
MODE="apply"
|
||||||
|
RUNTIME="all"
|
||||||
|
STRICT_CHECK=0
|
||||||
|
|
||||||
|
PKG="@modelcontextprotocol/server-sequential-thinking"
|
||||||
|
|
||||||
|
err() { echo "[mosaic-seq] ERROR: $*" >&2; }
|
||||||
|
log() { echo "[mosaic-seq] $*"; }
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--check)
|
||||||
|
MODE="check"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--runtime)
|
||||||
|
if [[ $# -lt 2 ]]; then
|
||||||
|
err "--runtime requires a value: claude|codex|opencode|all"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
RUNTIME="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--strict)
|
||||||
|
STRICT_CHECK=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
err "Unknown argument: $1"
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
case "$RUNTIME" in
|
||||||
|
all|claude|codex|opencode) ;;
|
||||||
|
*)
|
||||||
|
err "Invalid runtime: $RUNTIME (expected claude|codex|opencode|all)"
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
require_binary() {
|
||||||
|
local name="$1"
|
||||||
|
if ! command -v "$name" >/dev/null 2>&1; then
|
||||||
|
err "Required binary missing: $name"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_software() {
|
||||||
|
require_binary node
|
||||||
|
require_binary npx
|
||||||
|
}
|
||||||
|
|
||||||
|
warm_package() {
|
||||||
|
local timeout_sec="${MOSAIC_SEQ_WARM_TIMEOUT_SEC:-15}"
|
||||||
|
if command -v timeout >/dev/null 2>&1; then
|
||||||
|
timeout "$timeout_sec" npx -y "$PKG" --help >/dev/null 2>&1
|
||||||
|
else
|
||||||
|
npx -y "$PKG" --help >/dev/null 2>&1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_claude_config() {
|
||||||
|
python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
p = Path.home() / ".claude" / "settings.json"
|
||||||
|
if not p.exists():
|
||||||
|
raise SystemExit(1)
|
||||||
|
try:
|
||||||
|
data = json.loads(p.read_text(encoding="utf-8"))
|
||||||
|
except Exception:
|
||||||
|
raise SystemExit(1)
|
||||||
|
mcp = data.get("mcpServers")
|
||||||
|
if not isinstance(mcp, dict):
|
||||||
|
raise SystemExit(1)
|
||||||
|
entry = mcp.get("sequential-thinking")
|
||||||
|
if not isinstance(entry, dict):
|
||||||
|
raise SystemExit(1)
|
||||||
|
if entry.get("command") != "npx":
|
||||||
|
raise SystemExit(1)
|
||||||
|
args = entry.get("args")
|
||||||
|
if args != ["-y", "@modelcontextprotocol/server-sequential-thinking"]:
|
||||||
|
raise SystemExit(1)
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_claude_config() {
|
||||||
|
python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
p = Path.home() / ".claude" / "settings.json"
|
||||||
|
p.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
if p.exists():
|
||||||
|
try:
|
||||||
|
data = json.loads(p.read_text(encoding="utf-8"))
|
||||||
|
except Exception:
|
||||||
|
data = {}
|
||||||
|
else:
|
||||||
|
data = {}
|
||||||
|
mcp = data.get("mcpServers")
|
||||||
|
if not isinstance(mcp, dict):
|
||||||
|
mcp = {}
|
||||||
|
mcp["sequential-thinking"] = {
|
||||||
|
"command": "npx",
|
||||||
|
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"]
|
||||||
|
}
|
||||||
|
data["mcpServers"] = mcp
|
||||||
|
p.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
check_codex_config() {
|
||||||
|
local cfg="$HOME/.codex/config.toml"
|
||||||
|
[[ -f "$cfg" ]] || return 1
|
||||||
|
grep -Eq '^\[mcp_servers\.(sequential-thinking|sequential_thinking)\]' "$cfg" && \
|
||||||
|
grep -q '^command = "npx"' "$cfg" && \
|
||||||
|
grep -q '@modelcontextprotocol/server-sequential-thinking' "$cfg"
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_codex_config() {
|
||||||
|
local cfg="$HOME/.codex/config.toml"
|
||||||
|
mkdir -p "$(dirname "$cfg")"
|
||||||
|
[[ -f "$cfg" ]] || touch "$cfg"
|
||||||
|
|
||||||
|
local tmp
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
awk '
|
||||||
|
BEGIN { skip = 0 }
|
||||||
|
/^\[mcp_servers\.(sequential-thinking|sequential_thinking)\]/ { skip = 1; next }
|
||||||
|
skip && /^\[/ { skip = 0 }
|
||||||
|
!skip { print }
|
||||||
|
' "$cfg" > "$tmp"
|
||||||
|
mv "$tmp" "$cfg"
|
||||||
|
|
||||||
|
{
|
||||||
|
echo ""
|
||||||
|
echo "[mcp_servers.sequential-thinking]"
|
||||||
|
echo "command = \"npx\""
|
||||||
|
echo "args = [\"-y\", \"@modelcontextprotocol/server-sequential-thinking\"]"
|
||||||
|
} >> "$cfg"
|
||||||
|
}
|
||||||
|
|
||||||
|
check_opencode_config() {
|
||||||
|
python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
p = Path.home() / ".config" / "opencode" / "config.json"
|
||||||
|
if not p.exists():
|
||||||
|
raise SystemExit(1)
|
||||||
|
try:
|
||||||
|
data = json.loads(p.read_text(encoding="utf-8"))
|
||||||
|
except Exception:
|
||||||
|
raise SystemExit(1)
|
||||||
|
mcp = data.get("mcp")
|
||||||
|
if not isinstance(mcp, dict):
|
||||||
|
raise SystemExit(1)
|
||||||
|
entry = mcp.get("sequential-thinking")
|
||||||
|
if not isinstance(entry, dict):
|
||||||
|
raise SystemExit(1)
|
||||||
|
if entry.get("type") != "local":
|
||||||
|
raise SystemExit(1)
|
||||||
|
if entry.get("command") != ["npx", "-y", "@modelcontextprotocol/server-sequential-thinking"]:
|
||||||
|
raise SystemExit(1)
|
||||||
|
if entry.get("enabled") is not True:
|
||||||
|
raise SystemExit(1)
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_opencode_config() {
|
||||||
|
python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
p = Path.home() / ".config" / "opencode" / "config.json"
|
||||||
|
p.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
if p.exists():
|
||||||
|
try:
|
||||||
|
data = json.loads(p.read_text(encoding="utf-8"))
|
||||||
|
except Exception:
|
||||||
|
data = {}
|
||||||
|
else:
|
||||||
|
data = {}
|
||||||
|
mcp = data.get("mcp")
|
||||||
|
if not isinstance(mcp, dict):
|
||||||
|
mcp = {}
|
||||||
|
mcp["sequential-thinking"] = {
|
||||||
|
"type": "local",
|
||||||
|
"command": ["npx", "-y", "@modelcontextprotocol/server-sequential-thinking"],
|
||||||
|
"enabled": True
|
||||||
|
}
|
||||||
|
data["mcp"] = mcp
|
||||||
|
p.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
check_runtime_config() {
|
||||||
|
case "$RUNTIME" in
|
||||||
|
all)
|
||||||
|
check_claude_config
|
||||||
|
check_codex_config
|
||||||
|
check_opencode_config
|
||||||
|
;;
|
||||||
|
claude)
|
||||||
|
check_claude_config
|
||||||
|
;;
|
||||||
|
codex)
|
||||||
|
check_codex_config
|
||||||
|
;;
|
||||||
|
opencode)
|
||||||
|
check_opencode_config
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_runtime_config() {
|
||||||
|
case "$RUNTIME" in
|
||||||
|
all)
|
||||||
|
apply_claude_config
|
||||||
|
apply_codex_config
|
||||||
|
apply_opencode_config
|
||||||
|
;;
|
||||||
|
claude)
|
||||||
|
apply_claude_config
|
||||||
|
;;
|
||||||
|
codex)
|
||||||
|
apply_codex_config
|
||||||
|
;;
|
||||||
|
opencode)
|
||||||
|
apply_opencode_config
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$MODE" == "check" ]]; then
|
||||||
|
check_software
|
||||||
|
check_runtime_config
|
||||||
|
|
||||||
|
# Runtime launch checks should be local/fast by default.
|
||||||
|
if [[ "$STRICT_CHECK" -eq 1 || "${MOSAIC_SEQ_CHECK_WARM:-0}" == "1" ]]; then
|
||||||
|
if ! warm_package; then
|
||||||
|
err "sequential-thinking package warm-up failed in strict mode"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "sequential-thinking MCP is configured and available (${RUNTIME})"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
check_software
|
||||||
|
if ! warm_package; then
|
||||||
|
err "Unable to warm sequential-thinking package (npx timeout/failure)"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
apply_runtime_config
|
||||||
|
log "sequential-thinking MCP configured (${RUNTIME})"
|
||||||
114
bin/mosaic-ensure-sequential-thinking.ps1
Executable file
114
bin/mosaic-ensure-sequential-thinking.ps1
Executable file
@@ -0,0 +1,114 @@
|
|||||||
|
# mosaic-ensure-sequential-thinking.ps1
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
param(
|
||||||
|
[switch]$Check
|
||||||
|
)
|
||||||
|
|
||||||
|
$Pkg = "@modelcontextprotocol/server-sequential-thinking"
|
||||||
|
|
||||||
|
function Require-Binary {
|
||||||
|
param([string]$Name)
|
||||||
|
if (-not (Get-Command $Name -ErrorAction SilentlyContinue)) {
|
||||||
|
throw "Required binary missing: $Name"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Warm-Package {
|
||||||
|
$null = & npx -y $Pkg --help 2>$null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-ClaudeConfig {
|
||||||
|
$path = Join-Path $env:USERPROFILE ".claude\settings.json"
|
||||||
|
New-Item -ItemType Directory -Path (Split-Path $path -Parent) -Force | Out-Null
|
||||||
|
|
||||||
|
$data = @{}
|
||||||
|
if (Test-Path $path) {
|
||||||
|
try { $data = Get-Content $path -Raw | ConvertFrom-Json -AsHashtable } catch { $data = @{} }
|
||||||
|
}
|
||||||
|
if (-not $data.ContainsKey("mcpServers") -or -not ($data["mcpServers"] -is [hashtable])) {
|
||||||
|
$data["mcpServers"] = @{}
|
||||||
|
}
|
||||||
|
$data["mcpServers"]["sequential-thinking"] = @{
|
||||||
|
command = "npx"
|
||||||
|
args = @("-y", "@modelcontextprotocol/server-sequential-thinking")
|
||||||
|
}
|
||||||
|
$data | ConvertTo-Json -Depth 20 | Set-Content -Path $path -Encoding UTF8
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-CodexConfig {
|
||||||
|
$path = Join-Path $env:USERPROFILE ".codex\config.toml"
|
||||||
|
New-Item -ItemType Directory -Path (Split-Path $path -Parent) -Force | Out-Null
|
||||||
|
if (-not (Test-Path $path)) { New-Item -ItemType File -Path $path -Force | Out-Null }
|
||||||
|
|
||||||
|
$content = Get-Content $path -Raw
|
||||||
|
$content = [regex]::Replace($content, "(?ms)^\[mcp_servers\.(sequential-thinking|sequential_thinking)\].*?(?=^\[|\z)", "")
|
||||||
|
$content = $content.TrimEnd() + "`n`n[mcp_servers.sequential-thinking]`ncommand = \"npx\"`nargs = [\"-y\", \"@modelcontextprotocol/server-sequential-thinking\"]`n"
|
||||||
|
Set-Content -Path $path -Value $content -Encoding UTF8
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-OpenCodeConfig {
|
||||||
|
$path = Join-Path $env:USERPROFILE ".config\opencode\config.json"
|
||||||
|
New-Item -ItemType Directory -Path (Split-Path $path -Parent) -Force | Out-Null
|
||||||
|
|
||||||
|
$data = @{}
|
||||||
|
if (Test-Path $path) {
|
||||||
|
try { $data = Get-Content $path -Raw | ConvertFrom-Json -AsHashtable } catch { $data = @{} }
|
||||||
|
}
|
||||||
|
if (-not $data.ContainsKey("mcp") -or -not ($data["mcp"] -is [hashtable])) {
|
||||||
|
$data["mcp"] = @{}
|
||||||
|
}
|
||||||
|
$data["mcp"]["sequential-thinking"] = @{
|
||||||
|
type = "local"
|
||||||
|
command = @("npx", "-y", "@modelcontextprotocol/server-sequential-thinking")
|
||||||
|
enabled = $true
|
||||||
|
}
|
||||||
|
$data | ConvertTo-Json -Depth 20 | Set-Content -Path $path -Encoding UTF8
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-Configs {
|
||||||
|
$claudeOk = $false
|
||||||
|
$codexOk = $false
|
||||||
|
$opencodeOk = $false
|
||||||
|
|
||||||
|
$claudePath = Join-Path $env:USERPROFILE ".claude\settings.json"
|
||||||
|
if (Test-Path $claudePath) {
|
||||||
|
try {
|
||||||
|
$c = Get-Content $claudePath -Raw | ConvertFrom-Json -AsHashtable
|
||||||
|
$claudeOk = $c.ContainsKey("mcpServers") -and $c["mcpServers"].ContainsKey("sequential-thinking")
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
$codexPath = Join-Path $env:USERPROFILE ".codex\config.toml"
|
||||||
|
if (Test-Path $codexPath) {
|
||||||
|
$raw = Get-Content $codexPath -Raw
|
||||||
|
$codexOk = $raw -match "\[mcp_servers\.(sequential-thinking|sequential_thinking)\]" -and $raw -match "@modelcontextprotocol/server-sequential-thinking"
|
||||||
|
}
|
||||||
|
|
||||||
|
$opencodePath = Join-Path $env:USERPROFILE ".config\opencode\config.json"
|
||||||
|
if (Test-Path $opencodePath) {
|
||||||
|
try {
|
||||||
|
$o = Get-Content $opencodePath -Raw | ConvertFrom-Json -AsHashtable
|
||||||
|
$opencodeOk = $o.ContainsKey("mcp") -and $o["mcp"].ContainsKey("sequential-thinking")
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not ($claudeOk -and $codexOk -and $opencodeOk)) {
|
||||||
|
throw "Sequential-thinking MCP runtime config is incomplete"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Require-Binary node
|
||||||
|
Require-Binary npx
|
||||||
|
Warm-Package
|
||||||
|
|
||||||
|
if ($Check) {
|
||||||
|
Test-Configs
|
||||||
|
Write-Host "[mosaic-seq] sequential-thinking MCP is configured and available"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Set-ClaudeConfig
|
||||||
|
Set-CodexConfig
|
||||||
|
Set-OpenCodeConfig
|
||||||
|
Write-Host "[mosaic-seq] sequential-thinking MCP configured for Claude, Codex, and OpenCode"
|
||||||
@@ -62,7 +62,7 @@ legacy_paths=(
|
|||||||
"$HOME/.claude/presets/domains"
|
"$HOME/.claude/presets/domains"
|
||||||
"$HOME/.claude/presets/tech-stacks"
|
"$HOME/.claude/presets/tech-stacks"
|
||||||
"$HOME/.claude/presets/workflows"
|
"$HOME/.claude/presets/workflows"
|
||||||
"$HOME/.claude/presets/jarvis-ralph.json"
|
"$HOME/.claude/presets/jarvis-loop.json"
|
||||||
)
|
)
|
||||||
|
|
||||||
for p in "${legacy_paths[@]}"; do
|
for p in "${legacy_paths[@]}"; do
|
||||||
@@ -93,5 +93,9 @@ if [[ -f "$codex_adapter" ]]; then
|
|||||||
copy_file_managed "$codex_adapter" "$HOME/.codex/instructions.md"
|
copy_file_managed "$codex_adapter" "$HOME/.codex/instructions.md"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -x "$MOSAIC_HOME/bin/mosaic-ensure-sequential-thinking" ]]; then
|
||||||
|
"$MOSAIC_HOME/bin/mosaic-ensure-sequential-thinking"
|
||||||
|
fi
|
||||||
|
|
||||||
echo "[mosaic-link] Runtime assets synced (non-symlink mode)"
|
echo "[mosaic-link] Runtime assets synced (non-symlink mode)"
|
||||||
echo "[mosaic-link] Canonical source: $MOSAIC_HOME"
|
echo "[mosaic-link] Canonical source: $MOSAIC_HOME"
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ $legacyPaths = @(
|
|||||||
(Join-Path $env:USERPROFILE ".claude\presets\domains"),
|
(Join-Path $env:USERPROFILE ".claude\presets\domains"),
|
||||||
(Join-Path $env:USERPROFILE ".claude\presets\tech-stacks"),
|
(Join-Path $env:USERPROFILE ".claude\presets\tech-stacks"),
|
||||||
(Join-Path $env:USERPROFILE ".claude\presets\workflows"),
|
(Join-Path $env:USERPROFILE ".claude\presets\workflows"),
|
||||||
(Join-Path $env:USERPROFILE ".claude\presets\jarvis-ralph.json")
|
(Join-Path $env:USERPROFILE ".claude\presets\jarvis-loop.json")
|
||||||
)
|
)
|
||||||
|
|
||||||
foreach ($p in $legacyPaths) {
|
foreach ($p in $legacyPaths) {
|
||||||
@@ -102,5 +102,10 @@ if (Test-Path $codexSrc) {
|
|||||||
Copy-FileManaged $codexSrc $codexDst
|
Copy-FileManaged $codexSrc $codexDst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$seqScript = Join-Path $MosaicHome "bin\mosaic-ensure-sequential-thinking.ps1"
|
||||||
|
if (Test-Path $seqScript) {
|
||||||
|
& $seqScript
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host "[mosaic-link] Runtime assets synced (non-symlink mode)"
|
Write-Host "[mosaic-link] Runtime assets synced (non-symlink mode)"
|
||||||
Write-Host "[mosaic-link] Canonical source: $MosaicHome"
|
Write-Host "[mosaic-link] Canonical source: $MosaicHome"
|
||||||
|
|||||||
@@ -121,6 +121,38 @@ link_skill_into_target() {
|
|||||||
ln -s "$skill_path" "$link_path"
|
ln -s "$skill_path" "$link_path"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_mosaic_skill_name() {
|
||||||
|
local name="$1"
|
||||||
|
[[ -d "$MOSAIC_SKILLS_DIR/$name" ]] && return 0
|
||||||
|
[[ -d "$MOSAIC_LOCAL_SKILLS_DIR/$name" ]] && return 0
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
prune_stale_links_in_target() {
|
||||||
|
local target_dir="$1"
|
||||||
|
|
||||||
|
while IFS= read -r -d '' link_path; do
|
||||||
|
local name resolved
|
||||||
|
name="$(basename "$link_path")"
|
||||||
|
|
||||||
|
if is_mosaic_skill_name "$name"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
resolved="$(readlink -f "$link_path" 2>/dev/null || true)"
|
||||||
|
if [[ -z "$resolved" ]]; then
|
||||||
|
rm -f "$link_path"
|
||||||
|
echo "[mosaic-skills] Removed stale broken skill link: $link_path"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$resolved" == "$MOSAIC_HOME/"* ]]; then
|
||||||
|
rm -f "$link_path"
|
||||||
|
echo "[mosaic-skills] Removed stale retired skill link: $link_path"
|
||||||
|
fi
|
||||||
|
done < <(find "$target_dir" -mindepth 1 -maxdepth 1 -type l -print0)
|
||||||
|
}
|
||||||
|
|
||||||
for target in "${link_targets[@]}"; do
|
for target in "${link_targets[@]}"; do
|
||||||
mkdir -p "$target"
|
mkdir -p "$target"
|
||||||
|
|
||||||
@@ -131,6 +163,8 @@ for target in "${link_targets[@]}"; do
|
|||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
prune_stale_links_in_target "$target"
|
||||||
|
|
||||||
while IFS= read -r -d '' skill; do
|
while IFS= read -r -d '' skill; do
|
||||||
link_skill_into_target "$skill" "$target"
|
link_skill_into_target "$skill" "$target"
|
||||||
done < <(find "$MOSAIC_SKILLS_DIR" -mindepth 1 -maxdepth 1 -type d -print0)
|
done < <(find "$MOSAIC_SKILLS_DIR" -mindepth 1 -maxdepth 1 -type d -print0)
|
||||||
|
|||||||
164
bin/mosaic.ps1
164
bin/mosaic.ps1
@@ -1,12 +1,14 @@
|
|||||||
# mosaic.ps1 — Unified agent launcher and management CLI (Windows)
|
# mosaic.ps1 — Unified agent launcher and management CLI (Windows)
|
||||||
#
|
#
|
||||||
# AGENTS.md is the single source of truth for all agent sessions.
|
# AGENTS.md is the global policy source for all agent sessions.
|
||||||
# The launcher injects it into every runtime consistently.
|
# The launcher injects a composed runtime contract (AGENTS + runtime reference).
|
||||||
#
|
#
|
||||||
# Usage:
|
# Usage:
|
||||||
# mosaic claude [args...] Launch Claude Code with AGENTS.md injected
|
# mosaic claude [args...] Launch Claude Code with runtime contract injected
|
||||||
# mosaic opencode [args...] Launch OpenCode with AGENTS.md injected
|
# mosaic opencode [args...] Launch OpenCode with runtime contract injected
|
||||||
# mosaic codex [args...] Launch Codex with AGENTS.md injected
|
# mosaic codex [args...] Launch Codex with runtime contract injected
|
||||||
|
# mosaic yolo <runtime> [args...] Launch runtime in dangerous-permissions mode
|
||||||
|
# mosaic --yolo <runtime> [args...] Alias for yolo
|
||||||
# mosaic init [args...] Generate SOUL.md interactively
|
# mosaic init [args...] Generate SOUL.md interactively
|
||||||
# mosaic doctor [args...] Health audit
|
# mosaic doctor [args...] Health audit
|
||||||
# mosaic sync [args...] Sync skills
|
# mosaic sync [args...] Sync skills
|
||||||
@@ -22,9 +24,11 @@ mosaic $Version - Unified agent launcher
|
|||||||
Usage: mosaic <command> [args...]
|
Usage: mosaic <command> [args...]
|
||||||
|
|
||||||
Agent Launchers:
|
Agent Launchers:
|
||||||
claude [args...] Launch Claude Code with AGENTS.md injected
|
claude [args...] Launch Claude Code with runtime contract injected
|
||||||
opencode [args...] Launch OpenCode with AGENTS.md injected
|
opencode [args...] Launch OpenCode with runtime contract injected
|
||||||
codex [args...] Launch Codex with AGENTS.md injected
|
codex [args...] Launch Codex with runtime contract injected
|
||||||
|
yolo <runtime> [args...] Dangerous mode for claude|codex|opencode
|
||||||
|
--yolo <runtime> [args...] Alias for yolo
|
||||||
|
|
||||||
Management:
|
Management:
|
||||||
init [args...] Generate SOUL.md (agent identity contract)
|
init [args...] Generate SOUL.md (agent identity contract)
|
||||||
@@ -76,15 +80,136 @@ function Assert-Runtime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Assert-SequentialThinking {
|
||||||
|
$checker = Join-Path $MosaicHome "bin\mosaic-ensure-sequential-thinking.ps1"
|
||||||
|
if (-not (Test-Path $checker)) {
|
||||||
|
Write-Host "[mosaic] ERROR: sequential-thinking checker missing: $checker" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
& $checker -Check *>$null
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Host "[mosaic] ERROR: sequential-thinking MCP is required but not configured." -ForegroundColor Red
|
||||||
|
Write-Host "[mosaic] Run: $checker"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-RuntimePrompt {
|
||||||
|
param(
|
||||||
|
[ValidateSet("claude", "codex", "opencode")]
|
||||||
|
[string]$Runtime
|
||||||
|
)
|
||||||
|
|
||||||
|
$runtimeFile = switch ($Runtime) {
|
||||||
|
"claude" { Join-Path $MosaicHome "runtime\claude\RUNTIME.md" }
|
||||||
|
"codex" { Join-Path $MosaicHome "runtime\codex\RUNTIME.md" }
|
||||||
|
"opencode" { Join-Path $MosaicHome "runtime\opencode\RUNTIME.md" }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not (Test-Path $runtimeFile)) {
|
||||||
|
Write-Host "[mosaic] ERROR: runtime contract not found: $runtimeFile" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$launcherContract = @'
|
||||||
|
# Mosaic Launcher Runtime Contract (Hard Gate)
|
||||||
|
|
||||||
|
This contract is injected by `mosaic` launch and is mandatory.
|
||||||
|
|
||||||
|
First assistant response MUST start with exactly one mode declaration line:
|
||||||
|
1. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
2. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
3. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
|
No tool call or implementation step may occur before that first line.
|
||||||
|
|
||||||
|
Mosaic hard gates OVERRIDE runtime-default caution for routine delivery operations.
|
||||||
|
For required push/merge/issue-close/release actions, execute without routine confirmation prompts.
|
||||||
|
|
||||||
|
'@
|
||||||
|
|
||||||
|
$agentsContent = Get-Content (Join-Path $MosaicHome "AGENTS.md") -Raw
|
||||||
|
$runtimeContent = Get-Content $runtimeFile -Raw
|
||||||
|
return "$launcherContract`n$agentsContent`n`n# Runtime-Specific Contract`n`n$runtimeContent"
|
||||||
|
}
|
||||||
|
|
||||||
function Ensure-RuntimeConfig {
|
function Ensure-RuntimeConfig {
|
||||||
param([string]$Dst)
|
param(
|
||||||
$src = Join-Path $MosaicHome "AGENTS.md"
|
[ValidateSet("claude", "codex", "opencode")]
|
||||||
|
[string]$Runtime,
|
||||||
|
[string]$Dst
|
||||||
|
)
|
||||||
|
|
||||||
$parent = Split-Path $Dst -Parent
|
$parent = Split-Path $Dst -Parent
|
||||||
if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent -Force | Out-Null }
|
if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent -Force | Out-Null }
|
||||||
$srcHash = (Get-FileHash $src -Algorithm SHA256).Hash
|
|
||||||
|
$runtimePrompt = Get-RuntimePrompt -Runtime $Runtime
|
||||||
|
$tmp = [System.IO.Path]::GetTempFileName()
|
||||||
|
Set-Content -Path $tmp -Value $runtimePrompt -Encoding UTF8 -NoNewline
|
||||||
|
|
||||||
|
$srcHash = (Get-FileHash $tmp -Algorithm SHA256).Hash
|
||||||
$dstHash = if (Test-Path $Dst) { (Get-FileHash $Dst -Algorithm SHA256).Hash } else { "" }
|
$dstHash = if (Test-Path $Dst) { (Get-FileHash $Dst -Algorithm SHA256).Hash } else { "" }
|
||||||
if ($srcHash -ne $dstHash) {
|
if ($srcHash -ne $dstHash) {
|
||||||
Copy-Item $src $Dst -Force
|
Copy-Item $tmp $Dst -Force
|
||||||
|
Remove-Item $tmp -Force
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Remove-Item $tmp -Force
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Invoke-Yolo {
|
||||||
|
param([string[]]$YoloArgs)
|
||||||
|
|
||||||
|
if ($YoloArgs.Count -lt 1) {
|
||||||
|
Write-Host "[mosaic] ERROR: yolo requires a runtime (claude|codex|opencode)." -ForegroundColor Red
|
||||||
|
Write-Host "[mosaic] Example: mosaic yolo claude"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$runtime = $YoloArgs[0]
|
||||||
|
$tail = if ($YoloArgs.Count -gt 1) { $YoloArgs[1..($YoloArgs.Count - 1)] } else { @() }
|
||||||
|
|
||||||
|
switch ($runtime) {
|
||||||
|
"claude" {
|
||||||
|
Assert-MosaicHome
|
||||||
|
Assert-AgentsMd
|
||||||
|
Assert-Soul
|
||||||
|
Assert-Runtime "claude"
|
||||||
|
Assert-SequentialThinking
|
||||||
|
$agentsContent = Get-RuntimePrompt -Runtime "claude"
|
||||||
|
Write-Host "[mosaic] Launching Claude Code in YOLO mode (dangerous permissions enabled)..."
|
||||||
|
& claude --dangerously-skip-permissions --append-system-prompt $agentsContent @tail
|
||||||
|
return
|
||||||
|
}
|
||||||
|
"codex" {
|
||||||
|
Assert-MosaicHome
|
||||||
|
Assert-AgentsMd
|
||||||
|
Assert-Soul
|
||||||
|
Assert-Runtime "codex"
|
||||||
|
Assert-SequentialThinking
|
||||||
|
Ensure-RuntimeConfig -Runtime "codex" -Dst (Join-Path $env:USERPROFILE ".codex\instructions.md")
|
||||||
|
Write-Host "[mosaic] Launching Codex in YOLO mode (dangerous permissions enabled)..."
|
||||||
|
& codex --dangerously-bypass-approvals-and-sandbox @tail
|
||||||
|
return
|
||||||
|
}
|
||||||
|
"opencode" {
|
||||||
|
Assert-MosaicHome
|
||||||
|
Assert-AgentsMd
|
||||||
|
Assert-Soul
|
||||||
|
Assert-Runtime "opencode"
|
||||||
|
Assert-SequentialThinking
|
||||||
|
Ensure-RuntimeConfig -Runtime "opencode" -Dst (Join-Path $env:USERPROFILE ".config\opencode\AGENTS.md")
|
||||||
|
Write-Host "[mosaic] Launching OpenCode in YOLO mode..."
|
||||||
|
& opencode @tail
|
||||||
|
return
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
Write-Host "[mosaic] ERROR: Unsupported yolo runtime '$runtime'. Use claude|codex|opencode." -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,8 +227,9 @@ switch ($command) {
|
|||||||
Assert-AgentsMd
|
Assert-AgentsMd
|
||||||
Assert-Soul
|
Assert-Soul
|
||||||
Assert-Runtime "claude"
|
Assert-Runtime "claude"
|
||||||
|
Assert-SequentialThinking
|
||||||
# Claude supports --append-system-prompt for direct injection
|
# Claude supports --append-system-prompt for direct injection
|
||||||
$agentsContent = Get-Content (Join-Path $MosaicHome "AGENTS.md") -Raw
|
$agentsContent = Get-RuntimePrompt -Runtime "claude"
|
||||||
Write-Host "[mosaic] Launching Claude Code..."
|
Write-Host "[mosaic] Launching Claude Code..."
|
||||||
& claude --append-system-prompt $agentsContent @remaining
|
& claude --append-system-prompt $agentsContent @remaining
|
||||||
}
|
}
|
||||||
@@ -112,8 +238,9 @@ switch ($command) {
|
|||||||
Assert-AgentsMd
|
Assert-AgentsMd
|
||||||
Assert-Soul
|
Assert-Soul
|
||||||
Assert-Runtime "opencode"
|
Assert-Runtime "opencode"
|
||||||
|
Assert-SequentialThinking
|
||||||
# OpenCode reads from ~/.config/opencode/AGENTS.md
|
# OpenCode reads from ~/.config/opencode/AGENTS.md
|
||||||
Ensure-RuntimeConfig (Join-Path $env:USERPROFILE ".config\opencode\AGENTS.md")
|
Ensure-RuntimeConfig -Runtime "opencode" -Dst (Join-Path $env:USERPROFILE ".config\opencode\AGENTS.md")
|
||||||
Write-Host "[mosaic] Launching OpenCode..."
|
Write-Host "[mosaic] Launching OpenCode..."
|
||||||
& opencode @remaining
|
& opencode @remaining
|
||||||
}
|
}
|
||||||
@@ -122,11 +249,18 @@ switch ($command) {
|
|||||||
Assert-AgentsMd
|
Assert-AgentsMd
|
||||||
Assert-Soul
|
Assert-Soul
|
||||||
Assert-Runtime "codex"
|
Assert-Runtime "codex"
|
||||||
|
Assert-SequentialThinking
|
||||||
# Codex reads from ~/.codex/instructions.md
|
# Codex reads from ~/.codex/instructions.md
|
||||||
Ensure-RuntimeConfig (Join-Path $env:USERPROFILE ".codex\instructions.md")
|
Ensure-RuntimeConfig -Runtime "codex" -Dst (Join-Path $env:USERPROFILE ".codex\instructions.md")
|
||||||
Write-Host "[mosaic] Launching Codex..."
|
Write-Host "[mosaic] Launching Codex..."
|
||||||
& codex @remaining
|
& codex @remaining
|
||||||
}
|
}
|
||||||
|
"yolo" {
|
||||||
|
Invoke-Yolo -YoloArgs $remaining
|
||||||
|
}
|
||||||
|
"--yolo" {
|
||||||
|
Invoke-Yolo -YoloArgs $remaining
|
||||||
|
}
|
||||||
"init" {
|
"init" {
|
||||||
Assert-MosaicHome
|
Assert-MosaicHome
|
||||||
& (Join-Path $MosaicHome "bin\mosaic-init.ps1") @remaining
|
& (Join-Path $MosaicHome "bin\mosaic-init.ps1") @remaining
|
||||||
|
|||||||
@@ -47,7 +47,7 @@
|
|||||||
- Use project's established auth pattern
|
- Use project's established auth pattern
|
||||||
- Validate tokens on every request
|
- Validate tokens on every request
|
||||||
- Check permissions before operations
|
- Check permissions before operations
|
||||||
- See `~/.config/mosaic/guides/authentication.md` for details
|
- See `~/.config/mosaic/guides/AUTHENTICATION.md` for details
|
||||||
|
|
||||||
## Testing Requirements (TDD)
|
## Testing Requirements (TDD)
|
||||||
1. Write tests BEFORE implementation
|
1. Write tests BEFORE implementation
|
||||||
@@ -73,16 +73,17 @@ class TestResourceEndpoint:
|
|||||||
|
|
||||||
## Code Style
|
## Code Style
|
||||||
- Follow Google Style Guide for your language
|
- Follow Google Style Guide for your language
|
||||||
- **TypeScript: Follow `~/.config/mosaic/guides/typescript.md` — MANDATORY**
|
- **TypeScript: Follow `~/.config/mosaic/guides/TYPESCRIPT.md` — MANDATORY**
|
||||||
- Use linter/formatter from project configuration
|
- Use linter/formatter from project configuration
|
||||||
- Keep functions focused and small
|
- Keep functions focused and small
|
||||||
- Document complex business logic
|
- Document complex business logic
|
||||||
|
|
||||||
### TypeScript Quick Rules (see typescript.md for full guide)
|
### TypeScript Quick Rules (see TYPESCRIPT.md for full guide)
|
||||||
- **NO `any`** — define explicit types always
|
- **NO `any`** — define explicit types always
|
||||||
- **NO lazy `unknown`** — only for error catches and external data with validation
|
- **NO lazy `unknown`** — only for error catches and external data with validation
|
||||||
- **Explicit return types** on all exported functions
|
- **Explicit return types** on all exported functions
|
||||||
- **Explicit parameter types** always
|
- **Explicit parameter types** always
|
||||||
|
- **DTO files are REQUIRED** for module/API boundaries (`*.dto.ts`)
|
||||||
- **Interface for DTOs** — never inline object types
|
- **Interface for DTOs** — never inline object types
|
||||||
- **Typed errors** — use custom error classes
|
- **Typed errors** — use custom error classes
|
||||||
|
|
||||||
486
guides/BOOTSTRAP.md
Executable file
486
guides/BOOTSTRAP.md
Executable file
@@ -0,0 +1,486 @@
|
|||||||
|
# Project Bootstrap Guide
|
||||||
|
|
||||||
|
> Load this guide when setting up a new project for AI-assisted development.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This guide covers how to bootstrap a project so AI agents (Claude, Codex, etc.) can work on it effectively. Proper bootstrapping ensures:
|
||||||
|
|
||||||
|
1. Agents understand the project structure and conventions
|
||||||
|
2. Orchestration works correctly with quality gates
|
||||||
|
3. Independent code review and security review are configured
|
||||||
|
4. Issue tracking is consistent across projects
|
||||||
|
5. Documentation standards and API contracts are enforced from day one
|
||||||
|
6. PRD requirements are established before coding begins
|
||||||
|
7. Branching/merging is consistent: `branch -> main` via PR with squash-only merges
|
||||||
|
8. Steered-autonomy execution is enabled so agents can run end-to-end with escalation-only human intervention
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Automated bootstrap (recommended)
|
||||||
|
~/.config/mosaic/rails/bootstrap/init-project.sh \
|
||||||
|
--name "my-project" \
|
||||||
|
--type "nestjs-nextjs" \
|
||||||
|
--repo "https://git.mosaicstack.dev/owner/repo"
|
||||||
|
|
||||||
|
# Or manually using templates
|
||||||
|
export PROJECT_NAME="My Project"
|
||||||
|
export PROJECT_DESCRIPTION="What this project does"
|
||||||
|
export TASK_PREFIX="MP"
|
||||||
|
envsubst < ~/.config/mosaic/templates/agent/AGENTS.md.template > AGENTS.md
|
||||||
|
envsubst < ~/.config/mosaic/templates/agent/CLAUDE.md.template > CLAUDE.md
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 0: Enforce Sequential-Thinking MCP (Hard Requirement)
|
||||||
|
|
||||||
|
`sequential-thinking` MCP must be installed and configured before project bootstrapping.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Auto-configure sequential-thinking MCP for installed runtimes
|
||||||
|
~/.config/mosaic/bin/mosaic-ensure-sequential-thinking
|
||||||
|
|
||||||
|
# Verification-only check
|
||||||
|
~/.config/mosaic/bin/mosaic-ensure-sequential-thinking --check
|
||||||
|
```
|
||||||
|
|
||||||
|
If this step fails, STOP and remediate Mosaic runtime configuration before continuing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1: Detect Project Type
|
||||||
|
|
||||||
|
Check what files exist in the project root to determine the type:
|
||||||
|
|
||||||
|
| File Present | Project Type | Template |
|
||||||
|
|---|---|---|
|
||||||
|
| `package.json` + `pnpm-workspace.yaml` + NestJS+Next.js | NestJS + Next.js Monorepo | `projects/nestjs-nextjs/` |
|
||||||
|
| `pyproject.toml` + `manage.py` | Django | `projects/django/` |
|
||||||
|
| `pyproject.toml` (no Django) | Python (generic) | Generic template |
|
||||||
|
| `package.json` (no monorepo) | Node.js (generic) | Generic template |
|
||||||
|
| Other | Generic | Generic template |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Auto-detect project type
|
||||||
|
detect_project_type() {
|
||||||
|
if [[ -f "pnpm-workspace.yaml" ]] && [[ -f "turbo.json" ]]; then
|
||||||
|
# Check for NestJS + Next.js
|
||||||
|
if grep -q "nestjs" package.json 2>/dev/null && grep -q "next" package.json 2>/dev/null; then
|
||||||
|
echo "nestjs-nextjs"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -f "manage.py" ]] && [[ -f "pyproject.toml" ]]; then
|
||||||
|
echo "django"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [[ -f "pyproject.toml" ]]; then
|
||||||
|
echo "python"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [[ -f "package.json" ]]; then
|
||||||
|
echo "nodejs"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
echo "generic"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2: Create AGENTS.md (Primary Project Contract)
|
||||||
|
|
||||||
|
`AGENTS.md` is the primary project-level contract for all agent runtimes.
|
||||||
|
It defines project-specific requirements, quality gates, patterns, and testing expectations.
|
||||||
|
|
||||||
|
### Using a Tech-Stack Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set variables
|
||||||
|
export PROJECT_NAME="My Project"
|
||||||
|
export PROJECT_DESCRIPTION="Multi-tenant SaaS platform"
|
||||||
|
export PROJECT_DIR="my-project"
|
||||||
|
export REPO_URL="https://git.mosaicstack.dev/owner/repo"
|
||||||
|
export TASK_PREFIX="MP"
|
||||||
|
|
||||||
|
# Use tech-stack-specific template if available
|
||||||
|
TYPE=$(detect_project_type)
|
||||||
|
TEMPLATE_DIR="$HOME/.config/mosaic/templates/agent/projects/$TYPE"
|
||||||
|
|
||||||
|
if [[ -d "$TEMPLATE_DIR" ]]; then
|
||||||
|
envsubst < "$TEMPLATE_DIR/AGENTS.md.template" > AGENTS.md
|
||||||
|
else
|
||||||
|
envsubst < "$HOME/.config/mosaic/templates/agent/AGENTS.md.template" > AGENTS.md
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using the Generic Template
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set all required variables
|
||||||
|
export PROJECT_NAME="My Project"
|
||||||
|
export PROJECT_DESCRIPTION="What this project does"
|
||||||
|
export REPO_URL="https://git.mosaicstack.dev/owner/repo"
|
||||||
|
export PROJECT_DIR="my-project"
|
||||||
|
export SOURCE_DIR="src"
|
||||||
|
export CONFIG_FILES="pyproject.toml / package.json"
|
||||||
|
export FRONTEND_STACK="N/A"
|
||||||
|
export BACKEND_STACK="Python / FastAPI"
|
||||||
|
export DATABASE_STACK="PostgreSQL"
|
||||||
|
export TESTING_STACK="pytest"
|
||||||
|
export DEPLOYMENT_STACK="Docker"
|
||||||
|
export BUILD_COMMAND="pip install -e ."
|
||||||
|
export TEST_COMMAND="pytest tests/"
|
||||||
|
export LINT_COMMAND="ruff check ."
|
||||||
|
export TYPECHECK_COMMAND="mypy ."
|
||||||
|
export QUALITY_GATES="ruff check . && mypy . && pytest tests/"
|
||||||
|
|
||||||
|
envsubst < ~/.config/mosaic/templates/agent/AGENTS.md.template > AGENTS.md
|
||||||
|
```
|
||||||
|
|
||||||
|
### Required Sections
|
||||||
|
|
||||||
|
Every AGENTS.md should contain:
|
||||||
|
|
||||||
|
1. **Project description** — One-line summary
|
||||||
|
2. **Quality gates** — Commands that must pass
|
||||||
|
3. **Codebase patterns** — Reusable implementation rules
|
||||||
|
4. **Common gotchas** — Non-obvious constraints
|
||||||
|
5. **Testing approaches** — Project-specific test strategy
|
||||||
|
6. **Testing policy** — Situational-first validation and risk-based TDD
|
||||||
|
7. **Orchestrator integration** — Task prefix, worker checklist
|
||||||
|
8. **Documentation contract** — Required documentation gates and update expectations
|
||||||
|
9. **PRD requirement** — `docs/PRD.md` or `docs/PRD.json` required before coding
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 3: Create Runtime Context File (Runtime-Specific)
|
||||||
|
|
||||||
|
Runtime context files are runtime adapters. They are not the primary project contract.
|
||||||
|
Use `CLAUDE.md` for Claude runtime compatibility. Use other runtime adapters as required by your environment.
|
||||||
|
|
||||||
|
Claude runtime mandate (HARD RULE):
|
||||||
|
|
||||||
|
- `CLAUDE.md` MUST explicitly instruct Claude agents to read and use `AGENTS.md`.
|
||||||
|
- `CLAUDE.md` MUST treat `AGENTS.md` as the authoritative project-level contract.
|
||||||
|
- If `AGENTS.md` and runtime wording conflict, `AGENTS.md` project rules win.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
TYPE=$(detect_project_type)
|
||||||
|
TEMPLATE_DIR="$HOME/.config/mosaic/templates/agent/projects/$TYPE"
|
||||||
|
|
||||||
|
if [[ -d "$TEMPLATE_DIR" ]]; then
|
||||||
|
envsubst < "$TEMPLATE_DIR/CLAUDE.md.template" > CLAUDE.md
|
||||||
|
else
|
||||||
|
envsubst < "$HOME/.config/mosaic/templates/agent/CLAUDE.md.template" > CLAUDE.md
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
### Required Runtime Sections
|
||||||
|
|
||||||
|
Every runtime context file should contain:
|
||||||
|
|
||||||
|
1. **AGENTS handoff rule** — Runtime MUST direct agents to read/use `AGENTS.md`
|
||||||
|
2. **Conditional documentation loading** — Required guide loading map
|
||||||
|
3. **Technology stack** — Runtime-facing architecture summary
|
||||||
|
4. **Repository structure** — Important paths
|
||||||
|
5. **Development workflow** — Build/test/lint/typecheck commands
|
||||||
|
6. **Issue tracking** — Issue and commit conventions
|
||||||
|
7. **Code review** — Required review process
|
||||||
|
8. **Runtime notes** — Runtime-specific behavior references
|
||||||
|
9. **Branch and merge policy** — Trunk workflow (`branch -> main` via PR, squash-only)
|
||||||
|
10. **Autonomy and escalation policy** — Agent owns coding/review/PR/release/deploy lifecycle
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 4: Create Directory Structure
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create standard directories
|
||||||
|
mkdir -p docs/scratchpads
|
||||||
|
mkdir -p docs/templates
|
||||||
|
mkdir -p docs/reports/qa-automation/pending
|
||||||
|
mkdir -p docs/reports/qa-automation/in-progress
|
||||||
|
mkdir -p docs/reports/qa-automation/done
|
||||||
|
mkdir -p docs/reports/qa-automation/escalated
|
||||||
|
mkdir -p docs/reports/deferred
|
||||||
|
mkdir -p docs/tasks
|
||||||
|
mkdir -p docs/releases
|
||||||
|
mkdir -p docs/USER-GUIDE docs/ADMIN-GUIDE docs/DEVELOPER-GUIDE docs/API
|
||||||
|
|
||||||
|
# Documentation baseline files
|
||||||
|
touch docs/USER-GUIDE/README.md
|
||||||
|
touch docs/ADMIN-GUIDE/README.md
|
||||||
|
touch docs/DEVELOPER-GUIDE/README.md
|
||||||
|
touch docs/API/OPENAPI.yaml
|
||||||
|
touch docs/API/ENDPOINTS.md
|
||||||
|
touch docs/SITEMAP.md
|
||||||
|
|
||||||
|
# PRD baseline file (requirements source before coding)
|
||||||
|
cp ~/.config/mosaic/templates/docs/PRD.md.template docs/PRD.md
|
||||||
|
|
||||||
|
# TASKS baseline file (canonical tracking)
|
||||||
|
cp ~/.config/mosaic/templates/docs/TASKS.md.template docs/TASKS.md
|
||||||
|
|
||||||
|
# Deployment baseline file (target/platform/runbook)
|
||||||
|
touch docs/DEPLOYMENT.md
|
||||||
|
```
|
||||||
|
|
||||||
|
Documentation root hygiene (HARD RULE):
|
||||||
|
|
||||||
|
- Keep `docs/` root clean.
|
||||||
|
- Store reports in `docs/reports/`, archived task artifacts in `docs/tasks/`, releases in `docs/releases/`, and scratchpads in `docs/scratchpads/`.
|
||||||
|
- Do not place ad-hoc report files directly under `docs/`.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 5: Initialize Repository Labels & Milestones
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Use the init script
|
||||||
|
~/.config/mosaic/rails/bootstrap/init-repo-labels.sh
|
||||||
|
|
||||||
|
# Or manually create standard labels
|
||||||
|
~/.config/mosaic/rails/git/issue-create.sh # (labels are created on first use)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Standard Labels
|
||||||
|
|
||||||
|
| Label | Color | Purpose |
|
||||||
|
|-------|-------|---------|
|
||||||
|
| `epic` | `#3E4B9E` | Large feature spanning multiple issues |
|
||||||
|
| `feature` | `#0E8A16` | New functionality |
|
||||||
|
| `bug` | `#D73A4A` | Defect fix |
|
||||||
|
| `task` | `#0075CA` | General work item |
|
||||||
|
| `documentation` | `#0075CA` | Documentation updates |
|
||||||
|
| `security` | `#B60205` | Security-related |
|
||||||
|
| `breaking` | `#D93F0B` | Breaking change |
|
||||||
|
|
||||||
|
### Initial Milestone (Hard Rule)
|
||||||
|
|
||||||
|
Create the first pre-MVP milestone at `0.0.1`.
|
||||||
|
Reserve `0.1.0` for the MVP release milestone.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/.config/mosaic/rails/git/milestone-create.sh -t "0.0.1" -d "Pre-MVP - Foundation Sprint"
|
||||||
|
|
||||||
|
# Create when MVP scope is complete and release-ready:
|
||||||
|
~/.config/mosaic/rails/git/milestone-create.sh -t "0.1.0" -d "MVP - Minimum Viable Product"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 5b: Configure Main Branch Protection (Hard Rule)
|
||||||
|
|
||||||
|
Apply equivalent settings in Gitea, GitHub, or GitLab:
|
||||||
|
|
||||||
|
1. Protect `main` from direct pushes.
|
||||||
|
2. Require pull requests to merge into `main`.
|
||||||
|
3. Require required CI/status checks to pass before merge.
|
||||||
|
4. Require code review approval before merge.
|
||||||
|
5. Allow **squash merge only** for PRs into `main` (disable merge commits and rebase merges for `main`).
|
||||||
|
|
||||||
|
This enforces one merge strategy across human and agent workflows.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 6: Set Up CI/CD Review Pipeline
|
||||||
|
|
||||||
|
### Woodpecker CI
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Copy Codex review pipeline
|
||||||
|
mkdir -p .woodpecker/schemas
|
||||||
|
cp ~/.config/mosaic/rails/codex/woodpecker/codex-review.yml .woodpecker/
|
||||||
|
cp ~/.config/mosaic/rails/codex/schemas/*.json .woodpecker/schemas/
|
||||||
|
|
||||||
|
# Add codex_api_key secret to Woodpecker CI dashboard
|
||||||
|
```
|
||||||
|
|
||||||
|
### GitHub Actions
|
||||||
|
|
||||||
|
For GitHub repos, use the official Codex GitHub Action instead:
|
||||||
|
```yaml
|
||||||
|
# .github/workflows/codex-review.yml
|
||||||
|
uses: openai/codex-action@v1
|
||||||
|
```
|
||||||
|
|
||||||
|
### Python Package Publishing (Gitea PyPI)
|
||||||
|
|
||||||
|
If the project publishes Python packages, use Gitea's PyPI registry.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build and publish
|
||||||
|
python -m pip install --upgrade build twine
|
||||||
|
python -m build
|
||||||
|
python -m twine upload \
|
||||||
|
--repository-url "https://GITEA_HOST/api/packages/ORG/pypi" \
|
||||||
|
--username "$GITEA_USERNAME" \
|
||||||
|
--password "$GITEA_TOKEN" \
|
||||||
|
dist/*
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the same `gitea_username` and `gitea_token` CI secrets used for container and npm publishing.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 7: Verify Bootstrap
|
||||||
|
|
||||||
|
After bootstrapping, verify everything works:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Check files exist
|
||||||
|
ls AGENTS.md docs/scratchpads/
|
||||||
|
ls docs/reports/qa-automation/pending docs/reports/deferred docs/tasks docs/releases
|
||||||
|
ls docs/USER-GUIDE/README.md docs/ADMIN-GUIDE/README.md docs/DEVELOPER-GUIDE/README.md
|
||||||
|
ls docs/API/OPENAPI.yaml docs/API/ENDPOINTS.md docs/SITEMAP.md
|
||||||
|
ls docs/PRD.md
|
||||||
|
ls docs/TASKS.md
|
||||||
|
|
||||||
|
# Verify AGENTS.md has required sections
|
||||||
|
grep -c "Quality Gates" AGENTS.md
|
||||||
|
grep -c "Orchestrator Integration" AGENTS.md
|
||||||
|
grep -c "Testing Approaches" AGENTS.md
|
||||||
|
grep -c "Testing Policy" AGENTS.md
|
||||||
|
grep -c "Documentation Contract" AGENTS.md
|
||||||
|
grep -c "PRD Requirement" AGENTS.md
|
||||||
|
|
||||||
|
# Verify runtime context file has required sections
|
||||||
|
if [[ -f CLAUDE.md ]]; then
|
||||||
|
grep -c "AGENTS.md" CLAUDE.md
|
||||||
|
grep -c "Conditional Documentation Loading" CLAUDE.md
|
||||||
|
grep -c "Technology Stack" CLAUDE.md
|
||||||
|
grep -c "Code Review" CLAUDE.md
|
||||||
|
elif [[ -f RUNTIME.md ]]; then
|
||||||
|
grep -c "Conditional Documentation Loading" RUNTIME.md
|
||||||
|
grep -c "Technology Stack" RUNTIME.md
|
||||||
|
grep -c "Code Review" RUNTIME.md
|
||||||
|
else
|
||||||
|
echo "Missing runtime context file (CLAUDE.md or RUNTIME.md)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run quality gates from AGENTS.md
|
||||||
|
# (execute the command block under "Quality Gates")
|
||||||
|
|
||||||
|
# Test Codex review (if configured)
|
||||||
|
~/.config/mosaic/rails/codex/codex-code-review.sh --help
|
||||||
|
|
||||||
|
# Verify sequential-thinking MCP remains configured
|
||||||
|
~/.config/mosaic/bin/mosaic-ensure-sequential-thinking --check
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Available Templates
|
||||||
|
|
||||||
|
### Generic Templates
|
||||||
|
|
||||||
|
| Template | Path | Purpose |
|
||||||
|
|----------|------|---------|
|
||||||
|
| `AGENTS.md.template` | `~/.config/mosaic/templates/agent/` | Primary project agent contract |
|
||||||
|
| `CLAUDE.md.template` | `~/.config/mosaic/templates/agent/` | Runtime compatibility context (Claude) |
|
||||||
|
| `DOCUMENTATION-CHECKLIST.md` | `~/.config/mosaic/templates/docs/` | Documentation completion gate |
|
||||||
|
| `PRD.md.template` | `~/.config/mosaic/templates/docs/` | Requirements source template |
|
||||||
|
| `TASKS.md.template` | `~/.config/mosaic/templates/docs/` | Canonical task and issue tracking template |
|
||||||
|
|
||||||
|
### Tech-Stack Templates
|
||||||
|
|
||||||
|
| Stack | Path | Includes |
|
||||||
|
|-------|------|----------|
|
||||||
|
| NestJS + Next.js | `~/.config/mosaic/templates/agent/projects/nestjs-nextjs/` | AGENTS.md + runtime context template |
|
||||||
|
| Django | `~/.config/mosaic/templates/agent/projects/django/` | AGENTS.md + runtime context template |
|
||||||
|
|
||||||
|
### Orchestrator Templates
|
||||||
|
|
||||||
|
| Template | Path | Purpose |
|
||||||
|
|----------|------|---------|
|
||||||
|
| `tasks.md.template` | `~/src/jarvis-brain/docs/templates/orchestrator/` | Task tracking |
|
||||||
|
| `orchestrator-learnings.json.template` | `~/src/jarvis-brain/docs/templates/orchestrator/` | Variance tracking |
|
||||||
|
| `phase-issue-body.md.template` | `~/src/jarvis-brain/docs/templates/orchestrator/` | Git provider issue body |
|
||||||
|
| `scratchpad.md.template` | `~/src/jarvis-brain/docs/templates/` | Per-task working doc |
|
||||||
|
|
||||||
|
### Variables Reference
|
||||||
|
|
||||||
|
| Variable | Description | Example |
|
||||||
|
|----------|-------------|---------|
|
||||||
|
| `${PROJECT_NAME}` | Human-readable project name | "Mosaic Stack" |
|
||||||
|
| `${PROJECT_DESCRIPTION}` | One-line description | "Multi-tenant platform" |
|
||||||
|
| `${PROJECT_DIR}` | Directory name | "mosaic-stack" |
|
||||||
|
| `${PROJECT_SLUG}` | Python package slug | "mosaic_stack" |
|
||||||
|
| `${REPO_URL}` | Git remote URL | "https://git.mosaicstack.dev/mosaic/stack" |
|
||||||
|
| `${TASK_PREFIX}` | Orchestrator task prefix | "MS" |
|
||||||
|
| `${SOURCE_DIR}` | Source code directory | "src" or "apps" |
|
||||||
|
| `${QUALITY_GATES}` | Quality gate commands | "pnpm typecheck && pnpm lint && pnpm test" |
|
||||||
|
| `${BUILD_COMMAND}` | Build command | "pnpm build" |
|
||||||
|
| `${TEST_COMMAND}` | Test command | "pnpm test" |
|
||||||
|
| `${LINT_COMMAND}` | Lint command | "pnpm lint" |
|
||||||
|
| `${TYPECHECK_COMMAND}` | Type check command | "pnpm typecheck" |
|
||||||
|
| `${FRONTEND_STACK}` | Frontend technologies | "Next.js + React" |
|
||||||
|
| `${BACKEND_STACK}` | Backend technologies | "NestJS + Prisma" |
|
||||||
|
| `${DATABASE_STACK}` | Database technologies | "PostgreSQL" |
|
||||||
|
| `${TESTING_STACK}` | Testing technologies | "Vitest + Playwright" |
|
||||||
|
| `${DEPLOYMENT_STACK}` | Deployment technologies | "Docker" |
|
||||||
|
| `${CONFIG_FILES}` | Key config files | "package.json, tsconfig.json" |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bootstrap Scripts
|
||||||
|
|
||||||
|
### init-project.sh
|
||||||
|
|
||||||
|
Full project bootstrap with interactive and flag-based modes:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/.config/mosaic/rails/bootstrap/init-project.sh \
|
||||||
|
--name "My Project" \
|
||||||
|
--type "nestjs-nextjs" \
|
||||||
|
--repo "https://git.mosaicstack.dev/owner/repo" \
|
||||||
|
--prefix "MP" \
|
||||||
|
--description "Multi-tenant platform"
|
||||||
|
```
|
||||||
|
|
||||||
|
### init-repo-labels.sh
|
||||||
|
|
||||||
|
Initialize standard labels and the first pre-MVP milestone:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/.config/mosaic/rails/bootstrap/init-repo-labels.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
After bootstrapping, verify:
|
||||||
|
|
||||||
|
- [ ] `AGENTS.md` exists and is the primary project contract
|
||||||
|
- [ ] Runtime context file exists (`CLAUDE.md` or `RUNTIME.md`)
|
||||||
|
- [ ] `docs/scratchpads/` directory exists
|
||||||
|
- [ ] `docs/reports/qa-automation/pending` directory exists
|
||||||
|
- [ ] `docs/reports/deferred/` directory exists
|
||||||
|
- [ ] `docs/tasks/` directory exists
|
||||||
|
- [ ] `docs/releases/` directory exists
|
||||||
|
- [ ] `docs/USER-GUIDE/README.md` exists
|
||||||
|
- [ ] `docs/ADMIN-GUIDE/README.md` exists
|
||||||
|
- [ ] `docs/DEVELOPER-GUIDE/README.md` exists
|
||||||
|
- [ ] `docs/API/OPENAPI.yaml` exists
|
||||||
|
- [ ] `docs/API/ENDPOINTS.md` exists
|
||||||
|
- [ ] `docs/SITEMAP.md` exists
|
||||||
|
- [ ] `docs/PRD.md` or `docs/PRD.json` exists
|
||||||
|
- [ ] `docs/TASKS.md` exists and is ready for active tracking
|
||||||
|
- [ ] `docs/DEPLOYMENT.md` exists with target platform and rollback notes
|
||||||
|
- [ ] `sequential-thinking` MCP is configured and verification check passes
|
||||||
|
- [ ] Git labels created (epic, feature, bug, task, etc.)
|
||||||
|
- [ ] Initial pre-MVP milestone created (0.0.1)
|
||||||
|
- [ ] MVP milestone reserved for release (0.1.0)
|
||||||
|
- [ ] `main` is protected from direct pushes
|
||||||
|
- [ ] PRs into `main` are required
|
||||||
|
- [ ] Merge method for `main` is squash-only
|
||||||
|
- [ ] Quality gates run successfully
|
||||||
|
- [ ] `.env.example` exists (if project uses env vars)
|
||||||
|
- [ ] CI/CD pipeline configured (if using Woodpecker/GitHub Actions)
|
||||||
|
- [ ] Python publish path configured in CI (if project ships Python packages)
|
||||||
|
- [ ] Codex review scripts accessible (`~/.config/mosaic/rails/codex/`)
|
||||||
40
guides/code-review.md → guides/CODE-REVIEW.md
Normal file → Executable file
40
guides/code-review.md → guides/CODE-REVIEW.md
Normal file → Executable file
@@ -1,9 +1,25 @@
|
|||||||
# Code Review Guide
|
# Code Review Guide
|
||||||
|
|
||||||
|
## Hard Requirement
|
||||||
|
|
||||||
|
If an agent modifies source code, code review is REQUIRED before completion.
|
||||||
|
Do not mark code-change tasks done until review is completed and blockers are resolved or explicitly tracked.
|
||||||
|
If code/config/API contract/auth behavior changed and required docs are missing, this is a BLOCKER.
|
||||||
|
If tests pass but acceptance criteria are not verified by situational evidence, this is a BLOCKER.
|
||||||
|
If implementation diverges from `docs/PRD.md` or `docs/PRD.json` without PRD updates, this is a BLOCKER.
|
||||||
|
|
||||||
|
Merge strategy enforcement (HARD RULE):
|
||||||
|
- PR target for delivery is `main`.
|
||||||
|
- Direct pushes to `main` are prohibited.
|
||||||
|
- Merge to `main` MUST be squash-only.
|
||||||
|
- Use `~/.config/mosaic/rails/git/pr-merge.sh -n {PR_NUMBER} -m squash` (or PowerShell equivalent).
|
||||||
|
|
||||||
## Review Checklist
|
## Review Checklist
|
||||||
|
|
||||||
### 1. Correctness
|
### 1. Correctness
|
||||||
- [ ] Code does what the issue/PR description says
|
- [ ] Code does what the issue/PR description says
|
||||||
|
- [ ] Code aligns with active PRD requirements
|
||||||
|
- [ ] Acceptance criteria are mapped to concrete verification evidence
|
||||||
- [ ] Edge cases are handled
|
- [ ] Edge cases are handled
|
||||||
- [ ] Error conditions are managed properly
|
- [ ] Error conditions are managed properly
|
||||||
- [ ] No obvious bugs or logic errors
|
- [ ] No obvious bugs or logic errors
|
||||||
@@ -17,9 +33,22 @@
|
|||||||
- [ ] Sensitive data not logged
|
- [ ] Sensitive data not logged
|
||||||
- [ ] Secrets follow Vault structure (see `docs/vault-secrets-structure.md`)
|
- [ ] Secrets follow Vault structure (see `docs/vault-secrets-structure.md`)
|
||||||
|
|
||||||
|
### 2a. OWASP Coverage (Required)
|
||||||
|
- [ ] OWASP Top 10 categories were reviewed for change impact
|
||||||
|
- [ ] Access control checks verified on protected actions
|
||||||
|
- [ ] Cryptographic handling validated (keys, hashing, TLS assumptions)
|
||||||
|
- [ ] Injection risks reviewed for all untrusted inputs
|
||||||
|
- [ ] Security misconfiguration risks reviewed (headers, CORS, defaults)
|
||||||
|
- [ ] Dependency/component risk reviewed (known vulnerable components)
|
||||||
|
- [ ] Authentication/session flows reviewed for failure paths
|
||||||
|
- [ ] Logging/monitoring preserves detection without leaking sensitive data
|
||||||
|
|
||||||
### 3. Testing
|
### 3. Testing
|
||||||
- [ ] Tests exist for new functionality
|
- [ ] Tests exist for new functionality
|
||||||
- [ ] Tests cover happy path AND error cases
|
- [ ] Tests cover happy path AND error cases
|
||||||
|
- [ ] Situational tests cover all impacted change surfaces (primary gate)
|
||||||
|
- [ ] Tests validate required behavior/outcomes, not only internal implementation details
|
||||||
|
- [ ] TDD was applied when required by `~/.config/mosaic/guides/QA-TESTING.md`
|
||||||
- [ ] Coverage meets 85% minimum
|
- [ ] Coverage meets 85% minimum
|
||||||
- [ ] Tests are readable and maintainable
|
- [ ] Tests are readable and maintainable
|
||||||
- [ ] No flaky tests introduced
|
- [ ] No flaky tests introduced
|
||||||
@@ -32,7 +61,7 @@
|
|||||||
- [ ] Clear naming for variables and functions
|
- [ ] Clear naming for variables and functions
|
||||||
- [ ] No dead code or commented-out code
|
- [ ] No dead code or commented-out code
|
||||||
|
|
||||||
### 4a. TypeScript Strict Typing (see `typescript.md`)
|
### 4a. TypeScript Strict Typing (see `TYPESCRIPT.md`)
|
||||||
- [ ] **NO `any` types** — explicit types required everywhere
|
- [ ] **NO `any` types** — explicit types required everywhere
|
||||||
- [ ] **NO lazy `unknown`** — only for error catches with immediate narrowing
|
- [ ] **NO lazy `unknown`** — only for error catches with immediate narrowing
|
||||||
- [ ] **Explicit return types** on all exported/public functions
|
- [ ] **Explicit return types** on all exported/public functions
|
||||||
@@ -41,10 +70,16 @@
|
|||||||
- [ ] **No non-null assertions** (`!`) — use proper null handling
|
- [ ] **No non-null assertions** (`!`) — use proper null handling
|
||||||
- [ ] **Interfaces for objects** — not inline types
|
- [ ] **Interfaces for objects** — not inline types
|
||||||
- [ ] **Discriminated unions** for variant types
|
- [ ] **Discriminated unions** for variant types
|
||||||
|
- [ ] **DTO files used at boundaries** — module/API contracts are in `*.dto.ts`, not inline payload types
|
||||||
|
|
||||||
### 5. Documentation
|
### 5. Documentation
|
||||||
- [ ] Complex logic has explanatory comments
|
- [ ] Complex logic has explanatory comments
|
||||||
|
- [ ] Required docs updated per `~/.config/mosaic/guides/DOCUMENTATION.md`
|
||||||
- [ ] Public APIs are documented
|
- [ ] Public APIs are documented
|
||||||
|
- [ ] Private/internal APIs are documented
|
||||||
|
- [ ] API input/output schemas are documented
|
||||||
|
- [ ] API permissions/auth requirements are documented
|
||||||
|
- [ ] Site map updates are present when navigation changed
|
||||||
- [ ] README updated if needed
|
- [ ] README updated if needed
|
||||||
- [ ] Breaking changes noted
|
- [ ] Breaking changes noted
|
||||||
|
|
||||||
@@ -61,6 +96,8 @@
|
|||||||
|
|
||||||
## Review Process
|
## Review Process
|
||||||
|
|
||||||
|
Use `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md` whenever code/API/auth/infra changes are present.
|
||||||
|
|
||||||
### Getting Context
|
### Getting Context
|
||||||
```bash
|
```bash
|
||||||
# List the issue being addressed
|
# List the issue being addressed
|
||||||
@@ -99,3 +136,4 @@ This pattern appears in 3 places. A shared helper would reduce duplication.
|
|||||||
2. If changes requested, assign back to author
|
2. If changes requested, assign back to author
|
||||||
3. If approved, note approval in issue comments
|
3. If approved, note approval in issue comments
|
||||||
4. For merges, ensure CI passes first
|
4. For merges, ensure CI passes first
|
||||||
|
5. Merge PR to `main` with squash strategy only
|
||||||
132
guides/DOCUMENTATION.md
Normal file
132
guides/DOCUMENTATION.md
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# Documentation Standard (MANDATORY)
|
||||||
|
|
||||||
|
This guide defines REQUIRED documentation behavior for all Mosaic projects.
|
||||||
|
If code, API contracts, auth, or infrastructure changes, documentation updates are REQUIRED before completion.
|
||||||
|
|
||||||
|
## Hard Rules
|
||||||
|
|
||||||
|
1. Documentation is a delivery gate. Missing required documentation is a BLOCKER.
|
||||||
|
2. `docs/PRD.md` or `docs/PRD.json` is REQUIRED as the project requirements source before coding begins.
|
||||||
|
3. API documentation is OpenAPI-first. `docs/API/OPENAPI.yaml` (or `.json`) is the canonical API contract.
|
||||||
|
4. Public and private/internal endpoints MUST be documented.
|
||||||
|
5. API input and output schemas MUST be documented.
|
||||||
|
6. API authentication and permissions MUST be documented per endpoint.
|
||||||
|
7. A current site map MUST exist at `docs/SITEMAP.md`.
|
||||||
|
8. Documentation updates MUST be committed in the same logical change set as the code/API change.
|
||||||
|
9. Generated publishing output (Docusaurus/VitePress/MkDocs artifacts) is not canonical unless the project explicitly declares it canonical.
|
||||||
|
10. `docs/` root MUST stay clean. Reports and working artifacts MUST be stored in dedicated subdirectories, not dumped at `docs/` root.
|
||||||
|
|
||||||
|
## Required Documentation Structure
|
||||||
|
|
||||||
|
```text
|
||||||
|
docs/
|
||||||
|
PRD.md (or PRD.json)
|
||||||
|
TASKS.md (active orchestrator tracking, when orchestrator is used)
|
||||||
|
SITEMAP.md
|
||||||
|
USER-GUIDE/
|
||||||
|
ADMIN-GUIDE/
|
||||||
|
DEVELOPER-GUIDE/
|
||||||
|
API/
|
||||||
|
OPENAPI.yaml
|
||||||
|
ENDPOINTS.md
|
||||||
|
scratchpads/
|
||||||
|
reports/
|
||||||
|
tasks/
|
||||||
|
releases/
|
||||||
|
templates/ (optional)
|
||||||
|
```
|
||||||
|
|
||||||
|
Minimum requirements:
|
||||||
|
|
||||||
|
- `docs/PRD.md` or `docs/PRD.json`: authoritative requirements source for implementation and testing.
|
||||||
|
- `docs/USER-GUIDE/`: End-user workflows, feature behavior, common troubleshooting.
|
||||||
|
- `docs/ADMIN-GUIDE/`: Configuration, deployment, operations, incident/recovery procedures.
|
||||||
|
- `docs/DEVELOPER-GUIDE/`: Architecture, local setup, contribution/testing workflow, design constraints.
|
||||||
|
- `docs/API/OPENAPI.yaml`: API SSOT for all HTTP endpoints.
|
||||||
|
- `docs/API/ENDPOINTS.md`: Human-readable index for API endpoints, permissions, and change notes.
|
||||||
|
- `docs/SITEMAP.md`: Navigation index for all user/admin/developer/API documentation pages.
|
||||||
|
- `docs/reports/`: Review outputs, QA automation reports, deferrals, and audit artifacts.
|
||||||
|
- `docs/tasks/`: Archived task snapshots and orchestrator learnings.
|
||||||
|
- `docs/releases/`: Release notes and release-specific documentation.
|
||||||
|
- `docs/scratchpads/`: Active task-level working notes.
|
||||||
|
|
||||||
|
## Root Hygiene Rule (MANDATORY)
|
||||||
|
|
||||||
|
Allowed root documentation files are intentionally limited:
|
||||||
|
|
||||||
|
1. `docs/PRD.md` or `docs/PRD.json`
|
||||||
|
2. `docs/TASKS.md` (active milestone only, when task orchestration is in use)
|
||||||
|
3. `docs/SITEMAP.md`
|
||||||
|
4. `docs/README.md` (optional index)
|
||||||
|
|
||||||
|
All other docs MUST be placed in scoped folders (`docs/reports/`, `docs/tasks/`, `docs/releases/`, `docs/scratchpads/`, `docs/API/`, guide books).
|
||||||
|
|
||||||
|
## Artifact Placement Rules
|
||||||
|
|
||||||
|
| Artifact Type | REQUIRED Location |
|
||||||
|
|---|---|
|
||||||
|
| Code review reports, QA reports, audits | `docs/reports/<category>/` |
|
||||||
|
| Deferred error lists / unresolved findings | `docs/reports/deferred/` |
|
||||||
|
| Archived milestone task snapshots | `docs/tasks/` |
|
||||||
|
| Orchestrator learnings JSON | `docs/tasks/orchestrator-learnings.json` |
|
||||||
|
| Release notes | `docs/releases/` |
|
||||||
|
| Active scratchpads | `docs/scratchpads/` |
|
||||||
|
|
||||||
|
## API Documentation Contract (OpenAPI-First)
|
||||||
|
|
||||||
|
For every API endpoint, documentation MUST include:
|
||||||
|
|
||||||
|
1. visibility: `public` or `private/internal`
|
||||||
|
2. method and path
|
||||||
|
3. endpoint purpose
|
||||||
|
4. request/input schema
|
||||||
|
5. response/output schema(s)
|
||||||
|
6. auth method and required permission/role/scope
|
||||||
|
7. error status codes and behavior
|
||||||
|
|
||||||
|
If OpenAPI cannot fully express an internal constraint, document it in `docs/API/ENDPOINTS.md`.
|
||||||
|
|
||||||
|
## Book/Chapter/Page Structure
|
||||||
|
|
||||||
|
Use this structure for every guide:
|
||||||
|
|
||||||
|
1. Book: one root guide folder (`USER-GUIDE`, `ADMIN-GUIDE`, `DEVELOPER-GUIDE`)
|
||||||
|
2. Chapter: one subdirectory per topic area
|
||||||
|
3. Page: one focused markdown file per concern
|
||||||
|
|
||||||
|
Required index files:
|
||||||
|
|
||||||
|
1. `docs/USER-GUIDE/README.md`
|
||||||
|
2. `docs/ADMIN-GUIDE/README.md`
|
||||||
|
3. `docs/DEVELOPER-GUIDE/README.md`
|
||||||
|
|
||||||
|
Each index file MUST link to all chapters and pages in that book.
|
||||||
|
|
||||||
|
## Situational Documentation Matrix
|
||||||
|
|
||||||
|
| Change Surface | REQUIRED Documentation Updates |
|
||||||
|
|---|---|
|
||||||
|
| New feature or behavior change | User guide + developer guide + sitemap |
|
||||||
|
| API endpoint added/changed/removed | OpenAPI + API endpoint index + sitemap |
|
||||||
|
| Auth/RBAC/permission change | API auth/permission docs + admin guide + developer guide |
|
||||||
|
| Database schema/migration change | Developer guide + admin operational notes if runbook impact |
|
||||||
|
| CI/CD or deployment change | Admin guide + developer guide |
|
||||||
|
| Incident, recovery, or security control change | Admin guide runbook + security notes + sitemap |
|
||||||
|
|
||||||
|
## Publishing Target Rule (MANDATORY)
|
||||||
|
|
||||||
|
If the user does not specify documentation publishing target, the agent MUST ask:
|
||||||
|
|
||||||
|
1. Publish in-app (embedded docs)
|
||||||
|
2. Publish on external docs platform (for example: Docusaurus, VitePress, MkDocs)
|
||||||
|
|
||||||
|
Default behavior before publishing decision:
|
||||||
|
|
||||||
|
- Keep canonical docs in-repo under `docs/`.
|
||||||
|
- Do not assume external publishing platform.
|
||||||
|
|
||||||
|
## Completion Gate
|
||||||
|
|
||||||
|
You MUST NOT declare completion until all required documentation updates are done.
|
||||||
|
|
||||||
|
Use `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md` as the final gate.
|
||||||
@@ -49,12 +49,12 @@ describe('ComponentName', () => {
|
|||||||
|
|
||||||
## Code Style
|
## Code Style
|
||||||
- Follow Google JavaScript/TypeScript Style Guide
|
- Follow Google JavaScript/TypeScript Style Guide
|
||||||
- **TypeScript: Follow `~/.config/mosaic/guides/typescript.md` — MANDATORY**
|
- **TypeScript: Follow `~/.config/mosaic/guides/TYPESCRIPT.md` — MANDATORY**
|
||||||
- Use ESLint/Prettier configuration from project
|
- Use ESLint/Prettier configuration from project
|
||||||
- Prefer functional components over class components (React)
|
- Prefer functional components over class components (React)
|
||||||
- TypeScript strict mode is REQUIRED, not optional
|
- TypeScript strict mode is REQUIRED, not optional
|
||||||
|
|
||||||
### TypeScript Quick Rules (see typescript.md for full guide)
|
### TypeScript Quick Rules (see TYPESCRIPT.md for full guide)
|
||||||
- **NO `any`** — define explicit types always
|
- **NO `any`** — define explicit types always
|
||||||
- **NO lazy `unknown`** — only for error catches and external data with validation
|
- **NO lazy `unknown`** — only for error catches and external data with validation
|
||||||
- **Explicit return types** on all exported functions
|
- **Explicit return types** on all exported functions
|
||||||
@@ -112,6 +112,61 @@ readinessProbe:
|
|||||||
- Implement approval gates for production
|
- Implement approval gates for production
|
||||||
- Audit pipeline access
|
- Audit pipeline access
|
||||||
|
|
||||||
|
## Steered-Autonomous Deployment (Hard Rule)
|
||||||
|
|
||||||
|
In lights-out mode, the agent owns deployment end-to-end when deployment is in scope.
|
||||||
|
The human is escalation-only for missing access, hard policy conflicts, or irreversible risk.
|
||||||
|
|
||||||
|
### Deployment Target Selection
|
||||||
|
|
||||||
|
1. Use explicit target from `docs/PRD.md` / `docs/PRD.json` or `docs/DEPLOYMENT.md`.
|
||||||
|
2. If unspecified, infer from existing project config/integration.
|
||||||
|
3. If multiple targets exist, choose the target already wired in CI/CD and document rationale.
|
||||||
|
|
||||||
|
### Supported Targets
|
||||||
|
|
||||||
|
- **Portainer**: Deploy via configured stack webhook/API, then verify service health and container status.
|
||||||
|
- **Coolify**: Trigger deployment via Coolify API/webhook, then verify deployment status and endpoint health.
|
||||||
|
- **Vercel**: Deploy via `vercel` CLI or connected Git integration, then verify preview/production URL health.
|
||||||
|
- **Other SaaS providers**: Use provider CLI/API/runbook with the same validation and rollback gates.
|
||||||
|
|
||||||
|
### Image Tagging and Promotion (Hard Rule)
|
||||||
|
|
||||||
|
For containerized deployments:
|
||||||
|
|
||||||
|
1. Build immutable image tags: `sha-<shortsha>` and `v{base-version}-rc.{build}`.
|
||||||
|
2. Use mutable environment tags only as pointers: `testing`, optional `staging`, and `prod`.
|
||||||
|
3. Deploy by immutable digest, not by mutable tag alone.
|
||||||
|
4. Promote the exact tested digest between environments (no rebuild between testing and prod).
|
||||||
|
5. Do not use `latest` or `dev` as deployment references.
|
||||||
|
|
||||||
|
Blue-green is the default strategy for production promotion.
|
||||||
|
Canary is allowed only when automated SLO/error-rate gates and auto-rollback triggers are implemented.
|
||||||
|
|
||||||
|
### Post-Deploy Validation (REQUIRED)
|
||||||
|
|
||||||
|
1. Health endpoints return expected status.
|
||||||
|
2. Critical smoke tests pass in target environment.
|
||||||
|
3. Running version and digest match the promoted release candidate.
|
||||||
|
4. Observability signals (errors/latency) are within expected thresholds.
|
||||||
|
|
||||||
|
### Rollback Rule
|
||||||
|
|
||||||
|
If post-deploy validation fails:
|
||||||
|
|
||||||
|
1. Execute rollback/redeploy-safe path immediately.
|
||||||
|
2. Mark deployment as blocked in `docs/TASKS.md`.
|
||||||
|
3. Record failure evidence and next remediation step in scratchpad and release notes.
|
||||||
|
|
||||||
|
### Registry Retention and Cleanup
|
||||||
|
|
||||||
|
Cleanup MUST be automated.
|
||||||
|
|
||||||
|
- Keep all final release tags (`vX.Y.Z`) indefinitely.
|
||||||
|
- Keep active environment digests (`prod`, `testing`, and active blue/green slots).
|
||||||
|
- Keep recent RC tags (`vX.Y.Z-rc.N`) based on retention window.
|
||||||
|
- Remove stale `sha-*` and RC tags outside retention window if they are not actively deployed.
|
||||||
|
|
||||||
## Monitoring & Logging
|
## Monitoring & Logging
|
||||||
|
|
||||||
### Logging Standards
|
### Logging Standards
|
||||||
27
guides/MEMORY.md
Normal file
27
guides/MEMORY.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Memory and Retention Rules
|
||||||
|
|
||||||
|
## Hard Rules
|
||||||
|
|
||||||
|
1. You MUST store learned operational memory in `~/.config/mosaic/memory`.
|
||||||
|
2. You MUST NOT store durable memory in runtime-native memory silos.
|
||||||
|
3. You MUST write concise, reusable learnings that help future agents.
|
||||||
|
4. You MUST track active execution state in project documentation, not ad-hoc text files.
|
||||||
|
|
||||||
|
## Runtime-Native Memory Silos (FORBIDDEN for Durable Memory)
|
||||||
|
|
||||||
|
| Runtime | Native silo (forbidden for durable memory) | Required durable location |
|
||||||
|
|---|---|---|
|
||||||
|
| Claude Code | `~/.claude/projects/*/memory/` | `~/.config/mosaic/memory/` + project `docs/` |
|
||||||
|
| Codex | Runtime session/native memory under `~/.codex/` | `~/.config/mosaic/memory/` + project `docs/` |
|
||||||
|
| OpenCode | Runtime session/native memory under `~/.config/opencode/` | `~/.config/mosaic/memory/` + project `docs/` |
|
||||||
|
|
||||||
|
Treat runtime-native memory as volatile implementation detail. Do not rely on it for long-term project continuity.
|
||||||
|
|
||||||
|
## Project Continuity Files (MANDATORY)
|
||||||
|
|
||||||
|
| File | Purpose | Location |
|
||||||
|
|---|---|---|
|
||||||
|
| `docs/PRD.md` or `docs/PRD.json` | Source of requirements for planning, coding, testing, and review | Project `docs/` |
|
||||||
|
| `docs/TASKS.md` | Canonical tracking for tasks, milestones, issues, status, and blockers | Project `docs/` |
|
||||||
|
| `docs/scratchpads/<task>.md` | Task-specific working memory and verification evidence | Project `docs/scratchpads/` |
|
||||||
|
| `AGENTS.md` | Reusable local patterns and gotchas | Any working directory |
|
||||||
@@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
> Cross-project heuristic adjustments based on observed variance data.
|
> Cross-project heuristic adjustments based on observed variance data.
|
||||||
>
|
>
|
||||||
> **Note:** This file contains generic patterns only. Project-specific evidence is stored in each project's `docs/orchestrator-learnings.json`.
|
> **Note:** This file contains generic patterns only. Project-specific evidence is stored in each project's `docs/tasks/orchestrator-learnings.json`.
|
||||||
|
|
||||||
## Task Type Multipliers
|
## Task Type Multipliers
|
||||||
|
|
||||||
Apply these multipliers to base estimates from `orchestrator.md`:
|
Apply these multipliers to base estimates from `ORCHESTRATOR.md`:
|
||||||
|
|
||||||
| Task Type | Base Estimate | Multiplier | Confidence | Samples | Last Updated |
|
| Task Type | Base Estimate | Multiplier | Confidence | Samples | Last Updated |
|
||||||
|-----------|---------------|------------|------------|---------|--------------|
|
|-----------|---------------|------------|------------|---------|--------------|
|
||||||
@@ -37,7 +37,7 @@ Apply to all estimates based on task position in milestone:
|
|||||||
Final Estimate = Base Estimate × Type Multiplier × Phase Factor × TDD Overhead
|
Final Estimate = Base Estimate × Type Multiplier × Phase Factor × TDD Overhead
|
||||||
|
|
||||||
Where:
|
Where:
|
||||||
- Base Estimate: From orchestrator.md task type table
|
- Base Estimate: From ORCHESTRATOR.md task type table
|
||||||
- Type Multiplier: From table above (default 1.0)
|
- Type Multiplier: From table above (default 1.0)
|
||||||
- Phase Factor: 1.45 / 1.25 / 1.10 based on position
|
- Phase Factor: 1.45 / 1.25 / 1.10 based on position
|
||||||
- TDD Overhead: 1.20 if tests required
|
- TDD Overhead: 1.20 if tests required
|
||||||
@@ -122,5 +122,5 @@ Where:
|
|||||||
|
|
||||||
## Where to Find Project-Specific Data
|
## Where to Find Project-Specific Data
|
||||||
|
|
||||||
- **Project learnings:** `<project>/docs/orchestrator-learnings.json`
|
- **Project learnings:** `<project>/docs/tasks/orchestrator-learnings.json`
|
||||||
- **Cross-project metrics:** `jarvis-brain/data/orchestrator-metrics.json`
|
- **Cross-project metrics:** `jarvis-brain/data/orchestrator-metrics.json`
|
||||||
63
guides/PRD.md
Normal file
63
guides/PRD.md
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
# PRD Requirement Guide (MANDATORY)
|
||||||
|
|
||||||
|
This guide defines how requirements are captured before coding.
|
||||||
|
|
||||||
|
## Hard Rules
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The PRD is the authoritative requirements source for implementation and testing.
|
||||||
|
3. The main agent MUST prepare or update the PRD using user input and available project context before implementation starts.
|
||||||
|
4. The agent MUST NOT invent requirements silently.
|
||||||
|
5. In steered autonomy mode, best-guess decisions are REQUIRED when needed; each guessed decision MUST be marked with `ASSUMPTION:` and rationale.
|
||||||
|
|
||||||
|
## PRD Format
|
||||||
|
|
||||||
|
Allowed canonical formats:
|
||||||
|
|
||||||
|
1. `docs/PRD.md`
|
||||||
|
2. `docs/PRD.json`
|
||||||
|
|
||||||
|
Either format is valid. Both may exist if one is a transformed representation of the other.
|
||||||
|
For markdown PRDs, start from `~/.config/mosaic/templates/docs/PRD.md.template`.
|
||||||
|
|
||||||
|
## Best-Guess Mode
|
||||||
|
|
||||||
|
Steered autonomy is the default operating mode.
|
||||||
|
|
||||||
|
1. Agent SHOULD fill missing decisions in the PRD without waiting for routine confirmation.
|
||||||
|
2. Agent MUST mark each guessed decision with `ASSUMPTION:` and rationale.
|
||||||
|
3. If user explicitly requests strict-confirmation mode, the agent MUST ask before unresolved decisions are finalized.
|
||||||
|
4. For high-impact security/compliance/release uncertainty, escalate only if the decision cannot be safely constrained with rollback-ready defaults.
|
||||||
|
|
||||||
|
## Minimum PRD Content
|
||||||
|
|
||||||
|
Every PRD MUST include:
|
||||||
|
|
||||||
|
1. Problem statement and objective
|
||||||
|
2. In-scope and out-of-scope
|
||||||
|
3. User/stakeholder requirements
|
||||||
|
4. Functional requirements
|
||||||
|
5. Non-functional requirements (security, performance, reliability, observability)
|
||||||
|
6. Acceptance criteria
|
||||||
|
7. Constraints and dependencies
|
||||||
|
8. Risks and open questions
|
||||||
|
9. Testing and verification expectations
|
||||||
|
10. Delivery/milestone intent
|
||||||
|
|
||||||
|
## Pre-Coding Gate
|
||||||
|
|
||||||
|
Coding MUST NOT begin until:
|
||||||
|
|
||||||
|
1. PRD file exists (`docs/PRD.md` or `docs/PRD.json`)
|
||||||
|
2. PRD has required sections
|
||||||
|
3. Unresolved decisions are captured as explicit `ASSUMPTION:` entries with rationale and planned validation
|
||||||
|
|
||||||
|
## Change Control
|
||||||
|
|
||||||
|
When requirements materially change:
|
||||||
|
|
||||||
|
1. Update PRD first.
|
||||||
|
2. Then update implementation plan/tasks.
|
||||||
|
3. Then implement code changes.
|
||||||
|
|
||||||
|
Implementation that diverges from PRD without PRD updates is a blocker.
|
||||||
114
guides/QA-TESTING.md
Normal file
114
guides/QA-TESTING.md
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
# QA & Testing Guide
|
||||||
|
|
||||||
|
## Before Starting
|
||||||
|
|
||||||
|
1. Check assigned issue: `~/.config/mosaic/rails/git/issue-list.sh -a @me`
|
||||||
|
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
|
||||||
|
3. Review `docs/PRD.md` or `docs/PRD.json` as the requirements source.
|
||||||
|
4. Review acceptance criteria and affected change surfaces.
|
||||||
|
|
||||||
|
## Testing Policy (Hard Rules)
|
||||||
|
|
||||||
|
1. Situational testing is the PRIMARY validation gate.
|
||||||
|
2. Baseline testing is REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based and REQUIRED only for defined high-risk change types.
|
||||||
|
4. Tests MUST validate requirements and behavior, not only internal implementation details.
|
||||||
|
|
||||||
|
## Priority Order
|
||||||
|
|
||||||
|
1. Situational tests: prove requirements and real behavior on changed surfaces.
|
||||||
|
2. Baseline tests: lint/type/unit/integration safety checks.
|
||||||
|
3. TDD discipline: applied where risk justifies test-first workflow.
|
||||||
|
|
||||||
|
## Risk-Based TDD Requirement
|
||||||
|
|
||||||
|
| Change Type | TDD Requirement | Required Action |
|
||||||
|
|---|---|---|
|
||||||
|
| Bug fix | REQUIRED | Write a failing reproducer test first, then fix. |
|
||||||
|
| Security/auth/permission logic | REQUIRED | Write failing security/permission-path test first. |
|
||||||
|
| Critical business logic or data mutation rules | REQUIRED | Write failing rule/invariant test first. |
|
||||||
|
| API behavior regression | REQUIRED | Write failing contract/behavior test first. |
|
||||||
|
| Low-risk UI copy/style/layout | OPTIONAL | Add verification tests as appropriate; TDD recommended, not mandatory. |
|
||||||
|
| Mechanical refactor with unchanged behavior | OPTIONAL | Ensure regression/smoke coverage and situational evidence. |
|
||||||
|
|
||||||
|
If TDD is not required and skipped, record rationale in scratchpad.
|
||||||
|
If TDD is required and skipped, task is NOT complete.
|
||||||
|
|
||||||
|
## Baseline Test Requirements
|
||||||
|
|
||||||
|
For all software changes, run baseline checks applicable to the repo:
|
||||||
|
|
||||||
|
1. lint/static checks
|
||||||
|
2. type checks
|
||||||
|
3. unit tests for changed logic
|
||||||
|
4. integration tests for changed boundaries
|
||||||
|
|
||||||
|
## Situational Testing Matrix (Primary Gate)
|
||||||
|
|
||||||
|
| Change Surface | Required Situational Tests |
|
||||||
|
|---|---|
|
||||||
|
| Authentication/authorization | auth failure-path tests, permission boundary tests, token/session validation |
|
||||||
|
| Database schema/migrations | migration up/down validation, rollback safety, data integrity checks |
|
||||||
|
| API contract changes | backward compatibility checks, consumer-impact tests, contract tests |
|
||||||
|
| Frontend/UI workflow changes | end-to-end flow tests, accessibility sanity checks, state transition checks |
|
||||||
|
| CI/CD or deployment changes | pipeline execution validation, artifact integrity checks, rollback path check |
|
||||||
|
| Security-sensitive logic | abuse-case tests, input validation fuzzing/sanitization checks |
|
||||||
|
| Performance-critical path | baseline comparison, regression threshold checks |
|
||||||
|
|
||||||
|
## Coverage Requirements
|
||||||
|
|
||||||
|
### Minimum Standards
|
||||||
|
|
||||||
|
- Overall Coverage: 85% minimum
|
||||||
|
- Critical Paths: 95% minimum (auth, payments, data mutations)
|
||||||
|
- New Code: 90% minimum
|
||||||
|
|
||||||
|
Coverage is necessary but NOT sufficient. Passing coverage does not replace situational verification.
|
||||||
|
|
||||||
|
## Requirements-to-Evidence Mapping (Mandatory)
|
||||||
|
|
||||||
|
Before completion, map each acceptance criterion to concrete evidence.
|
||||||
|
Acceptance criteria MUST come from the active PRD.
|
||||||
|
|
||||||
|
Template:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
| Acceptance Criterion | Verification Method | Evidence |
|
||||||
|
|---|---|---|
|
||||||
|
| AC-1: ... | Situational test / baseline test / manual verification | command + result |
|
||||||
|
| AC-2: ... | ... | ... |
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Quality Rules
|
||||||
|
|
||||||
|
1. Test behavior and outcomes, not private implementation details.
|
||||||
|
2. Include failure-path and edge-case assertions for changed behavior.
|
||||||
|
3. Keep tests deterministic; no new flaky tests.
|
||||||
|
4. Keep tests isolated; no dependency on execution order.
|
||||||
|
|
||||||
|
## Anti-Gaming Rules
|
||||||
|
|
||||||
|
1. Do NOT stop at "tests pass" if acceptance criteria are not verified.
|
||||||
|
2. Do NOT write narrow tests that only satisfy assertions while missing real workflow behavior.
|
||||||
|
3. Do NOT claim completion without situational evidence for impacted surfaces.
|
||||||
|
|
||||||
|
## Reporting
|
||||||
|
|
||||||
|
QA report MUST include:
|
||||||
|
|
||||||
|
1. baseline tests run and outcomes
|
||||||
|
2. situational tests run and outcomes
|
||||||
|
3. TDD usage decision (required/applied or optional/skipped with rationale)
|
||||||
|
4. acceptance-criteria-to-evidence mapping
|
||||||
|
5. coverage results
|
||||||
|
6. residual risk notes
|
||||||
|
|
||||||
|
## Before Completing
|
||||||
|
|
||||||
|
1. Baseline tests pass.
|
||||||
|
2. Required situational tests pass.
|
||||||
|
3. TDD obligations met for required change types.
|
||||||
|
4. Acceptance criteria mapped to evidence.
|
||||||
|
5. No flaky tests introduced.
|
||||||
|
6. CI pipeline passes (if available).
|
||||||
|
7. Scratchpad updated with results.
|
||||||
@@ -11,6 +11,44 @@ Based on Google TypeScript Style Guide with stricter enforcement.
|
|||||||
1. **Explicit over implicit** — Always declare types, never rely on inference for public APIs
|
1. **Explicit over implicit** — Always declare types, never rely on inference for public APIs
|
||||||
2. **Specific over generic** — Use the narrowest type that works
|
2. **Specific over generic** — Use the narrowest type that works
|
||||||
3. **Safe over convenient** — Type safety is not negotiable
|
3. **Safe over convenient** — Type safety is not negotiable
|
||||||
|
4. **Contract-first boundaries** — Cross-module and API payloads MUST use dedicated DTO files
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## DTO Contract (MANDATORY)
|
||||||
|
|
||||||
|
DTO files are REQUIRED for TypeScript module boundaries to preserve shared context and consistency.
|
||||||
|
|
||||||
|
Hard requirements:
|
||||||
|
|
||||||
|
1. Input and output payloads crossing module boundaries MUST be defined in `*.dto.ts` files.
|
||||||
|
2. Controller/service boundary payloads MUST use DTO types; inline object literal types are NOT allowed.
|
||||||
|
3. Public API request/response contracts MUST use DTO files and remain stable across modules.
|
||||||
|
4. Shared DTOs used by multiple modules MUST live in a shared location (for example `src/shared/dto/` or `packages/shared/dto/`).
|
||||||
|
5. ORM/entity models MUST NOT be exposed directly across module boundaries; map them to DTOs.
|
||||||
|
6. DTO changes MUST be reflected in tests and documentation when contracts change.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ❌ WRONG: inline payload contract at boundary
|
||||||
|
export function createUser(payload: { email: string; role: string }): Promise<User> { }
|
||||||
|
|
||||||
|
// ✅ CORRECT: dedicated DTO file contract
|
||||||
|
// user-create.dto.ts
|
||||||
|
export interface UserCreateDto {
|
||||||
|
email: string;
|
||||||
|
role: UserRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
// user-response.dto.ts
|
||||||
|
export interface UserResponseDto {
|
||||||
|
id: string;
|
||||||
|
email: string;
|
||||||
|
role: UserRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
// service.ts
|
||||||
|
export function createUser(payload: UserCreateDto): Promise<UserResponseDto> { }
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -1,338 +0,0 @@
|
|||||||
# Project Bootstrap Guide
|
|
||||||
|
|
||||||
> Load this guide when setting up a new project for AI-assisted development.
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
This guide covers how to bootstrap a project so AI agents (Claude, Codex, etc.) can work on it effectively. Proper bootstrapping ensures:
|
|
||||||
|
|
||||||
1. Agents understand the project structure and conventions
|
|
||||||
2. Orchestration works correctly with quality gates
|
|
||||||
3. Independent code review and security review are configured
|
|
||||||
4. Issue tracking is consistent across projects
|
|
||||||
|
|
||||||
## Quick Start
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Automated bootstrap (recommended)
|
|
||||||
~/.config/mosaic/rails/bootstrap/init-project.sh \
|
|
||||||
--name "my-project" \
|
|
||||||
--type "nestjs-nextjs" \
|
|
||||||
--repo "https://git.mosaicstack.dev/owner/repo"
|
|
||||||
|
|
||||||
# Or manually using templates
|
|
||||||
export PROJECT_NAME="My Project"
|
|
||||||
export PROJECT_DESCRIPTION="What this project does"
|
|
||||||
export TASK_PREFIX="MP"
|
|
||||||
envsubst < ~/.config/mosaic/templates/agent/CLAUDE.md.template > CLAUDE.md
|
|
||||||
envsubst < ~/.config/mosaic/templates/agent/AGENTS.md.template > AGENTS.md
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 1: Detect Project Type
|
|
||||||
|
|
||||||
Check what files exist in the project root to determine the type:
|
|
||||||
|
|
||||||
| File Present | Project Type | Template |
|
|
||||||
|---|---|---|
|
|
||||||
| `package.json` + `pnpm-workspace.yaml` + NestJS+Next.js | NestJS + Next.js Monorepo | `projects/nestjs-nextjs/` |
|
|
||||||
| `pyproject.toml` + `manage.py` | Django | `projects/django/` |
|
|
||||||
| `pyproject.toml` (no Django) | Python (generic) | Generic template |
|
|
||||||
| `package.json` (no monorepo) | Node.js (generic) | Generic template |
|
|
||||||
| Other | Generic | Generic template |
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Auto-detect project type
|
|
||||||
detect_project_type() {
|
|
||||||
if [[ -f "pnpm-workspace.yaml" ]] && [[ -f "turbo.json" ]]; then
|
|
||||||
# Check for NestJS + Next.js
|
|
||||||
if grep -q "nestjs" package.json 2>/dev/null && grep -q "next" package.json 2>/dev/null; then
|
|
||||||
echo "nestjs-nextjs"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [[ -f "manage.py" ]] && [[ -f "pyproject.toml" ]]; then
|
|
||||||
echo "django"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
if [[ -f "pyproject.toml" ]]; then
|
|
||||||
echo "python"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
if [[ -f "package.json" ]]; then
|
|
||||||
echo "nodejs"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
echo "generic"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 2: Create CLAUDE.md
|
|
||||||
|
|
||||||
The `CLAUDE.md` file is the primary configuration file for AI agents. It tells them everything they need to know about the project.
|
|
||||||
|
|
||||||
### Using a Tech-Stack Template
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Set variables
|
|
||||||
export PROJECT_NAME="My Project"
|
|
||||||
export PROJECT_DESCRIPTION="Multi-tenant SaaS platform"
|
|
||||||
export PROJECT_DIR="my-project"
|
|
||||||
export REPO_URL="https://git.mosaicstack.dev/owner/repo"
|
|
||||||
export TASK_PREFIX="MP"
|
|
||||||
|
|
||||||
# Use tech-stack-specific template if available
|
|
||||||
TYPE=$(detect_project_type)
|
|
||||||
TEMPLATE_DIR="$HOME/.config/mosaic/templates/agent/projects/$TYPE"
|
|
||||||
|
|
||||||
if [[ -d "$TEMPLATE_DIR" ]]; then
|
|
||||||
envsubst < "$TEMPLATE_DIR/CLAUDE.md.template" > CLAUDE.md
|
|
||||||
else
|
|
||||||
envsubst < "$HOME/.config/mosaic/templates/agent/CLAUDE.md.template" > CLAUDE.md
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using the Generic Template
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Set all required variables
|
|
||||||
export PROJECT_NAME="My Project"
|
|
||||||
export PROJECT_DESCRIPTION="What this project does"
|
|
||||||
export REPO_URL="https://git.mosaicstack.dev/owner/repo"
|
|
||||||
export PROJECT_DIR="my-project"
|
|
||||||
export SOURCE_DIR="src"
|
|
||||||
export CONFIG_FILES="pyproject.toml / package.json"
|
|
||||||
export FRONTEND_STACK="N/A"
|
|
||||||
export BACKEND_STACK="Python / FastAPI"
|
|
||||||
export DATABASE_STACK="PostgreSQL"
|
|
||||||
export TESTING_STACK="pytest"
|
|
||||||
export DEPLOYMENT_STACK="Docker"
|
|
||||||
export BUILD_COMMAND="pip install -e ."
|
|
||||||
export TEST_COMMAND="pytest tests/"
|
|
||||||
export LINT_COMMAND="ruff check ."
|
|
||||||
export TYPECHECK_COMMAND="mypy ."
|
|
||||||
export QUALITY_GATES="ruff check . && mypy . && pytest tests/"
|
|
||||||
|
|
||||||
envsubst < ~/.config/mosaic/templates/agent/CLAUDE.md.template > CLAUDE.md
|
|
||||||
```
|
|
||||||
|
|
||||||
### Required Sections
|
|
||||||
|
|
||||||
Every CLAUDE.md should contain:
|
|
||||||
|
|
||||||
1. **Project description** — One-line summary
|
|
||||||
2. **Conditional documentation loading** — Table of guides
|
|
||||||
3. **Technology stack** — What's used
|
|
||||||
4. **Repository structure** — Directory tree
|
|
||||||
5. **Development workflow** — Branch strategy, build, test
|
|
||||||
6. **Quality gates** — Commands that must pass
|
|
||||||
7. **Issue tracking** — Commit format, labels
|
|
||||||
8. **Code review** — Codex and fallback review commands
|
|
||||||
9. **Secrets management** — How secrets are handled
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 3: Create AGENTS.md
|
|
||||||
|
|
||||||
The `AGENTS.md` file contains agent-specific patterns, gotchas, and orchestrator integration details.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
TYPE=$(detect_project_type)
|
|
||||||
TEMPLATE_DIR="$HOME/.config/mosaic/templates/agent/projects/$TYPE"
|
|
||||||
|
|
||||||
if [[ -d "$TEMPLATE_DIR" ]]; then
|
|
||||||
envsubst < "$TEMPLATE_DIR/AGENTS.md.template" > AGENTS.md
|
|
||||||
else
|
|
||||||
envsubst < "$HOME/.config/mosaic/templates/agent/AGENTS.md.template" > AGENTS.md
|
|
||||||
fi
|
|
||||||
```
|
|
||||||
|
|
||||||
### Living Document
|
|
||||||
|
|
||||||
AGENTS.md is a **living document**. Agents should update it when they discover:
|
|
||||||
- Reusable patterns (how similar features are built)
|
|
||||||
- Non-obvious requirements (e.g., "frontend env vars need NEXT_PUBLIC_ prefix")
|
|
||||||
- Common gotchas (e.g., "run migrations after schema changes")
|
|
||||||
- Testing approaches specific to this project
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 4: Create Directory Structure
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Create standard directories
|
|
||||||
mkdir -p docs/scratchpads
|
|
||||||
mkdir -p docs/templates
|
|
||||||
mkdir -p docs/reports
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 5: Initialize Repository Labels & Milestones
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Use the init script
|
|
||||||
~/.config/mosaic/rails/bootstrap/init-repo-labels.sh
|
|
||||||
|
|
||||||
# Or manually create standard labels
|
|
||||||
~/.config/mosaic/rails/git/issue-create.sh # (labels are created on first use)
|
|
||||||
```
|
|
||||||
|
|
||||||
### Standard Labels
|
|
||||||
|
|
||||||
| Label | Color | Purpose |
|
|
||||||
|-------|-------|---------|
|
|
||||||
| `epic` | `#3E4B9E` | Large feature spanning multiple issues |
|
|
||||||
| `feature` | `#0E8A16` | New functionality |
|
|
||||||
| `bug` | `#D73A4A` | Defect fix |
|
|
||||||
| `task` | `#0075CA` | General work item |
|
|
||||||
| `documentation` | `#0075CA` | Documentation updates |
|
|
||||||
| `security` | `#B60205` | Security-related |
|
|
||||||
| `breaking` | `#D93F0B` | Breaking change |
|
|
||||||
|
|
||||||
### Initial Milestone
|
|
||||||
|
|
||||||
Create the first milestone for MVP:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
~/.config/mosaic/rails/git/milestone-create.sh -t "0.1.0" -d "MVP - Minimum Viable Product"
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 6: Set Up CI/CD Review Pipeline
|
|
||||||
|
|
||||||
### Woodpecker CI
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Copy Codex review pipeline
|
|
||||||
mkdir -p .woodpecker/schemas
|
|
||||||
cp ~/.config/mosaic/rails/codex/woodpecker/codex-review.yml .woodpecker/
|
|
||||||
cp ~/.config/mosaic/rails/codex/schemas/*.json .woodpecker/schemas/
|
|
||||||
|
|
||||||
# Add codex_api_key secret to Woodpecker CI dashboard
|
|
||||||
```
|
|
||||||
|
|
||||||
### GitHub Actions
|
|
||||||
|
|
||||||
For GitHub repos, use the official Codex GitHub Action instead:
|
|
||||||
```yaml
|
|
||||||
# .github/workflows/codex-review.yml
|
|
||||||
uses: openai/codex-action@v1
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Step 7: Verify Bootstrap
|
|
||||||
|
|
||||||
After bootstrapping, verify everything works:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Check files exist
|
|
||||||
ls CLAUDE.md AGENTS.md docs/scratchpads/
|
|
||||||
|
|
||||||
# Verify CLAUDE.md has required sections
|
|
||||||
grep -c "Quality Gates" CLAUDE.md
|
|
||||||
grep -c "Technology Stack" CLAUDE.md
|
|
||||||
grep -c "Code Review" CLAUDE.md
|
|
||||||
|
|
||||||
# Verify quality gates run
|
|
||||||
eval "$(grep -A1 'Quality Gates' CLAUDE.md | tail -1)"
|
|
||||||
|
|
||||||
# Test Codex review (if configured)
|
|
||||||
~/.config/mosaic/rails/codex/codex-code-review.sh --help
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Available Templates
|
|
||||||
|
|
||||||
### Generic Templates
|
|
||||||
|
|
||||||
| Template | Path | Purpose |
|
|
||||||
|----------|------|---------|
|
|
||||||
| `CLAUDE.md.template` | `~/.config/mosaic/templates/agent/` | Generic project CLAUDE.md |
|
|
||||||
| `AGENTS.md.template` | `~/.config/mosaic/templates/agent/` | Generic agent context |
|
|
||||||
|
|
||||||
### Tech-Stack Templates
|
|
||||||
|
|
||||||
| Stack | Path | Includes |
|
|
||||||
|-------|------|----------|
|
|
||||||
| NestJS + Next.js | `~/.config/mosaic/templates/agent/projects/nestjs-nextjs/` | CLAUDE.md, AGENTS.md |
|
|
||||||
| Django | `~/.config/mosaic/templates/agent/projects/django/` | CLAUDE.md, AGENTS.md |
|
|
||||||
|
|
||||||
### Orchestrator Templates
|
|
||||||
|
|
||||||
| Template | Path | Purpose |
|
|
||||||
|----------|------|---------|
|
|
||||||
| `tasks.md.template` | `~/src/jarvis-brain/docs/templates/orchestrator/` | Task tracking |
|
|
||||||
| `orchestrator-learnings.json.template` | `~/src/jarvis-brain/docs/templates/orchestrator/` | Variance tracking |
|
|
||||||
| `phase-issue-body.md.template` | `~/src/jarvis-brain/docs/templates/orchestrator/` | Gitea issue body |
|
|
||||||
| `scratchpad.md.template` | `~/src/jarvis-brain/docs/templates/` | Per-task working doc |
|
|
||||||
|
|
||||||
### Variables Reference
|
|
||||||
|
|
||||||
| Variable | Description | Example |
|
|
||||||
|----------|-------------|---------|
|
|
||||||
| `${PROJECT_NAME}` | Human-readable project name | "Mosaic Stack" |
|
|
||||||
| `${PROJECT_DESCRIPTION}` | One-line description | "Multi-tenant platform" |
|
|
||||||
| `${PROJECT_DIR}` | Directory name | "mosaic-stack" |
|
|
||||||
| `${PROJECT_SLUG}` | Python package slug | "mosaic_stack" |
|
|
||||||
| `${REPO_URL}` | Git remote URL | "https://git.mosaicstack.dev/mosaic/stack" |
|
|
||||||
| `${TASK_PREFIX}` | Orchestrator task prefix | "MS" |
|
|
||||||
| `${SOURCE_DIR}` | Source code directory | "src" or "apps" |
|
|
||||||
| `${QUALITY_GATES}` | Quality gate commands | "pnpm typecheck && pnpm lint && pnpm test" |
|
|
||||||
| `${BUILD_COMMAND}` | Build command | "pnpm build" |
|
|
||||||
| `${TEST_COMMAND}` | Test command | "pnpm test" |
|
|
||||||
| `${LINT_COMMAND}` | Lint command | "pnpm lint" |
|
|
||||||
| `${TYPECHECK_COMMAND}` | Type check command | "pnpm typecheck" |
|
|
||||||
| `${FRONTEND_STACK}` | Frontend technologies | "Next.js + React" |
|
|
||||||
| `${BACKEND_STACK}` | Backend technologies | "NestJS + Prisma" |
|
|
||||||
| `${DATABASE_STACK}` | Database technologies | "PostgreSQL" |
|
|
||||||
| `${TESTING_STACK}` | Testing technologies | "Vitest + Playwright" |
|
|
||||||
| `${DEPLOYMENT_STACK}` | Deployment technologies | "Docker" |
|
|
||||||
| `${CONFIG_FILES}` | Key config files | "package.json, tsconfig.json" |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Bootstrap Scripts
|
|
||||||
|
|
||||||
### init-project.sh
|
|
||||||
|
|
||||||
Full project bootstrap with interactive and flag-based modes:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
~/.config/mosaic/rails/bootstrap/init-project.sh \
|
|
||||||
--name "My Project" \
|
|
||||||
--type "nestjs-nextjs" \
|
|
||||||
--repo "https://git.mosaicstack.dev/owner/repo" \
|
|
||||||
--prefix "MP" \
|
|
||||||
--description "Multi-tenant platform"
|
|
||||||
```
|
|
||||||
|
|
||||||
### init-repo-labels.sh
|
|
||||||
|
|
||||||
Initialize standard labels and MVP milestone:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
~/.config/mosaic/rails/bootstrap/init-repo-labels.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Checklist
|
|
||||||
|
|
||||||
After bootstrapping, verify:
|
|
||||||
|
|
||||||
- [ ] `CLAUDE.md` exists with all required sections
|
|
||||||
- [ ] `AGENTS.md` exists with patterns and quality gates
|
|
||||||
- [ ] `docs/scratchpads/` directory exists
|
|
||||||
- [ ] Git labels created (epic, feature, bug, task, etc.)
|
|
||||||
- [ ] Initial milestone created (0.1.0 MVP)
|
|
||||||
- [ ] Quality gates run successfully
|
|
||||||
- [ ] `.env.example` exists (if project uses env vars)
|
|
||||||
- [ ] CI/CD pipeline configured (if using Woodpecker/GitHub Actions)
|
|
||||||
- [ ] Codex review scripts accessible (`~/.config/mosaic/rails/codex/`)
|
|
||||||
@@ -12,7 +12,7 @@ GIT PUSH
|
|||||||
QUALITY GATES (lint, typecheck, test, audit)
|
QUALITY GATES (lint, typecheck, test, audit)
|
||||||
↓ all pass
|
↓ all pass
|
||||||
BUILD (compile all packages)
|
BUILD (compile all packages)
|
||||||
↓ only on main/develop/tags
|
↓ only on main/tags
|
||||||
DOCKER BUILD & PUSH (Kaniko → Gitea Container Registry)
|
DOCKER BUILD & PUSH (Kaniko → Gitea Container Registry)
|
||||||
↓ all images pushed
|
↓ all images pushed
|
||||||
PACKAGE LINKING (associate images with repository in Gitea)
|
PACKAGE LINKING (associate images with repository in Gitea)
|
||||||
@@ -123,10 +123,10 @@ when:
|
|||||||
# Top-level: run quality gates on everything
|
# Top-level: run quality gates on everything
|
||||||
- event: [push, pull_request, manual]
|
- event: [push, pull_request, manual]
|
||||||
|
|
||||||
# Per-step: only build Docker images on main/develop/tags
|
# Per-step: only build Docker images on main/tags
|
||||||
docker-build-api:
|
docker-build-api:
|
||||||
when:
|
when:
|
||||||
- branch: [main, develop]
|
- branch: [main]
|
||||||
event: [push, manual, tag]
|
event: [push, manual, tag]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -150,24 +150,29 @@ docker-build-SERVICE:
|
|||||||
from_secret: gitea_username
|
from_secret: gitea_username
|
||||||
GITEA_TOKEN:
|
GITEA_TOKEN:
|
||||||
from_secret: gitea_token
|
from_secret: gitea_token
|
||||||
|
RELEASE_BASE_VERSION: ${RELEASE_BASE_VERSION}
|
||||||
CI_COMMIT_BRANCH: ${CI_COMMIT_BRANCH}
|
CI_COMMIT_BRANCH: ${CI_COMMIT_BRANCH}
|
||||||
CI_COMMIT_TAG: ${CI_COMMIT_TAG}
|
CI_COMMIT_TAG: ${CI_COMMIT_TAG}
|
||||||
CI_COMMIT_SHA: ${CI_COMMIT_SHA}
|
CI_COMMIT_SHA: ${CI_COMMIT_SHA}
|
||||||
|
CI_PIPELINE_NUMBER: ${CI_PIPELINE_NUMBER}
|
||||||
commands:
|
commands:
|
||||||
- *kaniko_setup
|
- *kaniko_setup
|
||||||
- |
|
- |
|
||||||
DESTINATIONS="--destination REGISTRY/ORG/IMAGE_NAME:${CI_COMMIT_SHA:0:8}"
|
SHORT_SHA="${CI_COMMIT_SHA:0:8}"
|
||||||
|
BUILD_ID="${CI_PIPELINE_NUMBER:-$SHORT_SHA}"
|
||||||
|
BASE_VERSION="${RELEASE_BASE_VERSION:?RELEASE_BASE_VERSION is required (example: 0.0.1)}"
|
||||||
|
|
||||||
|
DESTINATIONS="--destination REGISTRY/ORG/IMAGE_NAME:sha-$SHORT_SHA"
|
||||||
if [ "$CI_COMMIT_BRANCH" = "main" ]; then
|
if [ "$CI_COMMIT_BRANCH" = "main" ]; then
|
||||||
DESTINATIONS="$DESTINATIONS --destination REGISTRY/ORG/IMAGE_NAME:latest"
|
DESTINATIONS="$DESTINATIONS --destination REGISTRY/ORG/IMAGE_NAME:v${BASE_VERSION}-rc.${BUILD_ID}"
|
||||||
elif [ "$CI_COMMIT_BRANCH" = "develop" ]; then
|
DESTINATIONS="$DESTINATIONS --destination REGISTRY/ORG/IMAGE_NAME:testing"
|
||||||
DESTINATIONS="$DESTINATIONS --destination REGISTRY/ORG/IMAGE_NAME:dev"
|
|
||||||
fi
|
fi
|
||||||
if [ -n "$CI_COMMIT_TAG" ]; then
|
if [ -n "$CI_COMMIT_TAG" ]; then
|
||||||
DESTINATIONS="$DESTINATIONS --destination REGISTRY/ORG/IMAGE_NAME:$CI_COMMIT_TAG"
|
DESTINATIONS="$DESTINATIONS --destination REGISTRY/ORG/IMAGE_NAME:$CI_COMMIT_TAG"
|
||||||
fi
|
fi
|
||||||
/kaniko/executor --context . --dockerfile PATH/TO/Dockerfile $DESTINATIONS
|
/kaniko/executor --context . --dockerfile PATH/TO/Dockerfile $DESTINATIONS
|
||||||
when:
|
when:
|
||||||
- branch: [main, develop]
|
- branch: [main]
|
||||||
event: [push, manual, tag]
|
event: [push, manual, tag]
|
||||||
depends_on:
|
depends_on:
|
||||||
- build
|
- build
|
||||||
@@ -184,15 +189,69 @@ docker-build-SERVICE:
|
|||||||
|
|
||||||
### Image Tagging Strategy
|
### Image Tagging Strategy
|
||||||
|
|
||||||
Every build produces multiple tags:
|
Tagging MUST follow a two-layer model: immutable identity tags + mutable environment tags.
|
||||||
|
|
||||||
|
Immutable tags:
|
||||||
|
|
||||||
| Condition | Tag | Purpose |
|
| Condition | Tag | Purpose |
|
||||||
|-----------|-----|---------|
|
|-----------|-----|---------|
|
||||||
| Always | `${CI_COMMIT_SHA:0:8}` | Immutable reference to exact commit |
|
| Always | `sha-${CI_COMMIT_SHA:0:8}` | Immutable reference to exact commit |
|
||||||
| `main` branch | `latest` | Current production release |
|
| `main` branch | `v{BASE_VERSION}-rc.{BUILD_ID}` | Intermediate release candidate for the active milestone |
|
||||||
| `develop` branch | `dev` | Current development build |
|
|
||||||
| Git tag (e.g., `v1.0.0`) | `v1.0.0` | Semantic version release |
|
| Git tag (e.g., `v1.0.0`) | `v1.0.0` | Semantic version release |
|
||||||
|
|
||||||
|
Mutable environment tags:
|
||||||
|
|
||||||
|
| Tag | Purpose |
|
||||||
|
|-----|---------|
|
||||||
|
| `testing` | Current candidate under situational validation |
|
||||||
|
| `staging` (optional) | Pre-production validation target |
|
||||||
|
| `prod` | Current production pointer |
|
||||||
|
|
||||||
|
Hard rules:
|
||||||
|
- Do NOT use `latest` for deployment.
|
||||||
|
- Do NOT use `dev` as the primary deployment tag.
|
||||||
|
- Deployments MUST resolve to an immutable image digest.
|
||||||
|
|
||||||
|
### Digest-First Promotion (Hard Rule)
|
||||||
|
|
||||||
|
Deploy and promote by digest, not by mutable tag:
|
||||||
|
|
||||||
|
1. Build and push candidate tags (`sha-*`, `vX.Y.Z-rc.N`, `testing`).
|
||||||
|
2. Resolve the digest from `sha-*` tag.
|
||||||
|
3. Deploy that digest to testing and run situational tests.
|
||||||
|
4. If green, promote the same digest to `staging`/`prod` tags.
|
||||||
|
5. Create final semantic release tag (`vX.Y.Z`) only at milestone completion.
|
||||||
|
|
||||||
|
Example with `crane`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DIGEST=$(crane digest REGISTRY/ORG/IMAGE:sha-${CI_COMMIT_SHA:0:8})
|
||||||
|
crane tag REGISTRY/ORG/IMAGE@${DIGEST} testing
|
||||||
|
# after situational tests pass:
|
||||||
|
crane tag REGISTRY/ORG/IMAGE@${DIGEST} prod
|
||||||
|
```
|
||||||
|
|
||||||
|
### Deployment Strategy: Blue-Green Default
|
||||||
|
|
||||||
|
- Blue-green is the default release strategy for lights-out operation.
|
||||||
|
- Canary is OPTIONAL and allowed only when automated SLO/error-rate monitoring and rollback triggers are configured.
|
||||||
|
- If canary guardrails are missing, you MUST use blue-green.
|
||||||
|
|
||||||
|
### Image Retention and Cleanup (Hard Rule)
|
||||||
|
|
||||||
|
Registry cleanup MUST be automated (daily or weekly job).
|
||||||
|
|
||||||
|
Retention policy:
|
||||||
|
- Keep all final release tags (`vX.Y.Z`) indefinitely.
|
||||||
|
- Keep digests currently referenced by `prod` and `testing` tags.
|
||||||
|
- Keep the most recent 20 RC tags (`vX.Y.Z-rc.N`) per service.
|
||||||
|
- Delete RC and `sha-*` tags older than 30 days when they are not referenced by active environments/releases.
|
||||||
|
|
||||||
|
Before deleting any image/tag:
|
||||||
|
- Verify digest is not currently deployed.
|
||||||
|
- Verify digest is not referenced by any active release/tag notes.
|
||||||
|
- Log cleanup actions in CI job output.
|
||||||
|
|
||||||
### Kaniko Options
|
### Kaniko Options
|
||||||
|
|
||||||
Common flags for `/kaniko/executor`:
|
Common flags for `/kaniko/executor`:
|
||||||
@@ -252,7 +311,10 @@ In `docker-compose.yml`:
|
|||||||
```yaml
|
```yaml
|
||||||
services:
|
services:
|
||||||
api:
|
api:
|
||||||
image: git.example.com/org/image:${IMAGE_TAG:-dev}
|
# Preferred: pin digest produced by CI and promoted by environment
|
||||||
|
image: git.example.com/org/image@${IMAGE_DIGEST}
|
||||||
|
# Optional channel pointer for non-prod:
|
||||||
|
# image: git.example.com/org/image:${IMAGE_TAG:-testing}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Package Linking
|
## Package Linking
|
||||||
@@ -315,7 +377,7 @@ link-packages:
|
|||||||
link_package "image-name-1"
|
link_package "image-name-1"
|
||||||
link_package "image-name-2"
|
link_package "image-name-2"
|
||||||
when:
|
when:
|
||||||
- branch: [main, develop]
|
- branch: [main]
|
||||||
event: [push, manual, tag]
|
event: [push, manual, tag]
|
||||||
depends_on:
|
depends_on:
|
||||||
- docker-build-image-1
|
- docker-build-image-1
|
||||||
@@ -350,6 +412,12 @@ Configure these in the Woodpecker UI (Settings > Secrets) or via CLI:
|
|||||||
| `gitea_username` | Gitea username or service account | `push`, `manual`, `tag` |
|
| `gitea_username` | Gitea username or service account | `push`, `manual`, `tag` |
|
||||||
| `gitea_token` | Gitea token with `package:write` scope | `push`, `manual`, `tag` |
|
| `gitea_token` | Gitea token with `package:write` scope | `push`, `manual`, `tag` |
|
||||||
|
|
||||||
|
### Required CI Variables (Non-Secret)
|
||||||
|
|
||||||
|
| Variable | Example | Purpose |
|
||||||
|
|----------|---------|---------|
|
||||||
|
| `RELEASE_BASE_VERSION` | `0.0.1` | Base milestone version used to generate RC tags (`v0.0.1-rc.N`) |
|
||||||
|
|
||||||
### Setting Secrets via CLI
|
### Setting Secrets via CLI
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -554,9 +622,9 @@ security-trivy:
|
|||||||
mkdir -p ~/.docker
|
mkdir -p ~/.docker
|
||||||
echo "{\"auths\":{\"REGISTRY\":{\"username\":\"$$GITEA_USER\",\"password\":\"$$GITEA_TOKEN\"}}}" > ~/.docker/config.json
|
echo "{\"auths\":{\"REGISTRY\":{\"username\":\"$$GITEA_USER\",\"password\":\"$$GITEA_TOKEN\"}}}" > ~/.docker/config.json
|
||||||
trivy image --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed \
|
trivy image --exit-code 1 --severity HIGH,CRITICAL --ignore-unfixed \
|
||||||
REGISTRY/ORG/IMAGE:$${CI_COMMIT_SHA:0:8}
|
REGISTRY/ORG/IMAGE:sha-$${CI_COMMIT_SHA:0:8}
|
||||||
when:
|
when:
|
||||||
- branch: [main, develop]
|
- branch: [main]
|
||||||
event: [push, manual, tag]
|
event: [push, manual, tag]
|
||||||
depends_on:
|
depends_on:
|
||||||
- docker-build-SERVICE
|
- docker-build-SERVICE
|
||||||
@@ -574,7 +642,7 @@ Docker build MUST depend on ALL quality + security steps. Trivy runs AFTER build
|
|||||||
|
|
||||||
## Monorepo Considerations
|
## Monorepo Considerations
|
||||||
|
|
||||||
### pnpm + Turbo (Mosaic Stack pattern)
|
### pnpm + Turbo
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
variables:
|
variables:
|
||||||
@@ -589,7 +657,7 @@ steps:
|
|||||||
- pnpm build # Turbo handles dependency order and caching
|
- pnpm build # Turbo handles dependency order and caching
|
||||||
```
|
```
|
||||||
|
|
||||||
### npm Workspaces (U-Connect pattern)
|
### npm Workspaces
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
variables:
|
variables:
|
||||||
@@ -684,24 +752,28 @@ steps:
|
|||||||
from_secret: gitea_username
|
from_secret: gitea_username
|
||||||
GITEA_TOKEN:
|
GITEA_TOKEN:
|
||||||
from_secret: gitea_token
|
from_secret: gitea_token
|
||||||
|
RELEASE_BASE_VERSION: ${RELEASE_BASE_VERSION}
|
||||||
CI_COMMIT_BRANCH: ${CI_COMMIT_BRANCH}
|
CI_COMMIT_BRANCH: ${CI_COMMIT_BRANCH}
|
||||||
CI_COMMIT_TAG: ${CI_COMMIT_TAG}
|
CI_COMMIT_TAG: ${CI_COMMIT_TAG}
|
||||||
CI_COMMIT_SHA: ${CI_COMMIT_SHA}
|
CI_COMMIT_SHA: ${CI_COMMIT_SHA}
|
||||||
|
CI_PIPELINE_NUMBER: ${CI_PIPELINE_NUMBER}
|
||||||
commands:
|
commands:
|
||||||
- *kaniko_setup
|
- *kaniko_setup
|
||||||
- |
|
- |
|
||||||
DESTINATIONS="--destination git.example.com/org/api:${CI_COMMIT_SHA:0:8}"
|
SHORT_SHA="${CI_COMMIT_SHA:0:8}"
|
||||||
|
BUILD_ID="${CI_PIPELINE_NUMBER:-$SHORT_SHA}"
|
||||||
|
BASE_VERSION="${RELEASE_BASE_VERSION:?RELEASE_BASE_VERSION is required}"
|
||||||
|
DESTINATIONS="--destination git.example.com/org/api:sha-$SHORT_SHA"
|
||||||
if [ "$CI_COMMIT_BRANCH" = "main" ]; then
|
if [ "$CI_COMMIT_BRANCH" = "main" ]; then
|
||||||
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/api:latest"
|
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/api:v${BASE_VERSION}-rc.${BUILD_ID}"
|
||||||
elif [ "$CI_COMMIT_BRANCH" = "develop" ]; then
|
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/api:testing"
|
||||||
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/api:dev"
|
|
||||||
fi
|
fi
|
||||||
if [ -n "$CI_COMMIT_TAG" ]; then
|
if [ -n "$CI_COMMIT_TAG" ]; then
|
||||||
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/api:$CI_COMMIT_TAG"
|
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/api:$CI_COMMIT_TAG"
|
||||||
fi
|
fi
|
||||||
/kaniko/executor --context . --dockerfile src/api/Dockerfile $DESTINATIONS
|
/kaniko/executor --context . --dockerfile src/api/Dockerfile $DESTINATIONS
|
||||||
when:
|
when:
|
||||||
- branch: [main, develop]
|
- branch: [main]
|
||||||
event: [push, manual, tag]
|
event: [push, manual, tag]
|
||||||
depends_on: [build]
|
depends_on: [build]
|
||||||
|
|
||||||
@@ -712,24 +784,28 @@ steps:
|
|||||||
from_secret: gitea_username
|
from_secret: gitea_username
|
||||||
GITEA_TOKEN:
|
GITEA_TOKEN:
|
||||||
from_secret: gitea_token
|
from_secret: gitea_token
|
||||||
|
RELEASE_BASE_VERSION: ${RELEASE_BASE_VERSION}
|
||||||
CI_COMMIT_BRANCH: ${CI_COMMIT_BRANCH}
|
CI_COMMIT_BRANCH: ${CI_COMMIT_BRANCH}
|
||||||
CI_COMMIT_TAG: ${CI_COMMIT_TAG}
|
CI_COMMIT_TAG: ${CI_COMMIT_TAG}
|
||||||
CI_COMMIT_SHA: ${CI_COMMIT_SHA}
|
CI_COMMIT_SHA: ${CI_COMMIT_SHA}
|
||||||
|
CI_PIPELINE_NUMBER: ${CI_PIPELINE_NUMBER}
|
||||||
commands:
|
commands:
|
||||||
- *kaniko_setup
|
- *kaniko_setup
|
||||||
- |
|
- |
|
||||||
DESTINATIONS="--destination git.example.com/org/web:${CI_COMMIT_SHA:0:8}"
|
SHORT_SHA="${CI_COMMIT_SHA:0:8}"
|
||||||
|
BUILD_ID="${CI_PIPELINE_NUMBER:-$SHORT_SHA}"
|
||||||
|
BASE_VERSION="${RELEASE_BASE_VERSION:?RELEASE_BASE_VERSION is required}"
|
||||||
|
DESTINATIONS="--destination git.example.com/org/web:sha-$SHORT_SHA"
|
||||||
if [ "$CI_COMMIT_BRANCH" = "main" ]; then
|
if [ "$CI_COMMIT_BRANCH" = "main" ]; then
|
||||||
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/web:latest"
|
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/web:v${BASE_VERSION}-rc.${BUILD_ID}"
|
||||||
elif [ "$CI_COMMIT_BRANCH" = "develop" ]; then
|
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/web:testing"
|
||||||
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/web:dev"
|
|
||||||
fi
|
fi
|
||||||
if [ -n "$CI_COMMIT_TAG" ]; then
|
if [ -n "$CI_COMMIT_TAG" ]; then
|
||||||
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/web:$CI_COMMIT_TAG"
|
DESTINATIONS="$DESTINATIONS --destination git.example.com/org/web:$CI_COMMIT_TAG"
|
||||||
fi
|
fi
|
||||||
/kaniko/executor --context . --dockerfile src/web/Dockerfile $DESTINATIONS
|
/kaniko/executor --context . --dockerfile src/web/Dockerfile $DESTINATIONS
|
||||||
when:
|
when:
|
||||||
- branch: [main, develop]
|
- branch: [main]
|
||||||
event: [push, manual, tag]
|
event: [push, manual, tag]
|
||||||
depends_on: [build]
|
depends_on: [build]
|
||||||
|
|
||||||
@@ -764,7 +840,7 @@ steps:
|
|||||||
link_package "api"
|
link_package "api"
|
||||||
link_package "web"
|
link_package "web"
|
||||||
when:
|
when:
|
||||||
- branch: [main, develop]
|
- branch: [main]
|
||||||
event: [push, manual, tag]
|
event: [push, manual, tag]
|
||||||
depends_on:
|
depends_on:
|
||||||
- docker-build-api
|
- docker-build-api
|
||||||
@@ -780,49 +856,130 @@ steps:
|
|||||||
5. **Add package linking step** after all Docker builds
|
5. **Add package linking step** after all Docker builds
|
||||||
6. **Update `docker-compose.yml`** to reference registry images instead of local builds:
|
6. **Update `docker-compose.yml`** to reference registry images instead of local builds:
|
||||||
```yaml
|
```yaml
|
||||||
image: git.example.com/org/service:${IMAGE_TAG:-dev}
|
image: git.example.com/org/service@${IMAGE_DIGEST}
|
||||||
```
|
```
|
||||||
7. **Test on develop branch first** — push a small change and verify the pipeline
|
7. **Test on a short-lived non-main branch first** — open a PR and verify quality gates before merging to `main`
|
||||||
8. **Verify images appear** in Gitea Packages tab after successful pipeline
|
8. **Verify images appear** in Gitea Packages tab after successful pipeline
|
||||||
|
|
||||||
|
## Post-Merge CI Monitoring (Hard Rule)
|
||||||
|
|
||||||
|
For source-code delivery, completion is not allowed at "PR opened" stage.
|
||||||
|
|
||||||
|
Required sequence:
|
||||||
|
|
||||||
|
1. Merge PR to `main` (squash) via Mosaic wrapper.
|
||||||
|
2. Monitor CI to terminal status:
|
||||||
|
```bash
|
||||||
|
~/.config/mosaic/rails/git/pr-ci-wait.sh -n <PR_NUMBER>
|
||||||
|
```
|
||||||
|
3. Require green status before claiming completion.
|
||||||
|
4. If CI fails, create remediation task(s) and continue until green.
|
||||||
|
5. If monitoring command fails, report blocker with the exact failed wrapper command and stop.
|
||||||
|
|
||||||
|
Woodpecker note:
|
||||||
|
- In Gitea + Woodpecker environments, commit status contexts generally reflect Woodpecker pipeline results.
|
||||||
|
- Always include CI run/status evidence in completion report.
|
||||||
|
|
||||||
|
## Queue Guard Before Push/Merge (Hard Rule)
|
||||||
|
|
||||||
|
Before pushing a branch or merging a PR, guard against overlapping project pipelines:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push -B main
|
||||||
|
~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose merge -B main
|
||||||
|
```
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
- If pipeline state is running/queued/pending, wait until queue clears.
|
||||||
|
- If timeout or API/auth failure occurs, treat as `blocked`, report exact failed wrapper command, and stop.
|
||||||
|
|
||||||
## Gitea as Unified Platform
|
## Gitea as Unified Platform
|
||||||
|
|
||||||
Gitea provides **three services in one**, eliminating the need for separate Harbor and Verdaccio deployments:
|
Gitea provides **multiple services in one**, eliminating the need for separate registry platforms:
|
||||||
|
|
||||||
| Service | What Gitea Replaces | Registry URL |
|
| Service | What Gitea Replaces | Registry URL |
|
||||||
|---------|---------------------|-------------|
|
|---------|---------------------|-------------|
|
||||||
| **Git hosting** | GitHub/GitLab | `https://GITEA_HOST/org/repo` |
|
| **Git hosting** | GitHub/GitLab | `https://GITEA_HOST/org/repo` |
|
||||||
| **Container registry** | Harbor, Docker Hub | `docker pull GITEA_HOST/org/image:tag` |
|
| **Container registry** | Harbor, Docker Hub | `docker pull GITEA_HOST/org/image:tag` |
|
||||||
| **npm registry** | Verdaccio, Artifactory | `https://GITEA_HOST/api/packages/org/npm/` |
|
| **npm registry** | Verdaccio, Artifactory | `https://GITEA_HOST/api/packages/org/npm/` |
|
||||||
|
| **PyPI registry** | Private PyPI/Artifactory | `https://GITEA_HOST/api/packages/org/pypi` |
|
||||||
|
| **Maven registry** | Nexus, Artifactory | `https://GITEA_HOST/api/packages/org/maven` |
|
||||||
|
| **NuGet registry** | Azure Artifacts, Artifactory | `https://GITEA_HOST/api/packages/org/nuget/index.json` |
|
||||||
|
| **Cargo registry** | crates.io mirrors, Artifactory | `https://GITEA_HOST/api/packages/org/cargo` |
|
||||||
|
| **Composer registry** | Private Packagist, Artifactory | `https://GITEA_HOST/api/packages/org/composer` |
|
||||||
|
| **Conan registry** | Artifactory Conan | `https://GITEA_HOST/api/packages/org/conan` |
|
||||||
|
| **Conda registry** | Anaconda Server, Artifactory | `https://GITEA_HOST/api/packages/org/conda` |
|
||||||
|
| **Generic registry** | Generic binary stores | `https://GITEA_HOST/api/packages/org/generic` |
|
||||||
|
|
||||||
### Additional Package Types
|
### Single Token, Multiple Services
|
||||||
|
|
||||||
Gitea also supports PyPI, Maven, NuGet, Cargo, Composer, Conan, Conda, Generic, and more. All use the same token authentication.
|
|
||||||
|
|
||||||
### Single Token, Three Services
|
|
||||||
|
|
||||||
A Gitea token with `package:write` scope handles:
|
A Gitea token with `package:write` scope handles:
|
||||||
- `git push` / `git pull`
|
- `git push` / `git pull`
|
||||||
- `docker push` / `docker pull` (container registry)
|
- `docker push` / `docker pull` (container registry)
|
||||||
- `npm publish` / `npm install` (npm registry)
|
- `npm publish` / `npm install` (npm registry)
|
||||||
|
- `twine upload` / `pip install` (PyPI registry)
|
||||||
|
- package operations for Maven/NuGet/Cargo/Composer/Conan/Conda/Generic registries
|
||||||
|
|
||||||
This means a single `gitea_token` secret in Woodpecker CI covers all CI/CD operations.
|
This means a single `gitea_token` secret in Woodpecker CI covers all CI/CD package operations.
|
||||||
|
|
||||||
|
## Python Packages on Gitea PyPI
|
||||||
|
|
||||||
|
For Python libraries and internal packages, use Gitea's built-in PyPI registry.
|
||||||
|
|
||||||
|
### Publish (Local or CI)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m pip install --upgrade build twine
|
||||||
|
python -m build
|
||||||
|
python -m twine upload \
|
||||||
|
--repository-url "https://GITEA_HOST/api/packages/ORG/pypi" \
|
||||||
|
--username "$GITEA_USERNAME" \
|
||||||
|
--password "$GITEA_TOKEN" \
|
||||||
|
dist/*
|
||||||
|
```
|
||||||
|
|
||||||
|
### Install (Consumer Projects)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install \
|
||||||
|
--extra-index-url "https://$GITEA_USERNAME:$GITEA_TOKEN@GITEA_HOST/api/packages/ORG/pypi/simple" \
|
||||||
|
your-package-name
|
||||||
|
```
|
||||||
|
|
||||||
|
### Woodpecker Step (Python Publish)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
publish-python-package:
|
||||||
|
image: python:3.12-slim
|
||||||
|
environment:
|
||||||
|
GITEA_USERNAME:
|
||||||
|
from_secret: gitea_username
|
||||||
|
GITEA_TOKEN:
|
||||||
|
from_secret: gitea_token
|
||||||
|
commands:
|
||||||
|
- python -m pip install --upgrade build twine
|
||||||
|
- python -m build
|
||||||
|
- python -m twine upload --repository-url https://GITEA_HOST/api/packages/ORG/pypi --username "$$GITEA_USERNAME" --password "$$GITEA_TOKEN" dist/*
|
||||||
|
when:
|
||||||
|
branch: [main]
|
||||||
|
event: [push]
|
||||||
|
```
|
||||||
|
|
||||||
### Architecture Simplification
|
### Architecture Simplification
|
||||||
|
|
||||||
**Before (3 services):**
|
**Before (4 services):**
|
||||||
```
|
```
|
||||||
Gitea (git) + Harbor (containers) + Verdaccio (npm)
|
Gitea (git) + Harbor (containers) + Verdaccio (npm) + Private PyPI
|
||||||
↓ separate auth ↓ separate auth ↓ OAuth/Authentik
|
↓ separate auth ↓ separate auth ↓ extra auth ↓ extra auth
|
||||||
3 tokens 1 robot account 1 OIDC integration
|
multiple tokens robot/service users npm-specific token pip/twine token
|
||||||
3 backup targets complex RBAC group-based access
|
fragmented access fragmented RBAC fragmented RBAC fragmented RBAC
|
||||||
```
|
```
|
||||||
|
|
||||||
**After (1 service):**
|
**After (1 service):**
|
||||||
```
|
```
|
||||||
Gitea (git + containers + npm)
|
Gitea (git + containers + npm + pypi)
|
||||||
↓ single token
|
↓ unified secrets
|
||||||
1 secret in Woodpecker
|
1 credentials model in CI
|
||||||
1 backup target
|
1 backup target
|
||||||
unified RBAC via Gitea teams
|
unified RBAC via Gitea teams
|
||||||
```
|
```
|
||||||
@@ -900,5 +1057,5 @@ If a project currently uses Verdaccio (e.g., U-Connect at `npm.uscllc.net`), fol
|
|||||||
- Link manually: Gitea UI > Packages > Select package > Link to repository
|
- Link manually: Gitea UI > Packages > Select package > Link to repository
|
||||||
|
|
||||||
### Pipeline runs Docker builds on pull requests
|
### Pipeline runs Docker builds on pull requests
|
||||||
- Verify `when` clause on Docker build steps restricts to `branch: [main, develop]`
|
- Verify `when` clause on Docker build steps restricts to `branch: [main]`
|
||||||
- Pull requests should only run quality gates, not build/push images
|
- Pull requests should only run quality gates, not build/push images
|
||||||
|
|||||||
203
guides/e2e-delivery.md
Normal file
203
guides/e2e-delivery.md
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
# E2E Delivery Procedure (MANDATORY)
|
||||||
|
|
||||||
|
This guide is REQUIRED for all agent sessions.
|
||||||
|
|
||||||
|
## 0. Mode Handshake (Before Any Action)
|
||||||
|
|
||||||
|
First response MUST declare mode before tool calls or implementation steps:
|
||||||
|
|
||||||
|
1. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
2. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
3. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
|
## 1. PRD Gate (Before Coding)
|
||||||
|
|
||||||
|
1. Ensure `docs/PRD.md` or `docs/PRD.json` exists before coding.
|
||||||
|
2. Load `~/.config/mosaic/guides/PRD.md`.
|
||||||
|
3. Prepare/update PRD from user input and available project context.
|
||||||
|
4. If requirements are missing:
|
||||||
|
- proceed with best-guess assumptions by default,
|
||||||
|
- mark each assumption with `ASSUMPTION:` and rationale,
|
||||||
|
- escalate only when uncertainty is high-impact and cannot be bounded safely.
|
||||||
|
5. Treat PRD as the requirement source for implementation, testing, and review.
|
||||||
|
|
||||||
|
## 1a. Tracking Gate (Before Coding)
|
||||||
|
|
||||||
|
1. For non-trivial work, `docs/TASKS.md` MUST exist before coding.
|
||||||
|
2. If `docs/TASKS.md` is missing, create it from `~/.config/mosaic/templates/docs/TASKS.md.template`.
|
||||||
|
3. Detect provider first via `~/.config/mosaic/rails/git/detect-platform.sh`.
|
||||||
|
4. For issue/PR/milestone operations, use Mosaic wrappers first (`~/.config/mosaic/rails/git/*.sh`).
|
||||||
|
5. If external git provider is available (Gitea/GitHub/GitLab), create or update issue(s) before coding.
|
||||||
|
6. Record provider issue reference(s) in `docs/TASKS.md` (example: `#123`).
|
||||||
|
7. If no external provider is available, use internal task refs in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
8. Scratchpad MUST reference both task ID and issue/internal ref.
|
||||||
|
|
||||||
|
## 2. Intake and Scope
|
||||||
|
|
||||||
|
1. Define scope, constraints, and acceptance criteria.
|
||||||
|
2. Identify affected surfaces (API, DB, UI, infra, auth, CI/CD, docs).
|
||||||
|
3. Identify required guides and load them before implementation.
|
||||||
|
4. For code/API/auth/infra changes, load `~/.config/mosaic/guides/DOCUMENTATION.md`.
|
||||||
|
5. Determine budget constraints:
|
||||||
|
- if the user provided a plan limit or token budget, treat it as a HARD cap,
|
||||||
|
- if budget is unknown, derive a working budget from estimates and runtime limits, then continue autonomously.
|
||||||
|
6. Record budget assumptions and caps in the scratchpad before implementation starts.
|
||||||
|
7. Track estimated vs used tokens per logical unit and adapt strategy to remain inside budget.
|
||||||
|
8. If projected usage exceeds budget, auto-reduce scope/parallelism first; escalate only if cap still cannot be met.
|
||||||
|
|
||||||
|
## 2a. Steered Autonomy (Lights-Out)
|
||||||
|
|
||||||
|
1. Agent owns delivery end-to-end: planning, coding, testing, review, PR/repo operations, release/tag, and deployment (when in scope).
|
||||||
|
2. Human intervention is escalation-only; do not pause for routine approvals or handoffs.
|
||||||
|
3. Continue execution until completion criteria are met or an escalation trigger is hit.
|
||||||
|
|
||||||
|
## 3. Scratchpad Requirement
|
||||||
|
|
||||||
|
1. Create a task-specific scratchpad before implementation.
|
||||||
|
2. Record:
|
||||||
|
- objective
|
||||||
|
- plan
|
||||||
|
- progress checkpoints
|
||||||
|
- tests run
|
||||||
|
- risks/blockers
|
||||||
|
- final verification evidence
|
||||||
|
|
||||||
|
## 4. Embedded Execution Cycle (MANDATORY)
|
||||||
|
|
||||||
|
For implementation work, you MUST run this cycle in order:
|
||||||
|
|
||||||
|
1. `plan` - map PRD requirements to concrete implementation steps.
|
||||||
|
2. `code` - implement one logical unit.
|
||||||
|
3. `test` - run required baseline and situational checks for that unit.
|
||||||
|
4. `review` - perform independent code review on the current delta.
|
||||||
|
5. `remediate` - fix all findings and any test failures.
|
||||||
|
6. `review` - re-review remediated changes until blockers are cleared.
|
||||||
|
7. `commit` - commit only when the logical unit passes tests and review.
|
||||||
|
8. `pre-push queue guard` - before pushing, wait for running/queued project pipelines to clear: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push`.
|
||||||
|
9. `push` - push immediately after queue guard passes.
|
||||||
|
10. `PR integration` - if external git provider is available, create/update PR to `main` and merge with required strategy via Mosaic wrappers.
|
||||||
|
11. `pre-merge queue guard` - before merging PR, wait for running/queued project pipelines to clear: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose merge`.
|
||||||
|
12. `CI/pipeline verification` - wait for terminal CI status and require green before completion (`~/.config/mosaic/rails/git/pr-ci-wait.sh` for PR-based workflow).
|
||||||
|
13. `issue closure` - close linked external issue (or close internal `docs/TASKS.md` task ref when provider is unavailable).
|
||||||
|
14. `greenfield situational test` - validate required user flows in a clean environment/startup path (post-merge for trunk workflow changes).
|
||||||
|
15. `deploy + post-deploy validation` - when deployment is in scope, deploy to configured target and run post-deploy health/smoke checks.
|
||||||
|
16. `repeat` - continue until all acceptance criteria are complete.
|
||||||
|
|
||||||
|
### Post-PR Hard Gate (Execute Sequentially, No Exceptions)
|
||||||
|
|
||||||
|
1. `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose merge -B main`
|
||||||
|
2. `~/.config/mosaic/rails/git/pr-merge.sh -n <PR_NUMBER> -m squash`
|
||||||
|
3. `~/.config/mosaic/rails/git/pr-ci-wait.sh -n <PR_NUMBER>`
|
||||||
|
4. `~/.config/mosaic/rails/git/issue-close.sh -i <ISSUE_NUMBER>` (or close internal `docs/TASKS.md` ref when no provider exists)
|
||||||
|
5. If any step fails: set status `blocked`, report the exact failed wrapper command, and stop.
|
||||||
|
6. Do not ask the human to perform routine merge/close operations.
|
||||||
|
7. Do not claim completion before step 4 succeeds.
|
||||||
|
|
||||||
|
### Forbidden Anti-Patterns
|
||||||
|
|
||||||
|
1. Do NOT stop at "PR created" or "PR updated".
|
||||||
|
2. Do NOT ask "should I merge?" for routine delivery PRs.
|
||||||
|
3. Do NOT ask "should I close the issue?" after merge + green CI.
|
||||||
|
|
||||||
|
If any step fails, you MUST remediate and re-run from the relevant step before proceeding.
|
||||||
|
If push-queue/merge-queue/PR merge/CI/issue closure fails, status is `blocked` (not complete) and you MUST report the exact failed wrapper command.
|
||||||
|
|
||||||
|
## 5. Testing Priority Model
|
||||||
|
|
||||||
|
Use this order of priority:
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY gate and MUST prove changed behavior meets requirements.
|
||||||
|
2. Baseline tests are REQUIRED safety checks and MUST run for all software changes.
|
||||||
|
3. TDD is risk-based and REQUIRED only for specific high-risk change types.
|
||||||
|
|
||||||
|
## 6. Mandatory Test Baseline
|
||||||
|
|
||||||
|
For all software changes, you MUST run baseline checks applicable to the repo/toolchain:
|
||||||
|
|
||||||
|
1. lint (or equivalent static checks)
|
||||||
|
2. type checks (if language/tooling supports it)
|
||||||
|
3. unit tests for changed logic
|
||||||
|
4. integration tests for changed boundaries
|
||||||
|
|
||||||
|
## 7. Situational Testing Matrix (PRIMARY GATE)
|
||||||
|
|
||||||
|
Run additional tests based on what changed:
|
||||||
|
|
||||||
|
| Change Surface | Required Situational Tests |
|
||||||
|
|---|---|
|
||||||
|
| Authentication/authorization | auth failure-path tests, permission boundary tests, token/session validation |
|
||||||
|
| Database schema/migrations | migration up/down validation, rollback safety, data integrity checks |
|
||||||
|
| API contract changes | backward compatibility checks, consumer-impact tests, contract tests |
|
||||||
|
| Frontend/UI workflow changes | end-to-end flow tests, accessibility sanity checks, state transition checks |
|
||||||
|
| CI/CD or deployment changes | pipeline execution validation, artifact integrity checks, rollback path check |
|
||||||
|
| Security-sensitive logic | abuse-case tests, input validation fuzzing/sanitization checks |
|
||||||
|
| Performance-critical path | baseline comparison, regression threshold checks |
|
||||||
|
|
||||||
|
## 8. Risk-Based TDD Requirement
|
||||||
|
|
||||||
|
TDD is REQUIRED for:
|
||||||
|
|
||||||
|
1. bug fixes (write a reproducer test first)
|
||||||
|
2. security/auth/permission logic changes
|
||||||
|
3. critical business logic and data-mutation rules
|
||||||
|
|
||||||
|
TDD is RECOMMENDED (not mandatory) for low-risk UI, copy, styling, and mechanical refactors.
|
||||||
|
If TDD is skipped for a non-required case, record the rationale in the scratchpad.
|
||||||
|
|
||||||
|
## 9. Mandatory Code Review Gate
|
||||||
|
|
||||||
|
If you modify source code, you MUST run an independent code review before completion.
|
||||||
|
|
||||||
|
1. Use automated review tooling when available.
|
||||||
|
2. If automated tooling is unavailable, run manual review using `~/.config/mosaic/guides/CODE-REVIEW.md`.
|
||||||
|
3. Any blocker or critical finding MUST be fixed or tracked as an explicit remediation task before closure.
|
||||||
|
|
||||||
|
## 10. Mandatory Documentation Gate
|
||||||
|
|
||||||
|
For code/API/auth/infra changes, documentation updates are REQUIRED before completion.
|
||||||
|
|
||||||
|
1. Apply the standard in `~/.config/mosaic/guides/DOCUMENTATION.md`.
|
||||||
|
2. Update required docs in the same logical change set as implementation.
|
||||||
|
3. Complete `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md`.
|
||||||
|
4. If publish platform is unspecified, ask the user to choose in-app or external platform before publishing.
|
||||||
|
5. Missing required documentation is a BLOCKER.
|
||||||
|
|
||||||
|
## 11. Completion Gate (All Required)
|
||||||
|
|
||||||
|
You MUST satisfy all items before completion:
|
||||||
|
|
||||||
|
1. Acceptance criteria met.
|
||||||
|
2. Baseline tests passed.
|
||||||
|
3. Situational tests passed (primary gate), including required greenfield situational validation.
|
||||||
|
4. PRD is current and implementation is aligned with PRD.
|
||||||
|
5. Acceptance criteria mapped to verification evidence.
|
||||||
|
6. Code review completed for source code changes.
|
||||||
|
7. Required documentation updates completed and reviewed.
|
||||||
|
8. Scratchpad updated with evidence.
|
||||||
|
9. Known risks documented.
|
||||||
|
10. No unresolved blocker hidden.
|
||||||
|
11. If deployment is in scope, deployment target, release version, and post-deploy verification evidence are documented.
|
||||||
|
12. `docs/TASKS.md` status and issue/internal references are updated to match delivered work.
|
||||||
|
13. If source code changed and external provider is available: PR merged to `main` (squash), with merge evidence recorded.
|
||||||
|
14. CI/pipeline status is terminal green for the merged PR/head commit.
|
||||||
|
15. Linked external issue is closed (or internal task ref is closed when no provider exists).
|
||||||
|
16. If any of items 13-15 fail due access/tooling, report `blocked` with exact failed wrapper command and do not claim completion.
|
||||||
|
|
||||||
|
## 12. Review and Reporting
|
||||||
|
|
||||||
|
Completion report MUST include:
|
||||||
|
|
||||||
|
1. what changed
|
||||||
|
2. PRD alignment summary
|
||||||
|
3. acceptance criteria to evidence mapping
|
||||||
|
4. what was tested (baseline + situational)
|
||||||
|
5. what was reviewed (code review scope)
|
||||||
|
6. what documentation was updated
|
||||||
|
7. command-level evidence summary
|
||||||
|
8. residual risks
|
||||||
|
9. deployment and post-deploy verification summary (if in scope)
|
||||||
|
10. explicit pass/fail status
|
||||||
|
11. tracking summary (`docs/TASKS.md` updates and issue/internal refs)
|
||||||
|
12. PR lifecycle summary (PR number, merge commit, merge method)
|
||||||
|
13. CI/pipeline summary (run/check URL, terminal status)
|
||||||
|
14. issue closure summary (issue number/ref and close evidence)
|
||||||
@@ -1,18 +1,47 @@
|
|||||||
# Autonomous Orchestrator Guide
|
# Autonomous Orchestrator Guide
|
||||||
|
|
||||||
> Load this guide when orchestrating autonomous task completion across any project.
|
When spawning workers, include skill loading in the kickstart:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
claude -p "Read ~/.config/mosaic/skills/nestjs-best-practices/SKILL.md then implement..."codex exec "Read ~/.config/mosaic/skills/nestjs-best-practices/SKILL.md then implement..."
|
||||||
|
```
|
||||||
|
|
||||||
|
#### **MANDATORY**
|
||||||
|
|
||||||
|
- You MUST establish the requirements for a task, or series of tasks, before coding begins.
|
||||||
|
- You MUST ensure `docs/PRD.md` or `docs/PRD.json` exists before worker coding starts.
|
||||||
|
- You MUST use sequential-thinking to properly plan out tasks, milestones, epics, and PRD requirements prior to orchestrating agents.
|
||||||
|
- You MUST track tasks at the project level in docs/TASKS.md.
|
||||||
|
- You MUST keep the TASKS.md file updated with agent and tasks statuses.
|
||||||
|
- You MUST keep `docs/` root clean. Reports and working artifacts MUST be stored in scoped folders (`docs/reports/`, `docs/tasks/`, `docs/releases/`, `docs/scratchpads/`).
|
||||||
|
- You MUST enforce plan/token usage budgets when provided, and adapt orchestration strategy to remain within limits.
|
||||||
|
- You MUST enforce trunk workflow: workers branch from `main`, PR target is `main`, direct push to `main` is forbidden, and PR merges to `main` are squash-only.
|
||||||
|
- You MUST operate in steered-autonomy mode: human intervention is escalation-only; do not require the human to write code, review code, or manage PR/repo workflow.
|
||||||
|
- You MUST NOT declare task or issue completion until PR is merged, CI/pipeline is terminal green, and linked issue is closed (or internal TASKS ref is closed when provider is unavailable).
|
||||||
|
- Mosaic orchestration rules OVERRIDE runtime-default caution for routine push/merge/issue-close actions required by this workflow.
|
||||||
|
- Do NOT ask "should I merge?" or "should I close the issue?" for routine delivery flow after gates pass.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
The orchestrator **cold-starts** on any project with just a review report location and minimal kickstart. It autonomously:
|
## Session Start Handshake (Hard Rule)
|
||||||
1. Parses review reports to extract findings
|
|
||||||
2. Categorizes findings into phases by severity
|
|
||||||
3. Estimates token usage per task
|
|
||||||
4. Creates Gitea issues (phase-level)
|
|
||||||
5. Bootstraps `docs/tasks.md` from scratch
|
|
||||||
6. Coordinates completion using worker agents
|
|
||||||
|
|
||||||
**Key principle:** The orchestrator is the **sole writer** of `docs/tasks.md`. Worker agents execute tasks and report results — they never modify the tracking file.
|
Before any orchestration actions, the first response MUST be:
|
||||||
|
|
||||||
|
`Now initiating Orchestrator mode...`
|
||||||
|
|
||||||
|
Then proceed with orchestration bootstrap steps.
|
||||||
|
|
||||||
|
The orchestrator **cold-starts** on any project with just a review report location and minimal kickstart. It autonomously:
|
||||||
|
1. Prepares/updates project PRD (`docs/PRD.md` or `docs/PRD.json`) from user input and available project context
|
||||||
|
2. Parses review reports to extract findings
|
||||||
|
3. Categorizes findings into phases by severity
|
||||||
|
4. Estimates token usage per task
|
||||||
|
5. Creates phase issues in the configured git provider (Gitea/GitHub/GitLab)
|
||||||
|
6. Bootstraps `docs/TASKS.md` from scratch
|
||||||
|
7. Coordinates completion using worker agents
|
||||||
|
8. Enforces documentation completion gates for code/API/auth/infra changes
|
||||||
|
|
||||||
|
**Key principle:** The orchestrator is the **sole writer** of `docs/TASKS.md`. Worker agents execute tasks and report results — they never modify the tracking file.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -25,8 +54,8 @@ The orchestrator **cold-starts** on any project with just a review report locati
|
|||||||
- "Quickly fixes" something to save time — this is how drift starts
|
- "Quickly fixes" something to save time — this is how drift starts
|
||||||
|
|
||||||
**The orchestrator ONLY:**
|
**The orchestrator ONLY:**
|
||||||
- Reads/writes `docs/tasks.md`
|
- Reads/writes `docs/TASKS.md`
|
||||||
- Reads/writes `docs/orchestrator-learnings.json`
|
- Reads/writes `docs/tasks/orchestrator-learnings.json`
|
||||||
- Delegates ALL code changes to workers (native subagent tool when available, otherwise Mosaic matrix rail)
|
- Delegates ALL code changes to workers (native subagent tool when available, otherwise Mosaic matrix rail)
|
||||||
- Parses worker JSON results
|
- Parses worker JSON results
|
||||||
- Commits task tracking updates (tasks.md, learnings)
|
- Commits task tracking updates (tasks.md, learnings)
|
||||||
@@ -56,7 +85,7 @@ Matrix rail mode commands:
|
|||||||
~/.config/mosaic/bin/mosaic-orchestrator-drain
|
~/.config/mosaic/bin/mosaic-orchestrator-drain
|
||||||
```
|
```
|
||||||
|
|
||||||
In Matrix rail mode, keep `docs/tasks.md` as canonical project tracking and use
|
In Matrix rail mode, keep `docs/TASKS.md` as canonical project tracking and use
|
||||||
`.mosaic/orchestrator/` for deterministic worker dispatch state.
|
`.mosaic/orchestrator/` for deterministic worker dispatch state.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -68,7 +97,7 @@ Use templates from `jarvis-brain/docs/templates/` to scaffold tracking files:
|
|||||||
```bash
|
```bash
|
||||||
# Set environment variables
|
# Set environment variables
|
||||||
export PROJECT="project-name"
|
export PROJECT="project-name"
|
||||||
export MILESTONE="M1-Feature"
|
export MILESTONE="0.0.1"
|
||||||
export CURRENT_DATETIME=$(date -Iseconds)
|
export CURRENT_DATETIME=$(date -Iseconds)
|
||||||
export TASK_PREFIX="PR-SEC"
|
export TASK_PREFIX="PR-SEC"
|
||||||
export PHASE_ISSUE="#1"
|
export PHASE_ISSUE="#1"
|
||||||
@@ -77,23 +106,41 @@ export PHASE_BRANCH="fix/security"
|
|||||||
# Copy templates
|
# Copy templates
|
||||||
TEMPLATES=~/src/jarvis-brain/docs/templates
|
TEMPLATES=~/src/jarvis-brain/docs/templates
|
||||||
|
|
||||||
# Create tasks.md (then populate with findings)
|
# Create PRD if missing (before coding begins)
|
||||||
envsubst < $TEMPLATES/orchestrator/tasks.md.template > docs/tasks.md
|
[[ -f docs/PRD.md || -f docs/PRD.json ]] || cp ~/.config/mosaic/templates/docs/PRD.md.template docs/PRD.md
|
||||||
|
|
||||||
|
# Create TASKS.md (then populate with findings)
|
||||||
|
envsubst < $TEMPLATES/orchestrator/tasks.md.template > docs/TASKS.md
|
||||||
|
|
||||||
# Create learnings tracking
|
# Create learnings tracking
|
||||||
envsubst < $TEMPLATES/orchestrator/orchestrator-learnings.json.template > docs/orchestrator-learnings.json
|
mkdir -p docs/tasks docs/reports/deferred
|
||||||
|
envsubst < $TEMPLATES/orchestrator/orchestrator-learnings.json.template > docs/tasks/orchestrator-learnings.json
|
||||||
|
|
||||||
# Create review report structure (if doing new review)
|
# Create review report structure (if doing new review)
|
||||||
$TEMPLATES/reports/review-report-scaffold.sh codebase-review
|
$TEMPLATES/reports/review-report-scaffold.sh codebase-review
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Milestone versioning (HARD RULE):
|
||||||
|
|
||||||
|
- Pre-MVP milestones MUST start at `0.0.1`.
|
||||||
|
- Pre-MVP progression MUST remain in `0.0.x` (`0.0.2`, `0.0.3`, ...).
|
||||||
|
- `0.1.0` is reserved for MVP release.
|
||||||
|
- You MUST NOT start pre-MVP planning at `0.1.0`.
|
||||||
|
|
||||||
|
Branch and merge strategy (HARD RULE):
|
||||||
|
|
||||||
|
- Workers use short-lived task branches from `origin/main`.
|
||||||
|
- Worker task branches merge back via PR to `main` only.
|
||||||
|
- Direct pushes to `main` are prohibited.
|
||||||
|
- PR merges to `main` MUST use squash merge.
|
||||||
|
|
||||||
**Available templates:**
|
**Available templates:**
|
||||||
|
|
||||||
| Template | Purpose |
|
| Template | Purpose |
|
||||||
|----------|---------|
|
|----------|---------|
|
||||||
| `orchestrator/tasks.md.template` | Task tracking table with schema |
|
| `orchestrator/tasks.md.template` | Task tracking table with schema |
|
||||||
| `orchestrator/orchestrator-learnings.json.template` | Variance tracking |
|
| `orchestrator/orchestrator-learnings.json.template` | Variance tracking |
|
||||||
| `orchestrator/phase-issue-body.md.template` | Gitea issue body |
|
| `orchestrator/phase-issue-body.md.template` | Git provider issue body |
|
||||||
| `orchestrator/compaction-summary.md.template` | 60% checkpoint format |
|
| `orchestrator/compaction-summary.md.template` | 60% checkpoint format |
|
||||||
| `reports/review-report-scaffold.sh` | Creates report directory |
|
| `reports/review-report-scaffold.sh` | Creates report directory |
|
||||||
| `scratchpad.md.template` | Per-task working document |
|
| `scratchpad.md.template` | Per-task working document |
|
||||||
@@ -104,6 +151,16 @@ See `jarvis-brain/docs/templates/README.md` for full documentation.
|
|||||||
|
|
||||||
## Phase 1: Bootstrap
|
## Phase 1: Bootstrap
|
||||||
|
|
||||||
|
### Step 0: Prepare PRD (Required Before Coding)
|
||||||
|
|
||||||
|
Before creating tasks or spawning workers:
|
||||||
|
|
||||||
|
1. Ensure `docs/PRD.md` or `docs/PRD.json` exists.
|
||||||
|
2. Build/update PRD from user input and available project context.
|
||||||
|
3. If requirements are missing, proceed with best-guess assumptions by default and mark each guessed requirement with `ASSUMPTION:` in PRD.
|
||||||
|
4. Escalate only when uncertainty is high-impact and cannot be safely bounded with rollback-ready defaults.
|
||||||
|
5. Do NOT start worker coding tasks until this step is complete.
|
||||||
|
|
||||||
### Step 1: Parse Review Reports
|
### Step 1: Parse Review Reports
|
||||||
|
|
||||||
Review reports typically follow this structure:
|
Review reports typically follow this structure:
|
||||||
@@ -169,6 +226,24 @@ Use these heuristics based on task type:
|
|||||||
- Test requirements (+5-10K if tests needed)
|
- Test requirements (+5-10K if tests needed)
|
||||||
- Documentation needs (+2-3K if docs needed)
|
- Documentation needs (+2-3K if docs needed)
|
||||||
|
|
||||||
|
### Step 3b: Budget Guardrail (HARD RULE)
|
||||||
|
|
||||||
|
Before creating dependencies or dispatching workers:
|
||||||
|
|
||||||
|
1. Determine budget cap:
|
||||||
|
- Use explicit user plan/token cap if provided.
|
||||||
|
- If no cap is provided, derive a soft cap from estimates and runtime constraints, then continue autonomously.
|
||||||
|
2. Calculate projected total from `estimate` column and record cap in task notes/scratchpad.
|
||||||
|
3. Apply dispatch mode by budget pressure:
|
||||||
|
- `<70%` of cap projected: normal orchestration (up to 2 workers).
|
||||||
|
- `70-90%` of cap projected: conservative mode (1 worker, tighter scope, no exploratory tasks).
|
||||||
|
- `>90%` of cap projected: freeze new worker starts; triage remaining work with user.
|
||||||
|
4. If projected usage exceeds cap, first reduce scope/parallelism automatically.
|
||||||
|
If cap still cannot be met, STOP and ask user to:
|
||||||
|
- reduce scope, or
|
||||||
|
- split into phases, or
|
||||||
|
- approve a higher budget.
|
||||||
|
|
||||||
### Step 4: Determine Dependencies
|
### Step 4: Determine Dependencies
|
||||||
|
|
||||||
**Automatic dependency rules:**
|
**Automatic dependency rules:**
|
||||||
@@ -183,9 +258,18 @@ Use these heuristics based on task type:
|
|||||||
- `{PREFIX}-CQ-{LAST}`: Phase 3 verification
|
- `{PREFIX}-CQ-{LAST}`: Phase 3 verification
|
||||||
- `{PREFIX}-TEST-{LAST}`: Phase 4 verification (final quality gates)
|
- `{PREFIX}-TEST-{LAST}`: Phase 4 verification (final quality gates)
|
||||||
|
|
||||||
### Step 5: Create Gitea Issues (Phase-Level)
|
### Step 5: Create Phase Issues (Gitea, GitHub, or GitLab)
|
||||||
|
|
||||||
Create ONE issue per phase using git scripts:
|
You MUST create ONE issue per phase in the configured external git provider.
|
||||||
|
|
||||||
|
Milestone binding rule:
|
||||||
|
|
||||||
|
- When the project is pre-MVP, issue milestones MUST use a `0.0.x` milestone.
|
||||||
|
- `0.1.0` MUST be used only for the MVP release milestone.
|
||||||
|
|
||||||
|
Provider options:
|
||||||
|
|
||||||
|
1. Gitea (preferred when available) via Mosaic helper:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~/.config/mosaic/rails/git/issue-create.sh \
|
~/.config/mosaic/rails/git/issue-create.sh \
|
||||||
@@ -201,6 +285,7 @@ Create ONE issue per phase using git scripts:
|
|||||||
|
|
||||||
- [ ] All critical findings remediated
|
- [ ] All critical findings remediated
|
||||||
- [ ] Quality gates passing
|
- [ ] Quality gates passing
|
||||||
|
- [ ] Required documentation updates complete
|
||||||
- [ ] No new regressions
|
- [ ] No new regressions
|
||||||
EOF
|
EOF
|
||||||
)" \
|
)" \
|
||||||
@@ -208,18 +293,44 @@ EOF
|
|||||||
-m "{milestone-name}"
|
-m "{milestone-name}"
|
||||||
```
|
```
|
||||||
|
|
||||||
**Capture issue numbers** — you'll link tasks to these.
|
2. GitHub (if repository uses GitHub):
|
||||||
|
|
||||||
### Step 6: Create docs/tasks.md
|
```bash
|
||||||
|
gh issue create \
|
||||||
|
--title "Phase 1: Critical Security Fixes" \
|
||||||
|
--body-file /tmp/phase-1-body.md \
|
||||||
|
--label "security,critical" \
|
||||||
|
--milestone "{milestone-name}"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. GitLab (if repository uses GitLab):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
glab issue create \
|
||||||
|
--title "Phase 1: Critical Security Fixes" \
|
||||||
|
--description-file /tmp/phase-1-body.md \
|
||||||
|
--label "security,critical" \
|
||||||
|
--milestone "{milestone-name}"
|
||||||
|
```
|
||||||
|
|
||||||
|
No external provider fallback (HARD RULE):
|
||||||
|
|
||||||
|
- If Gitea/GitHub/GitLab is unavailable, you MUST track phase-level milestones and issue equivalents directly in `docs/TASKS.md`.
|
||||||
|
- In this mode, the `issue` column MUST use internal refs (example: `TASKS:P1`, `TASKS:P2`).
|
||||||
|
- You MUST keep `docs/TASKS.md` as the complete system of record for tasks, milestones, and issue status.
|
||||||
|
|
||||||
|
**Capture issue references** — you'll link tasks to these.
|
||||||
|
|
||||||
|
### Step 6: Create docs/TASKS.md
|
||||||
|
|
||||||
Create the file with this exact schema:
|
Create the file with this exact schema:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
# Tasks
|
# Tasks
|
||||||
|
|
||||||
| id | status | description | issue | repo | branch | depends_on | blocks | agent | started_at | completed_at | estimate | used |
|
| id | status | description | issue | repo | branch | depends_on | blocks | agent | started_at | completed_at | estimate | used | notes |
|
||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
| {PREFIX}-SEC-001 | not-started | SEC-API-1: Brief description | #{N} | api | fix/security | | {PREFIX}-SEC-002 | | | | 8K | |
|
| {PREFIX}-SEC-001 | not-started | SEC-API-1: Brief description | #{N} | api | fix/security | | {PREFIX}-SEC-002 | | | | 8K | | |
|
||||||
```
|
```
|
||||||
|
|
||||||
**Column definitions:**
|
**Column definitions:**
|
||||||
@@ -227,9 +338,9 @@ Create the file with this exact schema:
|
|||||||
| Column | Format | Purpose |
|
| Column | Format | Purpose |
|
||||||
|--------|--------|---------|
|
|--------|--------|---------|
|
||||||
| `id` | `{PREFIX}-{CAT}-{NNN}` | Unique task ID (e.g., MS-SEC-001) |
|
| `id` | `{PREFIX}-{CAT}-{NNN}` | Unique task ID (e.g., MS-SEC-001) |
|
||||||
| `status` | `not-started` \| `in-progress` \| `done` \| `failed` | Current state |
|
| `status` | `not-started` \| `in-progress` \| `done` \| `failed` \| `blocked` \| `needs-qa` | Current state |
|
||||||
| `description` | `{FindingID}: Brief summary` | What to fix |
|
| `description` | `{FindingID}: Brief summary` | What to fix |
|
||||||
| `issue` | `#NNN` | Gitea issue (phase-level, all tasks in phase share) |
|
| `issue` | `#NNN` or `TASKS:Pn` | Provider issue ref (phase-level) or internal TASKS milestone ref |
|
||||||
| `repo` | Workspace name | `api`, `web`, `orchestrator`, etc. |
|
| `repo` | Workspace name | `api`, `web`, `orchestrator`, etc. |
|
||||||
| `branch` | Branch name | `fix/security`, `fix/code-quality`, etc. |
|
| `branch` | Branch name | `fix/security`, `fix/code-quality`, etc. |
|
||||||
| `depends_on` | Comma-separated IDs | Must complete first |
|
| `depends_on` | Comma-separated IDs | Must complete first |
|
||||||
@@ -239,6 +350,10 @@ Create the file with this exact schema:
|
|||||||
| `completed_at` | ISO 8601 | When work finished |
|
| `completed_at` | ISO 8601 | When work finished |
|
||||||
| `estimate` | `5K`, `15K`, etc. | Predicted token usage |
|
| `estimate` | `5K`, `15K`, etc. | Predicted token usage |
|
||||||
| `used` | `4.2K`, `12.8K`, etc. | Actual usage (fill on completion) |
|
| `used` | `4.2K`, `12.8K`, etc. | Actual usage (fill on completion) |
|
||||||
|
| `notes` | free text | Review results, PR/CI/issue closure evidence, blocker commands |
|
||||||
|
|
||||||
|
Status rule:
|
||||||
|
- `done` is allowed only after PR merge + green CI + issue/ref closure for source-code tasks.
|
||||||
|
|
||||||
**Category prefixes:**
|
**Category prefixes:**
|
||||||
- `SEC` — Security (Phase 1-2)
|
- `SEC` — Security (Phase 1-2)
|
||||||
@@ -246,11 +361,21 @@ Create the file with this exact schema:
|
|||||||
- `CQ` — Code quality (Phase 3)
|
- `CQ` — Code quality (Phase 3)
|
||||||
- `TEST` — Test coverage (Phase 4)
|
- `TEST` — Test coverage (Phase 4)
|
||||||
- `PERF` — Performance (Phase 3)
|
- `PERF` — Performance (Phase 3)
|
||||||
|
- `DOC` — Documentation updates/gates
|
||||||
|
|
||||||
|
### Step 6b: Add Documentation Tasks (MANDATORY)
|
||||||
|
|
||||||
|
For each phase containing code/API/auth/infra work:
|
||||||
|
|
||||||
|
1. Add explicit documentation tasks in `docs/TASKS.md` (or include docs in phase verification tasks).
|
||||||
|
2. Require completion of `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md`.
|
||||||
|
3. Ensure phase acceptance criteria includes documentation completion.
|
||||||
|
4. Do not mark phase complete until documentation tasks are done.
|
||||||
|
|
||||||
### Step 7: Commit Bootstrap
|
### Step 7: Commit Bootstrap
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git add docs/tasks.md
|
git add docs/TASKS.md
|
||||||
git commit -m "chore(orchestrator): Bootstrap tasks.md from review report
|
git commit -m "chore(orchestrator): Bootstrap tasks.md from review report
|
||||||
|
|
||||||
Parsed {N} findings into {M} tasks across {P} phases.
|
Parsed {N} findings into {M} tasks across {P} phases.
|
||||||
@@ -264,34 +389,61 @@ git push
|
|||||||
|
|
||||||
```
|
```
|
||||||
1. git pull --rebase
|
1. git pull --rebase
|
||||||
2. Read docs/tasks.md
|
2. Read docs/TASKS.md
|
||||||
3. Find next task: status=not-started AND all depends_on are done
|
3. Find next task: status=not-started AND all depends_on are done
|
||||||
4. If no task available:
|
4. If no task available:
|
||||||
- All done? → Report success, run final retrospective, STOP
|
- All done? → Report success, run final retrospective, STOP
|
||||||
- Some blocked? → Report deadlock, STOP
|
- Some blocked? → Report deadlock, STOP
|
||||||
5. Update tasks.md: status=in-progress, agent={identifier}, started_at={now}
|
5. Update tasks.md: status=in-progress, agent={identifier}, started_at={now}
|
||||||
6. Delegate worker task:
|
6. Budget gate (before dispatch):
|
||||||
|
- Compute cumulative used + remaining estimate
|
||||||
|
- If projected total > budget cap: STOP and request user decision (reduce scope/phase/increase cap)
|
||||||
|
- If projected total is 70-90% of cap: run conservative mode (single worker)
|
||||||
|
7. Delegate worker task:
|
||||||
- native mode: spawn worker agent via runtime subagent/task primitive
|
- native mode: spawn worker agent via runtime subagent/task primitive
|
||||||
- matrix mode: enqueue/consume task in `.mosaic/orchestrator/tasks.json` and run `mosaic-orchestrator-matrix-cycle`
|
- matrix mode: enqueue/consume task in `.mosaic/orchestrator/tasks.json` and run `mosaic-orchestrator-matrix-cycle`
|
||||||
7. Wait for worker completion
|
8. Wait for worker completion
|
||||||
8. Parse worker result (JSON)
|
9. Parse worker result (JSON)
|
||||||
9. **Variance check**: Calculate (actual - estimate) / estimate × 100
|
10. **Variance check**: Calculate (actual - estimate) / estimate × 100
|
||||||
- If |variance| > 50%: Capture learning (see Learning & Retrospective)
|
- If |variance| > 50%: Capture learning (see Learning & Retrospective)
|
||||||
- If |variance| > 100%: Flag as CRITICAL — review task classification
|
- If |variance| > 100%: Flag as CRITICAL — review task classification
|
||||||
10. **Post-Coding Review** (see Phase 2b below)
|
11. **Post-Coding Review** (see Phase 2b below)
|
||||||
11. Update tasks.md: status=done/failed/needs-qa, completed_at={now}, used={actual}
|
12. **Documentation Gate**: Verify required docs were updated per `~/.config/mosaic/guides/DOCUMENTATION.md`
|
||||||
12. **Cleanup reports**: Remove processed report files for completed task
|
and checklist completed (`~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md`) when applicable.
|
||||||
|
13. **PR + CI + Issue Closure Gate** (HARD RULE for source-code tasks):
|
||||||
|
- Before merging, run queue guard:
|
||||||
|
`~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose merge -B main`
|
||||||
|
- Ensure PR exists for the task branch (create/update via wrappers if needed):
|
||||||
|
`~/.config/mosaic/rails/git/pr-create.sh ... -B main`
|
||||||
|
- Merge via wrapper:
|
||||||
|
`~/.config/mosaic/rails/git/pr-merge.sh -n {PR_NUMBER} -m squash`
|
||||||
|
- Wait for terminal CI status:
|
||||||
|
`~/.config/mosaic/rails/git/pr-ci-wait.sh -n {PR_NUMBER}`
|
||||||
|
- Close linked issue after merge + green CI:
|
||||||
|
`~/.config/mosaic/rails/git/issue-close.sh -i {ISSUE_NUMBER}`
|
||||||
|
- If any wrapper command fails, mark task `blocked`, record the exact failed wrapper command, report blocker, and STOP.
|
||||||
|
- Do NOT stop at "PR created" or "PR merged pending CI".
|
||||||
|
- Do NOT claim completion before CI is green and issue/internal ref is closed.
|
||||||
|
14. Update tasks.md: status=done/failed/needs-qa/blocked, completed_at={now}, used={actual}
|
||||||
|
15. Recalculate budget position:
|
||||||
|
- cumulative used
|
||||||
|
- projected remaining from estimates
|
||||||
|
- total projected at completion
|
||||||
|
16. **Cleanup reports**: Remove processed report files for completed task
|
||||||
```bash
|
```bash
|
||||||
# Find and remove reports matching the finding ID
|
# Find and remove reports matching the finding ID
|
||||||
find docs/reports/qa-automation/pending/ -name "*{finding_id}*" -delete 2>/dev/null || true
|
find docs/reports/qa-automation/pending/ -name "*{finding_id}*" -delete 2>/dev/null || true
|
||||||
# If task failed, move reports to escalated/ instead
|
# If task failed, move reports to escalated/ instead
|
||||||
```
|
```
|
||||||
13. Commit + push: git add docs/tasks.md .gitignore && git commit && git push
|
17. Commit + push: git add docs/TASKS.md .gitignore && git commit && git push
|
||||||
14. If phase verification task: Run phase retrospective, clean up all phase reports
|
18. If phase verification task: Run phase retrospective, clean up all phase reports
|
||||||
15. Check context usage
|
19. Check context usage
|
||||||
16. If >= 55%: Output COMPACTION REQUIRED checkpoint, STOP, wait for user
|
20. If >= 55%: Output COMPACTION REQUIRED checkpoint, STOP, wait for user
|
||||||
17. If < 55%: Go to step 1
|
21. Check budget usage:
|
||||||
18. After user runs /compact and says "continue": Go to step 1
|
- If projected total > cap: STOP and request user decision before new tasks
|
||||||
|
- If projected total is 70-90% of cap: continue in conservative mode
|
||||||
|
22. If < 55% context and within budget: Go to step 1
|
||||||
|
23. After user runs /compact and says "continue": Go to step 1
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -375,7 +527,7 @@ Review the code changes on branch {branch} against {base_branch}.
|
|||||||
- Security (OWASP Top 10, secrets, injection)
|
- Security (OWASP Top 10, secrets, injection)
|
||||||
- Testing (coverage, quality)
|
- Testing (coverage, quality)
|
||||||
- Code quality (complexity, duplication)
|
- Code quality (complexity, duplication)
|
||||||
3. Reference: ~/.config/mosaic/guides/code-review.md
|
3. Reference: ~/.config/mosaic/guides/CODE-REVIEW.md
|
||||||
|
|
||||||
Report findings as JSON:
|
Report findings as JSON:
|
||||||
```json
|
```json
|
||||||
@@ -432,26 +584,34 @@ Construct this from the task row and pass to worker via Task tool:
|
|||||||
|
|
||||||
## Workflow
|
## Workflow
|
||||||
|
|
||||||
1. Checkout branch: `git checkout {branch} || git checkout -b {branch} develop && git pull`
|
1. Checkout branch: `git fetch origin && (git checkout {branch} || git checkout -b {branch} origin/main) && git rebase origin/main`
|
||||||
2. Read the finding details from the report
|
2. Read `docs/PRD.md` or `docs/PRD.json` and align implementation with PRD requirements
|
||||||
3. Implement the fix following existing code patterns
|
3. Read the finding details from the report
|
||||||
4. Run quality gates (ALL must pass — zero lint errors, zero type errors, all tests green):
|
4. Implement the fix following existing code patterns
|
||||||
|
5. Run quality gates (ALL must pass — zero lint errors, zero type errors, all tests green):
|
||||||
```bash
|
```bash
|
||||||
{quality_gates_command}
|
{quality_gates_command}
|
||||||
```
|
```
|
||||||
**MANDATORY:** This ALWAYS includes linting. If the project has a linter configured
|
**MANDATORY:** This ALWAYS includes linting. If the project has a linter configured
|
||||||
(ESLint, Biome, ruff, etc.), you MUST run it and fix ALL violations in files you touched.
|
(ESLint, Biome, ruff, etc.), you MUST run it and fix ALL violations in files you touched.
|
||||||
Do NOT leave lint warnings or errors for someone else to clean up.
|
Do NOT leave lint warnings or errors for someone else to clean up.
|
||||||
5. If gates fail: Fix and retry. Do NOT report success with failures.
|
6. Run REQUIRED situational tests based on changed surfaces (see `~/.config/mosaic/guides/E2E-DELIVERY.md` and `~/.config/mosaic/guides/QA-TESTING.md`).
|
||||||
6. Commit: `git commit -m "fix({finding_id}): brief description"`
|
7. If task is bug fix/security/auth/critical business logic, apply REQUIRED TDD discipline per `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
7. Push: `git push origin {branch}`
|
8. If gates or required situational tests fail: Fix and retry. Do NOT report success with failures.
|
||||||
8. Report result as JSON (see format below)
|
9. Commit: `git commit -m "fix({finding_id}): brief description"`
|
||||||
|
10. Before push, run queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push -B main`
|
||||||
|
11. Push: `git push origin {branch}`
|
||||||
|
12. Report result as JSON (see format below)
|
||||||
|
|
||||||
## Git Scripts
|
## Git Scripts
|
||||||
|
|
||||||
For issue/PR/milestone operations, use scripts (NOT raw tea/gh):
|
For issue/PR/milestone operations, use scripts (NOT raw tea/gh):
|
||||||
- `~/.config/mosaic/rails/git/issue-view.sh -i {N}`
|
- `~/.config/mosaic/rails/git/issue-view.sh -i {N}`
|
||||||
- `~/.config/mosaic/rails/git/pr-create.sh -t "Title" -b "Desc" -B develop`
|
- `~/.config/mosaic/rails/git/pr-create.sh -t "Title" -b "Desc" -B main`
|
||||||
|
- `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`
|
||||||
|
- `~/.config/mosaic/rails/git/pr-merge.sh -n {PR_NUMBER} -m squash`
|
||||||
|
- `~/.config/mosaic/rails/git/pr-ci-wait.sh -n {PR_NUMBER}`
|
||||||
|
- `~/.config/mosaic/rails/git/issue-close.sh -i {N}`
|
||||||
|
|
||||||
Standard git commands (pull, commit, push, checkout) are fine.
|
Standard git commands (pull, commit, push, checkout) are fine.
|
||||||
|
|
||||||
@@ -469,6 +629,9 @@ End your response with this JSON block:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`status=success` means "code pushed and ready for orchestrator integration gates";
|
||||||
|
it does NOT mean PR merged/CI green/issue closed.
|
||||||
|
|
||||||
## Post-Coding Review
|
## Post-Coding Review
|
||||||
|
|
||||||
After you complete and push your changes, the orchestrator will independently
|
After you complete and push your changes, the orchestrator will independently
|
||||||
@@ -478,7 +641,7 @@ created. You do NOT need to run the review yourself — the orchestrator handles
|
|||||||
|
|
||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
- DO NOT modify docs/tasks.md
|
- DO NOT modify docs/TASKS.md
|
||||||
- DO NOT claim other tasks
|
- DO NOT claim other tasks
|
||||||
- Complete this single task, report results, done
|
- Complete this single task, report results, done
|
||||||
````
|
````
|
||||||
@@ -493,14 +656,14 @@ created. You do NOT need to run the review yourself — the orchestrator handles
|
|||||||
- Compaction causes **protocol drift** — agent "remembers" gist but loses specifics
|
- Compaction causes **protocol drift** — agent "remembers" gist but loses specifics
|
||||||
- Post-compaction agents may violate core rules (e.g., letting workers modify tasks.md)
|
- Post-compaction agents may violate core rules (e.g., letting workers modify tasks.md)
|
||||||
- Fresh orchestrator has **100% protocol fidelity**
|
- Fresh orchestrator has **100% protocol fidelity**
|
||||||
- All state lives in `docs/tasks.md` — the orchestrator is **stateless and replaceable**
|
- All state lives in `docs/TASKS.md` — the orchestrator is **stateless and replaceable**
|
||||||
|
|
||||||
**At threshold (55-60%):**
|
**At threshold (55-60%):**
|
||||||
|
|
||||||
1. Complete current task
|
1. Complete current task
|
||||||
2. Persist all state:
|
2. Persist all state:
|
||||||
- Update docs/tasks.md with all progress
|
- Update docs/TASKS.md with all progress
|
||||||
- Update docs/orchestrator-learnings.json with variances
|
- Update docs/tasks/orchestrator-learnings.json with variances
|
||||||
- Commit and push both files
|
- Commit and push both files
|
||||||
3. Output **ORCHESTRATOR HANDOFF** message with ready-to-use takeover kickstart
|
3. Output **ORCHESTRATOR HANDOFF** message with ready-to-use takeover kickstart
|
||||||
4. **STOP COMPLETELY** — do not continue working
|
4. **STOP COMPLETELY** — do not continue working
|
||||||
@@ -517,8 +680,8 @@ Progress: {completed}/{total} tasks ({percentage}%)
|
|||||||
Current phase: Phase {N} ({phase_name})
|
Current phase: Phase {N} ({phase_name})
|
||||||
|
|
||||||
State persisted:
|
State persisted:
|
||||||
- docs/tasks.md ✓
|
- docs/TASKS.md ✓
|
||||||
- docs/orchestrator-learnings.json ✓
|
- docs/tasks/orchestrator-learnings.json ✓
|
||||||
|
|
||||||
## Takeover Kickstart
|
## Takeover Kickstart
|
||||||
|
|
||||||
@@ -531,8 +694,8 @@ Continue {mission_description} from existing state.
|
|||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
- Project: {project_path}
|
- Project: {project_path}
|
||||||
- State: docs/tasks.md (already populated)
|
- State: docs/TASKS.md (already populated)
|
||||||
- Protocol: docs/claude/orchestrator.md
|
- Protocol: ~/.config/mosaic/guides/ORCHESTRATOR.md
|
||||||
- Quality gates: {quality_gates_command}
|
- Quality gates: {quality_gates_command}
|
||||||
|
|
||||||
## Resume Point
|
## Resume Point
|
||||||
@@ -541,11 +704,11 @@ Continue {mission_description} from existing state.
|
|||||||
- Progress: {completed}/{total} tasks ({percentage}%)
|
- Progress: {completed}/{total} tasks ({percentage}%)
|
||||||
|
|
||||||
## Instructions
|
## Instructions
|
||||||
1. Read docs/claude/orchestrator.md for protocol
|
1. Read ~/.config/mosaic/guides/ORCHESTRATOR.md for protocol
|
||||||
2. Read docs/tasks.md to understand current state
|
2. Read docs/TASKS.md to understand current state
|
||||||
3. Continue execution from task {task_id}
|
3. Continue execution from task {task_id}
|
||||||
4. Follow Two-Phase Completion Protocol
|
4. Follow Two-Phase Completion Protocol
|
||||||
5. You are the SOLE writer of docs/tasks.md
|
5. You are the SOLE writer of docs/TASKS.md
|
||||||
---
|
---
|
||||||
|
|
||||||
STOP: Terminate this session and spawn fresh orchestrator with the kickstart above.
|
STOP: Terminate this session and spawn fresh orchestrator with the kickstart above.
|
||||||
@@ -583,7 +746,7 @@ Each major phase uses a two-phase approach to maximize completion while managing
|
|||||||
| Architectural | Requires design change | Document and defer |
|
| Architectural | Requires design change | Document and defer |
|
||||||
|
|
||||||
3. **Work priority:** Quick-win → Medium → Hard
|
3. **Work priority:** Quick-win → Medium → Hard
|
||||||
4. **Document deferrals** in `docs/deferred-errors.md`:
|
4. **Document deferrals** in `docs/reports/deferred/deferred-errors.md`:
|
||||||
```markdown
|
```markdown
|
||||||
## {PREFIX}-XXX: [Error description]
|
## {PREFIX}-XXX: [Error description]
|
||||||
- File: path/to/file.ts:123
|
- File: path/to/file.ts:123
|
||||||
@@ -608,7 +771,7 @@ Do NOT proceed to the next major phase until the current phase reaches Polish co
|
|||||||
✅ Phase 2 Polish: 118 errors triaged
|
✅ Phase 2 Polish: 118 errors triaged
|
||||||
- 40 medium → fixed
|
- 40 medium → fixed
|
||||||
- 78 low → EACH documented with rationale
|
- 78 low → EACH documented with rationale
|
||||||
✅ Phase 2 Complete: Created docs/deferred-errors.md
|
✅ Phase 2 Complete: Created docs/reports/deferred/deferred-errors.md
|
||||||
→ NOW proceed to Phase 3
|
→ NOW proceed to Phase 3
|
||||||
|
|
||||||
❌ WRONG: Phase 2 at 91%, "low priority acceptable", starting Phase 3
|
❌ WRONG: Phase 2 at 91%, "low priority acceptable", starting Phase 3
|
||||||
@@ -643,7 +806,7 @@ Orchestrators capture learnings to improve future estimation accuracy.
|
|||||||
|----------|--------|
|
|----------|--------|
|
||||||
| 0-30% | Log only (acceptable) |
|
| 0-30% | Log only (acceptable) |
|
||||||
| 30-50% | Flag for review |
|
| 30-50% | Flag for review |
|
||||||
| 50-100% | Capture learning to `docs/orchestrator-learnings.json` |
|
| 50-100% | Capture learning to `docs/tasks/orchestrator-learnings.json` |
|
||||||
| >100% | CRITICAL — review task classification, possible mismatch |
|
| >100% | CRITICAL — review task classification, possible mismatch |
|
||||||
|
|
||||||
### Task Type Classification
|
### Task Type Classification
|
||||||
@@ -662,7 +825,7 @@ Classify tasks by description keywords for pattern analysis:
|
|||||||
|
|
||||||
### Capture Learning
|
### Capture Learning
|
||||||
|
|
||||||
When |variance| > 50%, append to `docs/orchestrator-learnings.json`:
|
When |variance| > 50%, append to `docs/tasks/orchestrator-learnings.json`:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -708,7 +871,7 @@ Next: MS-SEC-004
|
|||||||
|
|
||||||
### Cross-Project Learnings
|
### Cross-Project Learnings
|
||||||
|
|
||||||
Universal heuristics are maintained in `~/.config/mosaic/guides/orchestrator-learnings.md`.
|
Universal heuristics are maintained in `~/.config/mosaic/guides/ORCHESTRATOR-LEARNINGS.md`.
|
||||||
After completing a milestone, review variance patterns and propose updates to the universal guide.
|
After completing a milestone, review variance patterns and propose updates to the universal guide.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -736,7 +899,7 @@ docs/reports/qa-automation/
|
|||||||
| Task success | Delete matching reports from `pending/` |
|
| Task success | Delete matching reports from `pending/` |
|
||||||
| Task failed | Move reports to `escalated/` for investigation |
|
| Task failed | Move reports to `escalated/` for investigation |
|
||||||
| Phase verification | Clean up all `pending/` reports for that phase |
|
| Phase verification | Clean up all `pending/` reports for that phase |
|
||||||
| Milestone complete | Archive or delete entire `escalated/` directory |
|
| Milestone complete | Complete release + tag workflow, then archive or delete `escalated/` directory |
|
||||||
|
|
||||||
**Cleanup commands:**
|
**Cleanup commands:**
|
||||||
```bash
|
```bash
|
||||||
@@ -766,6 +929,11 @@ mv docs/reports/qa-automation/pending/*failing-file* docs/reports/qa-automation/
|
|||||||
2. Skip to next unblocked task if possible
|
2. Skip to next unblocked task if possible
|
||||||
3. If all remaining tasks blocked: Report blockers, STOP
|
3. If all remaining tasks blocked: Report blockers, STOP
|
||||||
|
|
||||||
|
**PR/CI/Issue wrapper failure:**
|
||||||
|
1. Record task status as `blocked` in `docs/TASKS.md`.
|
||||||
|
2. Record the exact failed wrapper command (full command line) in task notes and user report.
|
||||||
|
3. STOP orchestration for that task; do not mark complete and do not silently fall back to raw provider commands.
|
||||||
|
|
||||||
**Git push conflict:**
|
**Git push conflict:**
|
||||||
1. `git pull --rebase`
|
1. `git pull --rebase`
|
||||||
2. If auto-resolves: push again
|
2. If auto-resolves: push again
|
||||||
@@ -776,54 +944,151 @@ mv docs/reports/qa-automation/pending/*failing-file* docs/reports/qa-automation/
|
|||||||
## Stopping Criteria
|
## Stopping Criteria
|
||||||
|
|
||||||
**ONLY stop if:**
|
**ONLY stop if:**
|
||||||
1. All tasks in docs/tasks.md are `done`
|
1. All tasks in docs/TASKS.md are `done`
|
||||||
2. Critical blocker preventing progress (document and alert)
|
2. Critical blocker preventing progress (document and alert)
|
||||||
3. Context usage >= 55% — output COMPACTION REQUIRED checkpoint and wait
|
3. Context usage >= 55% — output COMPACTION REQUIRED checkpoint and wait
|
||||||
4. Absolute context limit reached AND cannot compact further
|
4. Absolute context limit reached AND cannot compact further
|
||||||
|
5. PRD is current and reflects delivered requirements (`docs/PRD.md` or `docs/PRD.json`)
|
||||||
|
6. Required documentation checklist is complete for applicable changes
|
||||||
|
7. For milestone completion, release + git tag steps are complete
|
||||||
|
8. For source-code tasks with external provider, merged PR evidence exists
|
||||||
|
9. For source-code tasks with external provider, CI/pipeline is terminal green
|
||||||
|
10. For linked external issues, closure is complete (or internal TASKS ref closure if no provider)
|
||||||
|
|
||||||
**DO NOT stop to ask "should I continue?"** — the answer is always YES.
|
**DO NOT stop to ask "should I continue?"** — the answer is always YES.
|
||||||
**DO stop at 55-60%** — output the compaction checkpoint and wait for user to run `/compact`.
|
**DO stop at 55-60%** — output the compaction checkpoint and wait for user to run `/compact`.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Sprint Completion Protocol
|
## Merge-to-Main Candidate Protocol (Container Deployments)
|
||||||
|
|
||||||
When all tasks in `docs/tasks.md` are `done` (or triaged as `deferred`), archive the sprint artifacts before stopping. This preserves them for post-mortems, variance calibration, and historical reference.
|
If deployment is in scope and container images are used, every merge to `main` MUST execute this protocol:
|
||||||
|
|
||||||
### Archive Steps
|
1. Build and push immutable candidate image tags:
|
||||||
|
- `sha-<shortsha>` (always)
|
||||||
|
- `v{base-version}-rc.{build}` (for `main` merges)
|
||||||
|
- `testing` mutable pointer to the same digest
|
||||||
|
2. Resolve and record the image digest for each service.
|
||||||
|
3. Deploy by digest to testing environment (never deploy by mutable tag alone).
|
||||||
|
4. Run full situational testing against images pulled from the registry.
|
||||||
|
5. If tests pass, promote the SAME digest (no rebuild) to environment pointers (`staging`/`prod` as applicable).
|
||||||
|
6. If tests fail, rollback to last known-good digest and create remediation tasks immediately.
|
||||||
|
|
||||||
1. **Create archive directory** (if it doesn't exist):
|
Hard rules:
|
||||||
|
- `latest` MUST NOT be used as a deployment reference.
|
||||||
|
- Final semantic release tags (`vX.Y.Z`) are milestone-level only.
|
||||||
|
- Intermediate checkpoints use RC image tags (`vX.Y.Z-rc.N`) and digest promotion.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Milestone Completion Protocol (Release + Tag Required)
|
||||||
|
|
||||||
|
When all tasks in `docs/TASKS.md` are `done` (or triaged as `deferred`), you MUST complete release/tag operations before declaring the milestone complete.
|
||||||
|
|
||||||
|
### Required Completion Steps
|
||||||
|
|
||||||
|
1. **Prepare release metadata**:
|
||||||
|
- `milestone-name` (human-readable)
|
||||||
|
- `milestone-version` (semantic version, e.g., `0.0.3`, `0.1.0`)
|
||||||
|
- `tag` = `v{milestone-version}` (e.g., `v0.0.3`)
|
||||||
|
|
||||||
|
2. **Verify documentation gate**:
|
||||||
|
- Confirm required docs were updated per `~/.config/mosaic/guides/DOCUMENTATION.md`.
|
||||||
|
- Confirm checklist completion: `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md`.
|
||||||
|
- If docs are incomplete, STOP and create remediation task(s) before release/tag.
|
||||||
|
|
||||||
|
3. **Create and push annotated git tag**:
|
||||||
```bash
|
```bash
|
||||||
mkdir -p docs/tasks/
|
git pull --rebase
|
||||||
|
git tag -a "v{milestone-version}" -m "Release v{milestone-version} - {milestone-name}"
|
||||||
|
git push origin "v{milestone-version}"
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Move tasks.md to archive:**
|
4. **Create repository release** (provider-specific):
|
||||||
|
|
||||||
|
Gitea:
|
||||||
```bash
|
```bash
|
||||||
mv docs/tasks.md docs/tasks/{milestone-name}-tasks.md
|
tea releases create \
|
||||||
|
--tag "v{milestone-version}" \
|
||||||
|
--title "v{milestone-version}" \
|
||||||
|
--note "Milestone {milestone-name} completed."
|
||||||
|
```
|
||||||
|
|
||||||
|
GitHub:
|
||||||
|
```bash
|
||||||
|
gh release create "v{milestone-version}" \
|
||||||
|
--title "v{milestone-version}" \
|
||||||
|
--notes "Milestone {milestone-name} completed."
|
||||||
|
```
|
||||||
|
|
||||||
|
GitLab:
|
||||||
|
```bash
|
||||||
|
glab release create "v{milestone-version}" \
|
||||||
|
--name "v{milestone-version}" \
|
||||||
|
--notes "Milestone {milestone-name} completed."
|
||||||
|
```
|
||||||
|
|
||||||
|
No external provider fallback:
|
||||||
|
- Create and push annotated tag as above.
|
||||||
|
- Create `docs/releases/v{milestone-version}.md` with release notes and include milestone completion summary.
|
||||||
|
|
||||||
|
5. **Close milestone in provider**:
|
||||||
|
- Gitea/GitHub:
|
||||||
|
```bash
|
||||||
|
~/.config/mosaic/rails/git/milestone-close.sh -t "{milestone-name}"
|
||||||
|
```
|
||||||
|
- GitLab: close milestone via provider workflow (CLI or web UI).
|
||||||
|
If provider tooling is unavailable, record milestone closure status in `docs/TASKS.md` notes.
|
||||||
|
|
||||||
|
6. **Archive sprint artifacts**:
|
||||||
|
```bash
|
||||||
|
mkdir -p docs/tasks/
|
||||||
|
mv docs/TASKS.md docs/tasks/{milestone-name}-tasks.md
|
||||||
|
mv docs/tasks/orchestrator-learnings.json docs/tasks/{milestone-name}-learnings.json
|
||||||
```
|
```
|
||||||
Example: `docs/tasks/M6-AgentOrchestration-Fixes-tasks.md`
|
Example: `docs/tasks/M6-AgentOrchestration-Fixes-tasks.md`
|
||||||
|
|
||||||
3. **Move learnings to archive:**
|
7. **Commit archive + release references**:
|
||||||
```bash
|
```bash
|
||||||
mv docs/orchestrator-learnings.json docs/tasks/{milestone-name}-learnings.json
|
git add docs/tasks/ docs/releases/ 2>/dev/null || true
|
||||||
```
|
git rm docs/TASKS.md docs/tasks/orchestrator-learnings.json 2>/dev/null || true
|
||||||
|
git commit -m "chore(orchestrator): Complete {milestone-name} milestone release
|
||||||
|
|
||||||
4. **Commit the archive:**
|
- Tagged: v{milestone-version}
|
||||||
```bash
|
- Release published
|
||||||
git add docs/tasks/
|
- Artifacts archived to docs/tasks/"
|
||||||
git rm docs/tasks.md docs/orchestrator-learnings.json 2>/dev/null || true
|
|
||||||
git commit -m "chore(orchestrator): Archive {milestone-name} sprint artifacts
|
|
||||||
|
|
||||||
{completed}/{total} tasks completed, {deferred} deferred.
|
|
||||||
Archived to docs/tasks/ for post-mortem reference."
|
|
||||||
git push
|
git push
|
||||||
```
|
```
|
||||||
|
|
||||||
5. **Run final retrospective** — review variance patterns and propose updates to estimation heuristics.
|
8. **Run final retrospective** — review variance patterns and propose updates to estimation heuristics.
|
||||||
|
|
||||||
|
### Deployment Protocol (When In Scope)
|
||||||
|
|
||||||
|
If the milestone includes deployment, orchestrator MUST complete deployment before final completion status:
|
||||||
|
|
||||||
|
1. Determine deployment target from PRD, project config, or environment:
|
||||||
|
- `Portainer`
|
||||||
|
- `Coolify`
|
||||||
|
- `Vercel`
|
||||||
|
- other configured SaaS provider
|
||||||
|
2. Trigger deployment using provider API/CLI/webhook.
|
||||||
|
3. Deployment method MUST be digest-first:
|
||||||
|
- Resolve digest from candidate image (`sha-*` or `vX.Y.Z-rc.N`),
|
||||||
|
- deploy that digest,
|
||||||
|
- promote tags (`testing`/`staging`/`prod`) only after validation.
|
||||||
|
4. Run post-deploy verification:
|
||||||
|
- health endpoint checks,
|
||||||
|
- critical smoke tests,
|
||||||
|
- release/version verification,
|
||||||
|
- digest verification (running digest equals promoted digest).
|
||||||
|
5. Default strategy is blue-green. Canary is allowed only if automated metrics, thresholds, and rollback triggers are configured.
|
||||||
|
6. If verification fails, execute rollback/redeploy-safe path and mark milestone `blocked` until stable.
|
||||||
|
7. Record deployment evidence in milestone release notes and `docs/TASKS.md` notes, including digest and promoted tags.
|
||||||
|
8. Ensure registry cleanup is scheduled/enforced (retain release tags + active digests, purge stale RC/sha tags).
|
||||||
|
|
||||||
### Recovery
|
### Recovery
|
||||||
|
|
||||||
If an orchestrator starts and `docs/tasks.md` does not exist, check `docs/tasks/` for the most recent archive:
|
If an orchestrator starts and `docs/TASKS.md` does not exist, check `docs/tasks/` for the most recent archive:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
ls -t docs/tasks/*-tasks.md 2>/dev/null | head -1
|
ls -t docs/tasks/*-tasks.md 2>/dev/null | head -1
|
||||||
@@ -832,7 +1097,7 @@ ls -t docs/tasks/*-tasks.md 2>/dev/null | head -1
|
|||||||
If found, this may indicate another session archived the file. The orchestrator should:
|
If found, this may indicate another session archived the file. The orchestrator should:
|
||||||
1. Report what it found in `docs/tasks/`
|
1. Report what it found in `docs/tasks/`
|
||||||
2. Ask whether to resume from the archived file or bootstrap fresh
|
2. Ask whether to resume from the archived file or bootstrap fresh
|
||||||
3. If resuming: copy the archive back to `docs/tasks.md` and continue
|
3. If resuming: copy the archive back to `docs/TASKS.md` and continue
|
||||||
|
|
||||||
### Retention Policy
|
### Retention Policy
|
||||||
|
|
||||||
@@ -860,7 +1125,7 @@ Remediate findings from the codebase review.
|
|||||||
- Task prefix: {PREFIX} (e.g., MS, UC)
|
- Task prefix: {PREFIX} (e.g., MS, UC)
|
||||||
|
|
||||||
## Protocol
|
## Protocol
|
||||||
Read ~/.config/mosaic/guides/orchestrator.md for full instructions.
|
Read ~/.config/mosaic/guides/ORCHESTRATOR.md for full instructions.
|
||||||
|
|
||||||
## Start
|
## Start
|
||||||
Bootstrap from the review report, then execute until complete.
|
Bootstrap from the review report, then execute until complete.
|
||||||
|
|||||||
@@ -1,202 +0,0 @@
|
|||||||
# QA & Testing Guide
|
|
||||||
|
|
||||||
## Before Starting
|
|
||||||
1. Check assigned issue: `~/.config/mosaic/rails/git/issue-list.sh -a @me`
|
|
||||||
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
|
|
||||||
3. Review existing test structure and patterns
|
|
||||||
|
|
||||||
## Test-Driven Development (TDD) Process
|
|
||||||
|
|
||||||
### The TDD Cycle
|
|
||||||
1. **Red**: Write a failing test first
|
|
||||||
2. **Green**: Write minimal code to pass
|
|
||||||
3. **Refactor**: Improve code while keeping tests green
|
|
||||||
|
|
||||||
### TDD Rules
|
|
||||||
- Never write production code without a failing test
|
|
||||||
- Write only enough test to fail
|
|
||||||
- Write only enough code to pass
|
|
||||||
- Refactor continuously
|
|
||||||
|
|
||||||
## Coverage Requirements
|
|
||||||
|
|
||||||
### Minimum Standards
|
|
||||||
- **Overall Coverage**: 85% minimum
|
|
||||||
- **Critical Paths**: 95% minimum (auth, payments, data mutations)
|
|
||||||
- **New Code**: 90% minimum
|
|
||||||
|
|
||||||
### What to Cover
|
|
||||||
- All public interfaces
|
|
||||||
- Error handling paths
|
|
||||||
- Edge cases and boundaries
|
|
||||||
- Integration points
|
|
||||||
|
|
||||||
### What NOT to Count
|
|
||||||
- Generated code
|
|
||||||
- Configuration files
|
|
||||||
- Third-party library wrappers (thin wrappers only)
|
|
||||||
|
|
||||||
## Test Categories
|
|
||||||
|
|
||||||
### Unit Tests
|
|
||||||
- Test single functions/methods in isolation
|
|
||||||
- Mock external dependencies
|
|
||||||
- Fast execution (< 100ms per test)
|
|
||||||
- No network, database, or filesystem access
|
|
||||||
|
|
||||||
```python
|
|
||||||
def test_calculate_discount_applies_percentage():
|
|
||||||
result = calculate_discount(100, 0.20)
|
|
||||||
assert result == 80
|
|
||||||
```
|
|
||||||
|
|
||||||
### Integration Tests
|
|
||||||
- Test multiple components together
|
|
||||||
- Use real databases (test containers)
|
|
||||||
- Test API contracts
|
|
||||||
- Slower execution acceptable
|
|
||||||
|
|
||||||
```python
|
|
||||||
def test_create_user_persists_to_database(db_session):
|
|
||||||
user = create_user(db_session, "test@example.com")
|
|
||||||
retrieved = get_user_by_email(db_session, "test@example.com")
|
|
||||||
assert retrieved.id == user.id
|
|
||||||
```
|
|
||||||
|
|
||||||
### End-to-End Tests
|
|
||||||
- Test complete user workflows
|
|
||||||
- Use real browser (Playwright, Cypress)
|
|
||||||
- Test critical paths only (expensive to maintain)
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
test('user can complete checkout', async ({ page }) => {
|
|
||||||
await page.goto('/products');
|
|
||||||
await page.click('[data-testid="add-to-cart"]');
|
|
||||||
await page.click('[data-testid="checkout"]');
|
|
||||||
await page.fill('#email', 'test@example.com');
|
|
||||||
await page.click('[data-testid="submit-order"]');
|
|
||||||
await expect(page.locator('.order-confirmation')).toBeVisible();
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Test Structure
|
|
||||||
|
|
||||||
### Naming Convention
|
|
||||||
```
|
|
||||||
test_{what}_{condition}_{expected_result}
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
- test_login_with_valid_credentials_returns_token
|
|
||||||
- test_login_with_invalid_password_returns_401
|
|
||||||
- test_get_user_when_not_found_returns_404
|
|
||||||
```
|
|
||||||
|
|
||||||
### Arrange-Act-Assert Pattern
|
|
||||||
```python
|
|
||||||
def test_add_item_to_cart_increases_count():
|
|
||||||
# Arrange
|
|
||||||
cart = Cart()
|
|
||||||
item = Item(id=1, name="Widget", price=9.99)
|
|
||||||
|
|
||||||
# Act
|
|
||||||
cart.add(item)
|
|
||||||
|
|
||||||
# Assert
|
|
||||||
assert cart.item_count == 1
|
|
||||||
assert cart.total == 9.99
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test Isolation
|
|
||||||
- Each test should be independent
|
|
||||||
- Use setup/teardown for common state
|
|
||||||
- Clean up after tests
|
|
||||||
- Don't rely on test execution order
|
|
||||||
|
|
||||||
## Mocking Guidelines
|
|
||||||
|
|
||||||
### When to Mock
|
|
||||||
- External APIs and services
|
|
||||||
- Time-dependent operations
|
|
||||||
- Random number generation
|
|
||||||
- Expensive operations
|
|
||||||
|
|
||||||
### When NOT to Mock
|
|
||||||
- The code under test
|
|
||||||
- Simple data structures
|
|
||||||
- Database in integration tests
|
|
||||||
|
|
||||||
### Mock Example
|
|
||||||
```python
|
|
||||||
def test_send_notification_calls_email_service(mocker):
|
|
||||||
mock_email = mocker.patch('services.email.send')
|
|
||||||
|
|
||||||
send_notification(user_id=1, message="Hello")
|
|
||||||
|
|
||||||
mock_email.assert_called_once_with(
|
|
||||||
to="user@example.com",
|
|
||||||
subject="Notification",
|
|
||||||
body="Hello"
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Test Data Management
|
|
||||||
|
|
||||||
### Fixtures
|
|
||||||
- Use factories for complex objects
|
|
||||||
- Keep test data close to tests
|
|
||||||
- Use realistic but anonymized data
|
|
||||||
|
|
||||||
### Database Tests
|
|
||||||
- Use transactions with rollback
|
|
||||||
- Or use test containers
|
|
||||||
- Never test against production data
|
|
||||||
|
|
||||||
## Reporting
|
|
||||||
|
|
||||||
### Test Reports Should Include
|
|
||||||
- Total tests run
|
|
||||||
- Pass/fail counts
|
|
||||||
- Coverage percentage
|
|
||||||
- Execution time
|
|
||||||
- Flaky test identification
|
|
||||||
|
|
||||||
### QA Report Template
|
|
||||||
```markdown
|
|
||||||
# QA Report - Issue #{number}
|
|
||||||
|
|
||||||
## Summary
|
|
||||||
- Tests Added: X
|
|
||||||
- Tests Modified: Y
|
|
||||||
- Coverage: XX%
|
|
||||||
|
|
||||||
## Test Results
|
|
||||||
- Passed: X
|
|
||||||
- Failed: X
|
|
||||||
- Skipped: X
|
|
||||||
|
|
||||||
## Coverage Analysis
|
|
||||||
- Lines: XX%
|
|
||||||
- Branches: XX%
|
|
||||||
- Functions: XX%
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
[Any observations or concerns]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Commit Format
|
|
||||||
```
|
|
||||||
test(#34): Add user registration tests
|
|
||||||
|
|
||||||
- Unit tests for validation logic
|
|
||||||
- Integration tests for /api/users endpoint
|
|
||||||
- Coverage increased from 72% to 87%
|
|
||||||
|
|
||||||
Refs #34
|
|
||||||
```
|
|
||||||
|
|
||||||
## Before Completing
|
|
||||||
1. All tests pass locally
|
|
||||||
2. Coverage meets 85% threshold
|
|
||||||
3. No flaky tests introduced
|
|
||||||
4. CI pipeline passes
|
|
||||||
5. Update scratchpad with results
|
|
||||||
15
install.ps1
15
install.ps1
@@ -143,6 +143,21 @@ catch {
|
|||||||
Write-Warn "Runtime asset linking failed (non-fatal)"
|
Write-Warn "Runtime asset linking failed (non-fatal)"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
& "$binDir\mosaic-ensure-sequential-thinking.ps1" *>$null
|
||||||
|
Write-Ok "sequential-thinking MCP configured"
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
if ($env:MOSAIC_ALLOW_MISSING_SEQUENTIAL_THINKING -eq "1") {
|
||||||
|
Write-Warn "sequential-thinking MCP setup failed but bypassed (MOSAIC_ALLOW_MISSING_SEQUENTIAL_THINKING=1)"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Fail "sequential-thinking MCP setup failed (hard requirement)."
|
||||||
|
Write-Fail "Set MOSAIC_ALLOW_MISSING_SEQUENTIAL_THINKING=1 only for temporary bypass scenarios."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($env:MOSAIC_SKIP_SKILLS_SYNC -eq "1") {
|
if ($env:MOSAIC_SKIP_SKILLS_SYNC -eq "1") {
|
||||||
Write-Ok "Skills sync skipped (MOSAIC_SKIP_SKILLS_SYNC=1)"
|
Write-Ok "Skills sync skipped (MOSAIC_SKIP_SKILLS_SYNC=1)"
|
||||||
}
|
}
|
||||||
|
|||||||
12
install.sh
12
install.sh
@@ -151,6 +151,18 @@ else
|
|||||||
warn "Runtime asset linking failed (non-fatal)"
|
warn "Runtime asset linking failed (non-fatal)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if "$TARGET_DIR/bin/mosaic-ensure-sequential-thinking" >/dev/null 2>&1; then
|
||||||
|
ok "sequential-thinking MCP configured"
|
||||||
|
else
|
||||||
|
if [[ "${MOSAIC_ALLOW_MISSING_SEQUENTIAL_THINKING:-0}" == "1" ]]; then
|
||||||
|
warn "sequential-thinking MCP setup failed but bypassed (MOSAIC_ALLOW_MISSING_SEQUENTIAL_THINKING=1)"
|
||||||
|
else
|
||||||
|
fail "sequential-thinking MCP setup failed (hard requirement)."
|
||||||
|
fail "Set MOSAIC_ALLOW_MISSING_SEQUENTIAL_THINKING=1 only for temporary bypass scenarios."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "${MOSAIC_SKIP_SKILLS_SYNC:-0}" == "1" ]]; then
|
if [[ "${MOSAIC_SKIP_SKILLS_SYNC:-0}" == "1" ]]; then
|
||||||
ok "Skills sync skipped (MOSAIC_SKIP_SKILLS_SYNC=1)"
|
ok "Skills sync skipped (MOSAIC_SKIP_SKILLS_SYNC=1)"
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Profiles are runtime-neutral context packs that can be consumed by any agent run
|
|||||||
|
|
||||||
Current runtime overlay example:
|
Current runtime overlay example:
|
||||||
|
|
||||||
- `~/.config/mosaic/runtime/claude/settings-overlays/jarvis-ralph.json`
|
- `~/.config/mosaic/runtime/claude/settings-overlays/jarvis-loop.json`
|
||||||
|
|
||||||
## Claude Compatibility
|
## Claude Compatibility
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
# agent-lint.sh --fix-hint # Show fix commands for failures
|
# agent-lint.sh --fix-hint # Show fix commands for failures
|
||||||
#
|
#
|
||||||
# Checks per project:
|
# Checks per project:
|
||||||
# 1. Has CLAUDE.md?
|
# 1. Has runtime context file (CLAUDE.md or RUNTIME.md)?
|
||||||
# 2. Has AGENTS.md?
|
# 2. Has AGENTS.md?
|
||||||
# 3. CLAUDE.md references conditional context/guides?
|
# 3. Runtime context file references conditional context/guides?
|
||||||
# 4. CLAUDE.md has quality gates?
|
# 4. Runtime context file has quality gates?
|
||||||
# 5. For monorepos: sub-directories have AGENTS.md?
|
# 5. For monorepos: sub-directories have AGENTS.md?
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
@@ -92,9 +92,23 @@ is_monorepo() {
|
|||||||
(grep -q '"workspaces"' "$dir/package.json" 2>/dev/null)
|
(grep -q '"workspaces"' "$dir/package.json" 2>/dev/null)
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check for CLAUDE.md
|
# Resolve runtime context file (CLAUDE.md or RUNTIME.md)
|
||||||
check_claude_md() {
|
runtime_context_file() {
|
||||||
[[ -f "$1/CLAUDE.md" ]]
|
local dir="$1"
|
||||||
|
if [[ -f "$dir/CLAUDE.md" ]]; then
|
||||||
|
echo "$dir/CLAUDE.md"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [[ -f "$dir/RUNTIME.md" ]]; then
|
||||||
|
echo "$dir/RUNTIME.md"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for runtime context file
|
||||||
|
check_runtime_context() {
|
||||||
|
[[ -n "$(runtime_context_file "$1")" ]]
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check for AGENTS.md
|
# Check for AGENTS.md
|
||||||
@@ -104,14 +118,16 @@ check_agents_md() {
|
|||||||
|
|
||||||
# Check conditional loading/context (references guides or conditional section)
|
# Check conditional loading/context (references guides or conditional section)
|
||||||
check_conditional_loading() {
|
check_conditional_loading() {
|
||||||
local claude_md="$1/CLAUDE.md"
|
local ctx
|
||||||
[[ -f "$claude_md" ]] && grep -qi "agent-guides\|~/.config/mosaic/guides\|conditional.*loading\|conditional.*documentation\|conditional.*context" "$claude_md" 2>/dev/null
|
ctx="$(runtime_context_file "$1")"
|
||||||
|
[[ -n "$ctx" ]] && grep -qi "agent-guides\|~/.config/mosaic/guides\|conditional.*loading\|conditional.*documentation\|conditional.*context" "$ctx" 2>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check quality gates
|
# Check quality gates
|
||||||
check_quality_gates() {
|
check_quality_gates() {
|
||||||
local claude_md="$1/CLAUDE.md"
|
local ctx
|
||||||
[[ -f "$claude_md" ]] && grep -qi "quality.gates\|must pass before\|lint\|typecheck\|test" "$claude_md" 2>/dev/null
|
ctx="$(runtime_context_file "$1")"
|
||||||
|
[[ -n "$ctx" ]] && grep -qi "quality.gates\|must pass before\|lint\|typecheck\|test" "$ctx" 2>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check monorepo sub-AGENTS.md
|
# Check monorepo sub-AGENTS.md
|
||||||
@@ -152,16 +168,16 @@ lint_project() {
|
|||||||
local name
|
local name
|
||||||
name=$(basename "$dir")
|
name=$(basename "$dir")
|
||||||
|
|
||||||
local has_claude has_agents has_guides has_quality mono_status
|
local has_runtime has_agents has_guides has_quality mono_status
|
||||||
local score=0 max_score=4
|
local score=0 max_score=4
|
||||||
|
|
||||||
check_claude_md "$dir" && has_claude="OK" || has_claude="MISS"
|
check_runtime_context "$dir" && has_runtime="OK" || has_runtime="MISS"
|
||||||
check_agents_md "$dir" && has_agents="OK" || has_agents="MISS"
|
check_agents_md "$dir" && has_agents="OK" || has_agents="MISS"
|
||||||
check_conditional_loading "$dir" && has_guides="OK" || has_guides="MISS"
|
check_conditional_loading "$dir" && has_guides="OK" || has_guides="MISS"
|
||||||
check_quality_gates "$dir" && has_quality="OK" || has_quality="MISS"
|
check_quality_gates "$dir" && has_quality="OK" || has_quality="MISS"
|
||||||
mono_status=$(check_monorepo_sub_agents "$dir")
|
mono_status=$(check_monorepo_sub_agents "$dir")
|
||||||
|
|
||||||
[[ "$has_claude" == "OK" ]] && ((score++)) || true
|
[[ "$has_runtime" == "OK" ]] && ((score++)) || true
|
||||||
[[ "$has_agents" == "OK" ]] && ((score++)) || true
|
[[ "$has_agents" == "OK" ]] && ((score++)) || true
|
||||||
[[ "$has_guides" == "OK" ]] && ((score++)) || true
|
[[ "$has_guides" == "OK" ]] && ((score++)) || true
|
||||||
[[ "$has_quality" == "OK" ]] && ((score++)) || true
|
[[ "$has_quality" == "OK" ]] && ((score++)) || true
|
||||||
@@ -171,7 +187,7 @@ lint_project() {
|
|||||||
{
|
{
|
||||||
"project": "$name",
|
"project": "$name",
|
||||||
"path": "$dir",
|
"path": "$dir",
|
||||||
"claude_md": "$has_claude",
|
"runtime_context": "$has_runtime",
|
||||||
"agents_md": "$has_agents",
|
"agents_md": "$has_agents",
|
||||||
"conditional_loading": "$has_guides",
|
"conditional_loading": "$has_guides",
|
||||||
"quality_gates": "$has_quality",
|
"quality_gates": "$has_quality",
|
||||||
@@ -182,8 +198,8 @@ lint_project() {
|
|||||||
JSONEOF
|
JSONEOF
|
||||||
else
|
else
|
||||||
# Color-code the status
|
# Color-code the status
|
||||||
local c_claude c_agents c_guides c_quality
|
local c_runtime c_agents c_guides c_quality
|
||||||
[[ "$has_claude" == "OK" ]] && c_claude="${GREEN} OK ${NC}" || c_claude="${RED} MISS ${NC}"
|
[[ "$has_runtime" == "OK" ]] && c_runtime="${GREEN} OK ${NC}" || c_runtime="${RED} MISS ${NC}"
|
||||||
[[ "$has_agents" == "OK" ]] && c_agents="${GREEN} OK ${NC}" || c_agents="${RED} MISS ${NC}"
|
[[ "$has_agents" == "OK" ]] && c_agents="${GREEN} OK ${NC}" || c_agents="${RED} MISS ${NC}"
|
||||||
[[ "$has_guides" == "OK" ]] && c_guides="${GREEN} OK ${NC}" || c_guides="${RED} MISS ${NC}"
|
[[ "$has_guides" == "OK" ]] && c_guides="${GREEN} OK ${NC}" || c_guides="${RED} MISS ${NC}"
|
||||||
[[ "$has_quality" == "OK" ]] && c_quality="${GREEN} OK ${NC}" || c_quality="${RED} MISS ${NC}"
|
[[ "$has_quality" == "OK" ]] && c_quality="${GREEN} OK ${NC}" || c_quality="${RED} MISS ${NC}"
|
||||||
@@ -193,7 +209,7 @@ JSONEOF
|
|||||||
[[ $score -eq 4 ]] && score_color="$GREEN"
|
[[ $score -eq 4 ]] && score_color="$GREEN"
|
||||||
|
|
||||||
printf " %-35s %b %b %b %b ${score_color}%d/%d${NC}" \
|
printf " %-35s %b %b %b %b ${score_color}%d/%d${NC}" \
|
||||||
"$name" "$c_claude" "$c_agents" "$c_guides" "$c_quality" "$score" "$max_score"
|
"$name" "$c_runtime" "$c_agents" "$c_guides" "$c_quality" "$score" "$max_score"
|
||||||
|
|
||||||
# Show monorepo status if applicable
|
# Show monorepo status if applicable
|
||||||
if [[ "$mono_status" != "N/A" && "$mono_status" != "OK" ]]; then
|
if [[ "$mono_status" != "N/A" && "$mono_status" != "OK" ]]; then
|
||||||
@@ -203,7 +219,7 @@ JSONEOF
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if $VERBOSE && ! $JSON_OUTPUT; then
|
if $VERBOSE && ! $JSON_OUTPUT; then
|
||||||
[[ "$has_claude" == "MISS" ]] && echo " ${DIM} CLAUDE.md missing${NC}"
|
[[ "$has_runtime" == "MISS" ]] && echo " ${DIM} Runtime context file missing (CLAUDE.md or RUNTIME.md)${NC}"
|
||||||
[[ "$has_agents" == "MISS" ]] && echo " ${DIM} AGENTS.md missing${NC}"
|
[[ "$has_agents" == "MISS" ]] && echo " ${DIM} AGENTS.md missing${NC}"
|
||||||
[[ "$has_guides" == "MISS" ]] && echo " ${DIM} No conditional context/loading section detected${NC}"
|
[[ "$has_guides" == "MISS" ]] && echo " ${DIM} No conditional context/loading section detected${NC}"
|
||||||
[[ "$has_quality" == "MISS" ]] && echo " ${DIM} No quality gates section${NC}"
|
[[ "$has_quality" == "MISS" ]] && echo " ${DIM} No quality gates section${NC}"
|
||||||
@@ -213,7 +229,7 @@ JSONEOF
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if $FIX_HINT && ! $JSON_OUTPUT; then
|
if $FIX_HINT && ! $JSON_OUTPUT; then
|
||||||
if [[ "$has_claude" == "MISS" || "$has_agents" == "MISS" ]]; then
|
if [[ "$has_runtime" == "MISS" || "$has_agents" == "MISS" ]]; then
|
||||||
echo " ${DIM}Fix: ~/.config/mosaic/rails/bootstrap/init-project.sh --name \"$name\" --type auto${NC}"
|
echo " ${DIM}Fix: ~/.config/mosaic/rails/bootstrap/init-project.sh --name \"$name\" --type auto${NC}"
|
||||||
elif [[ "$has_guides" == "MISS" ]]; then
|
elif [[ "$has_guides" == "MISS" ]]; then
|
||||||
echo " ${DIM}Fix: ~/.config/mosaic/rails/bootstrap/agent-upgrade.sh $dir --section conditional-loading${NC}"
|
echo " ${DIM}Fix: ~/.config/mosaic/rails/bootstrap/agent-upgrade.sh $dir --section conditional-loading${NC}"
|
||||||
@@ -258,7 +274,7 @@ main() {
|
|||||||
echo -e "${BOLD}Agent Configuration Audit — $(date +%Y-%m-%d)${NC}"
|
echo -e "${BOLD}Agent Configuration Audit — $(date +%Y-%m-%d)${NC}"
|
||||||
echo "========================================================"
|
echo "========================================================"
|
||||||
printf " %-35s %s %s %s %s %s\n" \
|
printf " %-35s %s %s %s %s %s\n" \
|
||||||
"Project" "CLAUDE" "AGENTS" "Guides" "Quality" "Score"
|
"Project" "RUNTIME" "AGENTS" "Guides" "Quality" "Score"
|
||||||
echo " -----------------------------------------------------------------------"
|
echo " -----------------------------------------------------------------------"
|
||||||
|
|
||||||
for dir in "${projects[@]}"; do
|
for dir in "${projects[@]}"; do
|
||||||
|
|||||||
@@ -113,6 +113,19 @@ has_section() {
|
|||||||
[[ -f "$file" ]] && grep -qi "$pattern" "$file" 2>/dev/null
|
[[ -f "$file" ]] && grep -qi "$pattern" "$file" 2>/dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
runtime_context_file() {
|
||||||
|
local project_dir="$1"
|
||||||
|
if [[ -f "$project_dir/CLAUDE.md" ]]; then
|
||||||
|
echo "$project_dir/CLAUDE.md"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [[ -f "$project_dir/RUNTIME.md" ]]; then
|
||||||
|
echo "$project_dir/RUNTIME.md"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
echo "$project_dir/CLAUDE.md"
|
||||||
|
}
|
||||||
|
|
||||||
backup_file() {
|
backup_file() {
|
||||||
local file="$1"
|
local file="$1"
|
||||||
if [[ -f "$file" ]] && ! $DRY_RUN; then
|
if [[ -f "$file" ]] && ! $DRY_RUN; then
|
||||||
@@ -124,7 +137,8 @@ backup_file() {
|
|||||||
inject_fragment() {
|
inject_fragment() {
|
||||||
local project_dir="$1"
|
local project_dir="$1"
|
||||||
local fragment_name="$2"
|
local fragment_name="$2"
|
||||||
local claude_md="$project_dir/CLAUDE.md"
|
local ctx_file
|
||||||
|
ctx_file="$(runtime_context_file "$project_dir")"
|
||||||
local fragment_file="$FRAGMENTS_DIR/$fragment_name.md"
|
local fragment_file="$FRAGMENTS_DIR/$fragment_name.md"
|
||||||
|
|
||||||
if [[ ! -f "$fragment_file" ]]; then
|
if [[ ! -f "$fragment_file" ]]; then
|
||||||
@@ -144,12 +158,12 @@ inject_fragment() {
|
|||||||
*) echo "Unknown fragment: $fragment_name"; return 1 ;;
|
*) echo "Unknown fragment: $fragment_name"; return 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [[ ! -f "$claude_md" ]]; then
|
if [[ ! -f "$ctx_file" ]]; then
|
||||||
echo -e " ${YELLOW}No CLAUDE.md — skipping fragment injection${NC}"
|
echo -e " ${YELLOW}No runtime context file (CLAUDE.md/RUNTIME.md) — skipping fragment injection${NC}"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if has_section "$claude_md" "$detect_pattern"; then
|
if has_section "$ctx_file" "$detect_pattern"; then
|
||||||
echo -e " ${DIM}$fragment_name already present${NC}"
|
echo -e " ${DIM}$fragment_name already present${NC}"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -157,10 +171,10 @@ inject_fragment() {
|
|||||||
if $DRY_RUN; then
|
if $DRY_RUN; then
|
||||||
echo -e " ${GREEN}Would inject: $fragment_name${NC}"
|
echo -e " ${GREEN}Would inject: $fragment_name${NC}"
|
||||||
else
|
else
|
||||||
backup_file "$claude_md"
|
backup_file "$ctx_file"
|
||||||
echo "" >> "$claude_md"
|
echo "" >> "$ctx_file"
|
||||||
cat "$fragment_file" >> "$claude_md"
|
cat "$fragment_file" >> "$ctx_file"
|
||||||
echo "" >> "$claude_md"
|
echo "" >> "$ctx_file"
|
||||||
echo -e " ${GREEN}Injected: $fragment_name${NC}"
|
echo -e " ${GREEN}Injected: $fragment_name${NC}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@@ -257,8 +271,8 @@ upgrade_project() {
|
|||||||
# Always try conditional-loading (highest impact)
|
# Always try conditional-loading (highest impact)
|
||||||
inject_fragment "$dir" "conditional-loading"
|
inject_fragment "$dir" "conditional-loading"
|
||||||
|
|
||||||
# Try other fragments if CLAUDE.md exists
|
# Try other fragments if runtime context exists
|
||||||
if [[ -f "$dir/CLAUDE.md" ]]; then
|
if [[ -f "$dir/CLAUDE.md" || -f "$dir/RUNTIME.md" ]]; then
|
||||||
inject_fragment "$dir" "commit-format"
|
inject_fragment "$dir" "commit-format"
|
||||||
inject_fragment "$dir" "secrets"
|
inject_fragment "$dir" "secrets"
|
||||||
inject_fragment "$dir" "multi-agent"
|
inject_fragment "$dir" "multi-agent"
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ set -e
|
|||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
TEMPLATE_DIR="$HOME/.config/mosaic/templates/agent"
|
TEMPLATE_DIR="$HOME/.config/mosaic/templates/agent"
|
||||||
GIT_SCRIPT_DIR="$HOME/.config/mosaic/rails/git"
|
GIT_SCRIPT_DIR="$HOME/.config/mosaic/rails/git"
|
||||||
|
SEQUENTIAL_MCP_SCRIPT="$HOME/.config/mosaic/bin/mosaic-ensure-sequential-thinking"
|
||||||
|
|
||||||
# Defaults
|
# Defaults
|
||||||
PROJECT_NAME=""
|
PROJECT_NAME=""
|
||||||
@@ -320,10 +321,14 @@ fi
|
|||||||
|
|
||||||
if [[ "$DRY_RUN" == true ]]; then
|
if [[ "$DRY_RUN" == true ]]; then
|
||||||
echo "[DRY RUN] Would create:"
|
echo "[DRY RUN] Would create:"
|
||||||
|
echo " - Validate sequential-thinking MCP hard requirement"
|
||||||
echo " - CLAUDE.md (from $STACK_TEMPLATE_DIR/CLAUDE.md.template)"
|
echo " - CLAUDE.md (from $STACK_TEMPLATE_DIR/CLAUDE.md.template)"
|
||||||
echo " - AGENTS.md (from $STACK_TEMPLATE_DIR/AGENTS.md.template)"
|
echo " - AGENTS.md (from $STACK_TEMPLATE_DIR/AGENTS.md.template)"
|
||||||
echo " - docs/scratchpads/"
|
echo " - docs/scratchpads/"
|
||||||
echo " - docs/reports/"
|
echo " - docs/reports/qa-automation/{pending,in-progress,done,escalated}"
|
||||||
|
echo " - docs/reports/deferred/"
|
||||||
|
echo " - docs/tasks/"
|
||||||
|
echo " - docs/releases/"
|
||||||
echo " - docs/templates/"
|
echo " - docs/templates/"
|
||||||
if [[ "$SKIP_CI" != true ]]; then
|
if [[ "$SKIP_CI" != true ]]; then
|
||||||
echo " - .woodpecker/codex-review.yml"
|
echo " - .woodpecker/codex-review.yml"
|
||||||
@@ -331,7 +336,8 @@ if [[ "$DRY_RUN" == true ]]; then
|
|||||||
fi
|
fi
|
||||||
if [[ "$SKIP_LABELS" != true ]]; then
|
if [[ "$SKIP_LABELS" != true ]]; then
|
||||||
echo " - Standard git labels (epic, feature, bug, task, documentation, security, breaking)"
|
echo " - Standard git labels (epic, feature, bug, task, documentation, security, breaking)"
|
||||||
echo " - Milestone: 0.1.0 - MVP"
|
echo " - Milestone: 0.0.1 - Pre-MVP Foundation"
|
||||||
|
echo " - Milestone policy: 0.0.x pre-MVP, 0.1.0 for MVP release"
|
||||||
fi
|
fi
|
||||||
if [[ "$CICD_DOCKER" == true ]]; then
|
if [[ "$CICD_DOCKER" == true ]]; then
|
||||||
echo " - Docker build/push/link steps appended to .woodpecker.yml"
|
echo " - Docker build/push/link steps appended to .woodpecker.yml"
|
||||||
@@ -343,6 +349,21 @@ if [[ "$DRY_RUN" == true ]]; then
|
|||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Enforce sequential-thinking MCP hard requirement.
|
||||||
|
if [[ ! -x "$SEQUENTIAL_MCP_SCRIPT" ]]; then
|
||||||
|
echo "Error: Missing sequential-thinking setup helper: $SEQUENTIAL_MCP_SCRIPT" >&2
|
||||||
|
echo "Install/repair Mosaic at ~/.config/mosaic before bootstrapping projects." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if "$SEQUENTIAL_MCP_SCRIPT" >/dev/null 2>&1; then
|
||||||
|
echo "Verified sequential-thinking MCP configuration"
|
||||||
|
else
|
||||||
|
echo "Error: sequential-thinking MCP setup failed (hard requirement)." >&2
|
||||||
|
echo "Run: $SEQUENTIAL_MCP_SCRIPT" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Create CLAUDE.md
|
# Create CLAUDE.md
|
||||||
if [[ -f "CLAUDE.md" ]]; then
|
if [[ -f "CLAUDE.md" ]]; then
|
||||||
echo "CLAUDE.md already exists — skipping (rename or delete to recreate)"
|
echo "CLAUDE.md already exists — skipping (rename or delete to recreate)"
|
||||||
@@ -368,8 +389,17 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Create directories
|
# Create directories
|
||||||
mkdir -p docs/scratchpads docs/reports docs/templates
|
mkdir -p \
|
||||||
echo "Created docs/scratchpads/, docs/reports/, docs/templates/"
|
docs/scratchpads \
|
||||||
|
docs/reports/qa-automation/pending \
|
||||||
|
docs/reports/qa-automation/in-progress \
|
||||||
|
docs/reports/qa-automation/done \
|
||||||
|
docs/reports/qa-automation/escalated \
|
||||||
|
docs/reports/deferred \
|
||||||
|
docs/tasks \
|
||||||
|
docs/releases \
|
||||||
|
docs/templates
|
||||||
|
echo "Created docs/scratchpads/, docs/reports/*, docs/tasks/, docs/releases/, docs/templates/"
|
||||||
|
|
||||||
# Set up CI/CD pipeline
|
# Set up CI/CD pipeline
|
||||||
if [[ "$SKIP_CI" != true ]]; then
|
if [[ "$SKIP_CI" != true ]]; then
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ while [[ $# -gt 0 ]]; do
|
|||||||
echo "Create standard labels and initial milestone for the current repository."
|
echo "Create standard labels and initial milestone for the current repository."
|
||||||
echo ""
|
echo ""
|
||||||
echo "Options:"
|
echo "Options:"
|
||||||
echo " --skip-milestone Skip creating the 0.1.0 MVP milestone"
|
echo " --skip-milestone Skip creating the 0.0.1 pre-MVP milestone"
|
||||||
echo " -h, --help Show this help"
|
echo " -h, --help Show this help"
|
||||||
exit 0
|
exit 0
|
||||||
;;
|
;;
|
||||||
@@ -107,14 +107,16 @@ done
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
# Create initial milestone
|
# Create initial pre-MVP milestone
|
||||||
if [[ "$SKIP_MILESTONE" != true ]]; then
|
if [[ "$SKIP_MILESTONE" != true ]]; then
|
||||||
echo "Creating initial milestone..."
|
echo "Creating initial pre-MVP milestone..."
|
||||||
|
|
||||||
"$GIT_SCRIPT_DIR/milestone-create.sh" -t "0.1.0" -d "MVP - Minimum Viable Product" 2>/dev/null && \
|
"$GIT_SCRIPT_DIR/milestone-create.sh" -t "0.0.1" -d "Pre-MVP - Foundation Sprint" 2>/dev/null && \
|
||||||
echo " [created] Milestone '0.1.0 - MVP'" || \
|
echo " [created] Milestone '0.0.1 - Pre-MVP'" || \
|
||||||
echo " [skip] Milestone may already exist or creation failed"
|
echo " [skip] Milestone may already exist or creation failed"
|
||||||
|
|
||||||
|
echo " [note] Reserve 0.1.0 for MVP release milestone"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -260,6 +260,6 @@ For best results, use `gpt-5.2-codex` or newer for strongest review accuracy.
|
|||||||
|
|
||||||
## See Also
|
## See Also
|
||||||
|
|
||||||
- `~/.config/mosaic/guides/code-review.md` — Manual code review checklist
|
- `~/.config/mosaic/guides/CODE-REVIEW.md` — Manual code review checklist
|
||||||
- `~/.config/mosaic/rails/git/` — Git helper scripts (issue/PR management)
|
- `~/.config/mosaic/rails/git/` — Git helper scripts (issue/PR management)
|
||||||
- OpenAI Codex CLI docs: https://developers.openai.com/codex/cli/
|
- OpenAI Codex CLI docs: https://developers.openai.com/codex/cli/
|
||||||
|
|||||||
247
rails/git/ci-queue-wait.ps1
Normal file
247
rails/git/ci-queue-wait.ps1
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
# ci-queue-wait.ps1 - Wait until project CI queue is clear (no running/queued pipeline on branch head)
|
||||||
|
# Usage: .\ci-queue-wait.ps1 [-Branch main] [-TimeoutSeconds 900] [-IntervalSeconds 15] [-Purpose merge] [-RequireStatus]
|
||||||
|
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[Alias("B")]
|
||||||
|
[string]$Branch = "main",
|
||||||
|
|
||||||
|
[Alias("t")]
|
||||||
|
[int]$TimeoutSeconds = 900,
|
||||||
|
|
||||||
|
[Alias("i")]
|
||||||
|
[int]$IntervalSeconds = 15,
|
||||||
|
|
||||||
|
[ValidateSet("push", "merge")]
|
||||||
|
[string]$Purpose = "merge",
|
||||||
|
|
||||||
|
[switch]$RequireStatus,
|
||||||
|
|
||||||
|
[Alias("h")]
|
||||||
|
[switch]$Help
|
||||||
|
)
|
||||||
|
|
||||||
|
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
. "$ScriptDir\detect-platform.ps1"
|
||||||
|
|
||||||
|
function Show-Usage {
|
||||||
|
@"
|
||||||
|
Usage: ci-queue-wait.ps1 [-Branch main] [-TimeoutSeconds 900] [-IntervalSeconds 15] [-Purpose push|merge] [-RequireStatus]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-Branch, -B BRANCH Branch head to inspect (default: main)
|
||||||
|
-TimeoutSeconds, -t SECONDS Max wait time (default: 900)
|
||||||
|
-IntervalSeconds, -i SECONDS Poll interval (default: 15)
|
||||||
|
-Purpose VALUE push or merge (default: merge)
|
||||||
|
-RequireStatus Fail if no CI status contexts are present
|
||||||
|
-Help, -h Show help
|
||||||
|
"@
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($Help) {
|
||||||
|
Show-Usage
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($TimeoutSeconds -lt 1 -or $IntervalSeconds -lt 1) {
|
||||||
|
Write-Error "TimeoutSeconds and IntervalSeconds must be positive integers."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-RemoteHost {
|
||||||
|
$remoteUrl = git remote get-url origin 2>$null
|
||||||
|
if ([string]::IsNullOrEmpty($remoteUrl)) { return $null }
|
||||||
|
if ($remoteUrl -match "^https?://([^/]+)/") { return $Matches[1] }
|
||||||
|
if ($remoteUrl -match "^git@([^:]+):") { return $Matches[1] }
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-GiteaToken {
|
||||||
|
param([string]$Host)
|
||||||
|
|
||||||
|
if ($env:GITEA_TOKEN) { return $env:GITEA_TOKEN }
|
||||||
|
|
||||||
|
$credPath = Join-Path $HOME ".git-credentials"
|
||||||
|
if (-not (Test-Path $credPath)) { return $null }
|
||||||
|
|
||||||
|
$line = Get-Content $credPath | Where-Object { $_ -like "*$Host*" } | Select-Object -First 1
|
||||||
|
if (-not $line) { return $null }
|
||||||
|
|
||||||
|
if ($line -match 'https?://[^@]*:([^@/]+)@') {
|
||||||
|
return $Matches[1]
|
||||||
|
}
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-QueueState {
|
||||||
|
param([object]$Payload)
|
||||||
|
|
||||||
|
$pending = @("pending", "queued", "running", "waiting")
|
||||||
|
$failure = @("failure", "error", "failed")
|
||||||
|
$success = @("success")
|
||||||
|
|
||||||
|
$state = ""
|
||||||
|
if ($null -ne $Payload.state) {
|
||||||
|
$state = "$($Payload.state)".ToLowerInvariant()
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($pending -contains $state) { return "pending" }
|
||||||
|
if ($failure -contains $state) { return "terminal-failure" }
|
||||||
|
if ($success -contains $state) { return "terminal-success" }
|
||||||
|
|
||||||
|
$values = @()
|
||||||
|
$statuses = @()
|
||||||
|
if ($null -ne $Payload.statuses) { $statuses = @($Payload.statuses) }
|
||||||
|
|
||||||
|
foreach ($s in $statuses) {
|
||||||
|
if ($null -eq $s) { continue }
|
||||||
|
$v = ""
|
||||||
|
if ($null -ne $s.status) { $v = "$($s.status)".ToLowerInvariant() }
|
||||||
|
elseif ($null -ne $s.state) { $v = "$($s.state)".ToLowerInvariant() }
|
||||||
|
if (-not [string]::IsNullOrEmpty($v)) { $values += $v }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($values.Count -eq 0 -and [string]::IsNullOrEmpty($state)) { return "no-status" }
|
||||||
|
if (($values | Where-Object { $pending -contains $_ }).Count -gt 0) { return "pending" }
|
||||||
|
if (($values | Where-Object { $failure -contains $_ }).Count -gt 0) { return "terminal-failure" }
|
||||||
|
if ($values.Count -gt 0 -and ($values | Where-Object { -not ($success -contains $_) }).Count -eq 0) { return "terminal-success" }
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
function Print-PendingContexts {
|
||||||
|
param([object]$Payload)
|
||||||
|
|
||||||
|
$pending = @("pending", "queued", "running", "waiting")
|
||||||
|
$statuses = @()
|
||||||
|
if ($null -ne $Payload.statuses) { $statuses = @($Payload.statuses) }
|
||||||
|
|
||||||
|
if ($statuses.Count -eq 0) {
|
||||||
|
Write-Host "[ci-queue-wait] no status contexts reported"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$found = $false
|
||||||
|
foreach ($s in $statuses) {
|
||||||
|
if ($null -eq $s) { continue }
|
||||||
|
$name = if ($s.context) { $s.context } elseif ($s.name) { $s.name } else { "unknown-context" }
|
||||||
|
$value = if ($s.status) { "$($s.status)".ToLowerInvariant() } elseif ($s.state) { "$($s.state)".ToLowerInvariant() } else { "unknown" }
|
||||||
|
$target = if ($s.target_url) { $s.target_url } elseif ($s.url) { $s.url } else { "" }
|
||||||
|
if ($pending -contains $value) {
|
||||||
|
$found = $true
|
||||||
|
if ($target) {
|
||||||
|
Write-Host "[ci-queue-wait] pending: $name=$value ($target)"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "[ci-queue-wait] pending: $name=$value"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $found) {
|
||||||
|
Write-Host "[ci-queue-wait] no pending contexts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$platform = Get-GitPlatform
|
||||||
|
$owner = Get-GitRepoOwner
|
||||||
|
$repo = Get-GitRepoName
|
||||||
|
|
||||||
|
if ([string]::IsNullOrEmpty($owner) -or [string]::IsNullOrEmpty($repo)) {
|
||||||
|
Write-Error "Could not determine repository owner/name from git remote."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$headSha = $null
|
||||||
|
$host = $null
|
||||||
|
$giteaToken = $null
|
||||||
|
|
||||||
|
switch ($platform) {
|
||||||
|
"github" {
|
||||||
|
if (-not (Get-Command gh -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Error "gh CLI is required for GitHub CI queue guard."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$headSha = (& gh api "repos/$owner/$repo/branches/$Branch" --jq ".commit.sha").Trim()
|
||||||
|
if ([string]::IsNullOrEmpty($headSha)) {
|
||||||
|
Write-Error "Could not resolve $Branch head SHA."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "[ci-queue-wait] platform=github purpose=$Purpose branch=$Branch sha=$headSha"
|
||||||
|
}
|
||||||
|
"gitea" {
|
||||||
|
$host = Get-RemoteHost
|
||||||
|
if ([string]::IsNullOrEmpty($host)) {
|
||||||
|
Write-Error "Could not determine remote host."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
$giteaToken = Get-GiteaToken -Host $host
|
||||||
|
if ([string]::IsNullOrEmpty($giteaToken)) {
|
||||||
|
Write-Error "Gitea token not found. Set GITEA_TOKEN or configure ~/.git-credentials."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$branchUrl = "https://$host/api/v1/repos/$owner/$repo/branches/$Branch"
|
||||||
|
$branchPayload = Invoke-RestMethod -Method Get -Uri $branchUrl -Headers @{ Authorization = "token $giteaToken" }
|
||||||
|
$headSha = ($branchPayload.commit.id | Out-String).Trim()
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Error "Could not resolve $Branch head SHA from Gitea API."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if ([string]::IsNullOrEmpty($headSha)) {
|
||||||
|
Write-Error "Could not resolve $Branch head SHA."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "[ci-queue-wait] platform=gitea purpose=$Purpose branch=$Branch sha=$headSha"
|
||||||
|
}
|
||||||
|
default {
|
||||||
|
Write-Error "Unsupported platform '$platform'."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$deadline = (Get-Date).AddSeconds($TimeoutSeconds)
|
||||||
|
|
||||||
|
while ($true) {
|
||||||
|
if ((Get-Date) -gt $deadline) {
|
||||||
|
Write-Error "Timed out waiting for CI queue to clear on $Branch after ${TimeoutSeconds}s."
|
||||||
|
exit 124
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($platform -eq "github") {
|
||||||
|
$statusJson = & gh api "repos/$owner/$repo/commits/$headSha/status"
|
||||||
|
$payload = $statusJson | ConvertFrom-Json
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$statusUrl = "https://$host/api/v1/repos/$owner/$repo/commits/$headSha/status"
|
||||||
|
$payload = Invoke-RestMethod -Method Get -Uri $statusUrl -Headers @{ Authorization = "token $giteaToken" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Error "Failed to query commit status for queue guard."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$state = Get-QueueState -Payload $payload
|
||||||
|
Write-Host "[ci-queue-wait] state=$state purpose=$Purpose branch=$Branch"
|
||||||
|
|
||||||
|
switch ($state) {
|
||||||
|
"pending" {
|
||||||
|
Print-PendingContexts -Payload $payload
|
||||||
|
Start-Sleep -Seconds $IntervalSeconds
|
||||||
|
}
|
||||||
|
"no-status" {
|
||||||
|
if ($RequireStatus) {
|
||||||
|
Write-Error "No CI status contexts found while -RequireStatus is set."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
Write-Host "[ci-queue-wait] no status contexts present; proceeding."
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
"terminal-success" { exit 0 }
|
||||||
|
"terminal-failure" { exit 0 }
|
||||||
|
"unknown" { exit 0 }
|
||||||
|
default { exit 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
307
rails/git/ci-queue-wait.sh
Executable file
307
rails/git/ci-queue-wait.sh
Executable file
@@ -0,0 +1,307 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ci-queue-wait.sh - Wait until project CI queue is clear (no running/queued pipeline on branch head)
|
||||||
|
# Usage: ci-queue-wait.sh [-B branch] [-t timeout_sec] [-i interval_sec] [--purpose push|merge] [--require-status]
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
BRANCH="main"
|
||||||
|
TIMEOUT_SEC=900
|
||||||
|
INTERVAL_SEC=15
|
||||||
|
PURPOSE="merge"
|
||||||
|
REQUIRE_STATUS=0
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") [-B branch] [-t timeout_sec] [-i interval_sec] [--purpose push|merge] [--require-status]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-B, --branch BRANCH Branch head to inspect (default: main)
|
||||||
|
-t, --timeout SECONDS Max wait time in seconds (default: 900)
|
||||||
|
-i, --interval SECONDS Poll interval in seconds (default: 15)
|
||||||
|
--purpose VALUE Log context: push|merge (default: merge)
|
||||||
|
--require-status Fail if no CI status contexts are present
|
||||||
|
-h, --help Show this help
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$(basename "$0")
|
||||||
|
$(basename "$0") --purpose push -B main -t 600 -i 10
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
get_remote_host() {
|
||||||
|
local remote_url
|
||||||
|
remote_url=$(git remote get-url origin 2>/dev/null || true)
|
||||||
|
if [[ -z "$remote_url" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [[ "$remote_url" =~ ^https?://([^/]+)/ ]]; then
|
||||||
|
echo "${BASH_REMATCH[1]}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if [[ "$remote_url" =~ ^git@([^:]+): ]]; then
|
||||||
|
echo "${BASH_REMATCH[1]}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get_gitea_token() {
|
||||||
|
local host="$1"
|
||||||
|
if [[ -n "${GITEA_TOKEN:-}" ]]; then
|
||||||
|
echo "$GITEA_TOKEN"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local creds="$HOME/.git-credentials"
|
||||||
|
if [[ -f "$creds" ]]; then
|
||||||
|
local token
|
||||||
|
token=$(grep -F "$host" "$creds" 2>/dev/null | sed -n 's#https\?://[^@]*:\([^@/]*\)@.*#\1#p' | head -n 1)
|
||||||
|
if [[ -n "$token" ]]; then
|
||||||
|
echo "$token"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get_state_from_status_json() {
|
||||||
|
python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
payload = json.load(sys.stdin)
|
||||||
|
except Exception:
|
||||||
|
print("unknown")
|
||||||
|
raise SystemExit(0)
|
||||||
|
|
||||||
|
statuses = payload.get("statuses") or []
|
||||||
|
state = (payload.get("state") or "").lower()
|
||||||
|
|
||||||
|
pending_values = {"pending", "queued", "running", "waiting"}
|
||||||
|
failure_values = {"failure", "error", "failed"}
|
||||||
|
success_values = {"success"}
|
||||||
|
|
||||||
|
if state in pending_values:
|
||||||
|
print("pending")
|
||||||
|
raise SystemExit(0)
|
||||||
|
if state in failure_values:
|
||||||
|
print("terminal-failure")
|
||||||
|
raise SystemExit(0)
|
||||||
|
if state in success_values:
|
||||||
|
print("terminal-success")
|
||||||
|
raise SystemExit(0)
|
||||||
|
|
||||||
|
values = []
|
||||||
|
for item in statuses:
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
continue
|
||||||
|
value = (item.get("status") or item.get("state") or "").lower()
|
||||||
|
if value:
|
||||||
|
values.append(value)
|
||||||
|
|
||||||
|
if not values and not state:
|
||||||
|
print("no-status")
|
||||||
|
elif any(v in pending_values for v in values):
|
||||||
|
print("pending")
|
||||||
|
elif any(v in failure_values for v in values):
|
||||||
|
print("terminal-failure")
|
||||||
|
elif values and all(v in success_values for v in values):
|
||||||
|
print("terminal-success")
|
||||||
|
else:
|
||||||
|
print("unknown")
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
print_pending_contexts() {
|
||||||
|
python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
payload = json.load(sys.stdin)
|
||||||
|
except Exception:
|
||||||
|
print("[ci-queue-wait] unable to decode status payload")
|
||||||
|
raise SystemExit(0)
|
||||||
|
|
||||||
|
statuses = payload.get("statuses") or []
|
||||||
|
if not statuses:
|
||||||
|
print("[ci-queue-wait] no status contexts reported")
|
||||||
|
raise SystemExit(0)
|
||||||
|
|
||||||
|
pending_values = {"pending", "queued", "running", "waiting"}
|
||||||
|
found = False
|
||||||
|
for item in statuses:
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
continue
|
||||||
|
name = item.get("context") or item.get("name") or "unknown-context"
|
||||||
|
value = (item.get("status") or item.get("state") or "unknown").lower()
|
||||||
|
target = item.get("target_url") or item.get("url") or ""
|
||||||
|
if value in pending_values:
|
||||||
|
found = True
|
||||||
|
if target:
|
||||||
|
print(f"[ci-queue-wait] pending: {name}={value} ({target})")
|
||||||
|
else:
|
||||||
|
print(f"[ci-queue-wait] pending: {name}={value}")
|
||||||
|
if not found:
|
||||||
|
print("[ci-queue-wait] no pending contexts")
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
github_get_branch_head_sha() {
|
||||||
|
local owner="$1"
|
||||||
|
local repo="$2"
|
||||||
|
local branch="$3"
|
||||||
|
gh api "repos/${owner}/${repo}/branches/${branch}" --jq '.commit.sha'
|
||||||
|
}
|
||||||
|
|
||||||
|
github_get_commit_status_json() {
|
||||||
|
local owner="$1"
|
||||||
|
local repo="$2"
|
||||||
|
local sha="$3"
|
||||||
|
gh api "repos/${owner}/${repo}/commits/${sha}/status"
|
||||||
|
}
|
||||||
|
|
||||||
|
gitea_get_branch_head_sha() {
|
||||||
|
local host="$1"
|
||||||
|
local repo="$2"
|
||||||
|
local branch="$3"
|
||||||
|
local token="$4"
|
||||||
|
local url="https://${host}/api/v1/repos/${repo}/branches/${branch}"
|
||||||
|
curl -fsS -H "Authorization: token ${token}" "$url" | python3 -c '
|
||||||
|
import json, sys
|
||||||
|
data = json.load(sys.stdin)
|
||||||
|
commit = data.get("commit") or {}
|
||||||
|
print((commit.get("id") or "").strip())
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
gitea_get_commit_status_json() {
|
||||||
|
local host="$1"
|
||||||
|
local repo="$2"
|
||||||
|
local sha="$3"
|
||||||
|
local token="$4"
|
||||||
|
local url="https://${host}/api/v1/repos/${repo}/commits/${sha}/status"
|
||||||
|
curl -fsS -H "Authorization: token ${token}" "$url"
|
||||||
|
}
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-B|--branch)
|
||||||
|
BRANCH="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-t|--timeout)
|
||||||
|
TIMEOUT_SEC="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-i|--interval)
|
||||||
|
INTERVAL_SEC="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--purpose)
|
||||||
|
PURPOSE="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--require-status)
|
||||||
|
REQUIRE_STATUS=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if ! [[ "$TIMEOUT_SEC" =~ ^[0-9]+$ ]] || ! [[ "$INTERVAL_SEC" =~ ^[0-9]+$ ]]; then
|
||||||
|
echo "Error: timeout and interval must be integer seconds." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
OWNER=$(get_repo_owner)
|
||||||
|
REPO=$(get_repo_name)
|
||||||
|
detect_platform > /dev/null
|
||||||
|
PLATFORM="${PLATFORM:-unknown}"
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
if ! command -v gh >/dev/null 2>&1; then
|
||||||
|
echo "Error: gh CLI is required for GitHub CI queue guard." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
HEAD_SHA=$(github_get_branch_head_sha "$OWNER" "$REPO" "$BRANCH")
|
||||||
|
if [[ -z "$HEAD_SHA" ]]; then
|
||||||
|
echo "Error: Could not resolve ${BRANCH} head SHA." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "[ci-queue-wait] platform=github purpose=${PURPOSE} branch=${BRANCH} sha=${HEAD_SHA}"
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
HOST=$(get_remote_host) || {
|
||||||
|
echo "Error: Could not determine remote host." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
TOKEN=$(get_gitea_token "$HOST") || {
|
||||||
|
echo "Error: Gitea token not found. Set GITEA_TOKEN or configure ~/.git-credentials." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
HEAD_SHA=$(gitea_get_branch_head_sha "$HOST" "$OWNER/$REPO" "$BRANCH" "$TOKEN")
|
||||||
|
if [[ -z "$HEAD_SHA" ]]; then
|
||||||
|
echo "Error: Could not resolve ${BRANCH} head SHA." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "[ci-queue-wait] platform=gitea purpose=${PURPOSE} branch=${BRANCH} sha=${HEAD_SHA}"
|
||||||
|
else
|
||||||
|
echo "Error: Unsupported platform '${PLATFORM}'." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
START_TS=$(date +%s)
|
||||||
|
DEADLINE_TS=$((START_TS + TIMEOUT_SEC))
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
NOW_TS=$(date +%s)
|
||||||
|
if (( NOW_TS > DEADLINE_TS )); then
|
||||||
|
echo "Error: Timed out waiting for CI queue to clear on ${BRANCH} after ${TIMEOUT_SEC}s." >&2
|
||||||
|
exit 124
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
STATUS_JSON=$(github_get_commit_status_json "$OWNER" "$REPO" "$HEAD_SHA")
|
||||||
|
else
|
||||||
|
STATUS_JSON=$(gitea_get_commit_status_json "$HOST" "$OWNER/$REPO" "$HEAD_SHA" "$TOKEN")
|
||||||
|
fi
|
||||||
|
|
||||||
|
STATE=$(printf '%s' "$STATUS_JSON" | get_state_from_status_json)
|
||||||
|
echo "[ci-queue-wait] state=${STATE} purpose=${PURPOSE} branch=${BRANCH}"
|
||||||
|
|
||||||
|
case "$STATE" in
|
||||||
|
pending)
|
||||||
|
printf '%s' "$STATUS_JSON" | print_pending_contexts
|
||||||
|
sleep "$INTERVAL_SEC"
|
||||||
|
;;
|
||||||
|
no-status)
|
||||||
|
if [[ "$REQUIRE_STATUS" -eq 1 ]]; then
|
||||||
|
echo "Error: No CI status contexts found for ${BRANCH} while --require-status is set." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "[ci-queue-wait] no status contexts present; proceeding."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
terminal-success|terminal-failure|unknown)
|
||||||
|
# Queue guard only blocks on pending/running/queued states.
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "[ci-queue-wait] unrecognized state '${STATE}', proceeding conservatively."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
@@ -13,6 +13,80 @@ BODY=""
|
|||||||
LABELS=""
|
LABELS=""
|
||||||
MILESTONE=""
|
MILESTONE=""
|
||||||
|
|
||||||
|
get_remote_host() {
|
||||||
|
local remote_url
|
||||||
|
remote_url=$(git remote get-url origin 2>/dev/null || true)
|
||||||
|
if [[ -z "$remote_url" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [[ "$remote_url" =~ ^https?://([^/]+)/ ]]; then
|
||||||
|
echo "${BASH_REMATCH[1]}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if [[ "$remote_url" =~ ^git@([^:]+): ]]; then
|
||||||
|
echo "${BASH_REMATCH[1]}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get_gitea_token() {
|
||||||
|
local host="$1"
|
||||||
|
if [[ -n "${GITEA_TOKEN:-}" ]]; then
|
||||||
|
echo "$GITEA_TOKEN"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local creds="$HOME/.git-credentials"
|
||||||
|
if [[ -f "$creds" ]]; then
|
||||||
|
local token
|
||||||
|
token=$(grep -F "$host" "$creds" 2>/dev/null | sed -n 's#https\?://[^@]*:\([^@/]*\)@.*#\1#p' | head -n 1)
|
||||||
|
if [[ -n "$token" ]]; then
|
||||||
|
echo "$token"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
gitea_issue_create_api() {
|
||||||
|
local host repo token url payload
|
||||||
|
host=$(get_remote_host) || {
|
||||||
|
echo "Error: could not determine remote host for API fallback" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
repo=$(get_repo_info) || {
|
||||||
|
echo "Error: could not determine repo owner/name for API fallback" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
token=$(get_gitea_token "$host") || {
|
||||||
|
echo "Error: Gitea token not found for API fallback (set GITEA_TOKEN or configure ~/.git-credentials)" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ -n "$LABELS" || -n "$MILESTONE" ]]; then
|
||||||
|
echo "Warning: API fallback currently applies title/body only; labels/milestone require authenticated tea setup." >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
payload=$(TITLE="$TITLE" BODY="$BODY" python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
payload = {"title": os.environ["TITLE"]}
|
||||||
|
body = os.environ.get("BODY", "")
|
||||||
|
if body:
|
||||||
|
payload["body"] = body
|
||||||
|
print(json.dumps(payload))
|
||||||
|
PY
|
||||||
|
)
|
||||||
|
|
||||||
|
url="https://${host}/api/v1/repos/${repo}/issues"
|
||||||
|
curl -fsS -X POST \
|
||||||
|
-H "Authorization: token ${token}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$payload" \
|
||||||
|
"$url"
|
||||||
|
}
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
Usage: $(basename "$0") [OPTIONS]
|
Usage: $(basename "$0") [OPTIONS]
|
||||||
@@ -78,12 +152,18 @@ case "$PLATFORM" in
|
|||||||
eval "$CMD"
|
eval "$CMD"
|
||||||
;;
|
;;
|
||||||
gitea)
|
gitea)
|
||||||
|
if command -v tea >/dev/null 2>&1; then
|
||||||
CMD="tea issue create --title \"$TITLE\""
|
CMD="tea issue create --title \"$TITLE\""
|
||||||
[[ -n "$BODY" ]] && CMD="$CMD --description \"$BODY\""
|
[[ -n "$BODY" ]] && CMD="$CMD --description \"$BODY\""
|
||||||
[[ -n "$LABELS" ]] && CMD="$CMD --labels \"$LABELS\""
|
[[ -n "$LABELS" ]] && CMD="$CMD --labels \"$LABELS\""
|
||||||
# tea accepts milestone by name directly (verified 2026-02-05)
|
# tea accepts milestone by name directly (verified 2026-02-05)
|
||||||
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
|
[[ -n "$MILESTONE" ]] && CMD="$CMD --milestone \"$MILESTONE\""
|
||||||
eval "$CMD"
|
if eval "$CMD"; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Warning: tea issue create failed, trying Gitea API fallback..." >&2
|
||||||
|
fi
|
||||||
|
gitea_issue_create_api
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Error: Could not detect git platform" >&2
|
echo "Error: Could not detect git platform" >&2
|
||||||
|
|||||||
@@ -10,6 +10,64 @@ source "$SCRIPT_DIR/detect-platform.sh"
|
|||||||
# Parse arguments
|
# Parse arguments
|
||||||
ISSUE_NUMBER=""
|
ISSUE_NUMBER=""
|
||||||
|
|
||||||
|
get_remote_host() {
|
||||||
|
local remote_url
|
||||||
|
remote_url=$(git remote get-url origin 2>/dev/null || true)
|
||||||
|
if [[ -z "$remote_url" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [[ "$remote_url" =~ ^https?://([^/]+)/ ]]; then
|
||||||
|
echo "${BASH_REMATCH[1]}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if [[ "$remote_url" =~ ^git@([^:]+): ]]; then
|
||||||
|
echo "${BASH_REMATCH[1]}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get_gitea_token() {
|
||||||
|
local host="$1"
|
||||||
|
if [[ -n "${GITEA_TOKEN:-}" ]]; then
|
||||||
|
echo "$GITEA_TOKEN"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
local creds="$HOME/.git-credentials"
|
||||||
|
if [[ -f "$creds" ]]; then
|
||||||
|
local token
|
||||||
|
token=$(grep -F "$host" "$creds" 2>/dev/null | sed -n 's#https\?://[^@]*:\([^@/]*\)@.*#\1#p' | head -n 1)
|
||||||
|
if [[ -n "$token" ]]; then
|
||||||
|
echo "$token"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
gitea_issue_view_api() {
|
||||||
|
local host repo token url
|
||||||
|
host=$(get_remote_host) || {
|
||||||
|
echo "Error: could not determine remote host for API fallback" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
repo=$(get_repo_info) || {
|
||||||
|
echo "Error: could not determine repo owner/name for API fallback" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
token=$(get_gitea_token "$host") || {
|
||||||
|
echo "Error: Gitea token not found for API fallback (set GITEA_TOKEN or configure ~/.git-credentials)" >&2
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
url="https://${host}/api/v1/repos/${repo}/issues/${ISSUE_NUMBER}"
|
||||||
|
if command -v python3 >/dev/null 2>&1; then
|
||||||
|
curl -fsS -H "Authorization: token ${token}" "$url" | python3 -m json.tool
|
||||||
|
else
|
||||||
|
curl -fsS -H "Authorization: token ${token}" "$url"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case $1 in
|
case $1 in
|
||||||
-i|--issue)
|
-i|--issue)
|
||||||
@@ -41,7 +99,13 @@ detect_platform
|
|||||||
if [[ "$PLATFORM" == "github" ]]; then
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
gh issue view "$ISSUE_NUMBER"
|
gh issue view "$ISSUE_NUMBER"
|
||||||
elif [[ "$PLATFORM" == "gitea" ]]; then
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
tea issue "$ISSUE_NUMBER"
|
if command -v tea >/dev/null 2>&1; then
|
||||||
|
if tea issue "$ISSUE_NUMBER"; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Warning: tea issue view failed, trying Gitea API fallback..." >&2
|
||||||
|
fi
|
||||||
|
gitea_issue_view_api
|
||||||
else
|
else
|
||||||
echo "Error: Unknown platform"
|
echo "Error: Unknown platform"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ Create or list milestones on the current repository (Gitea or GitHub).
|
|||||||
|
|
||||||
Versioning Convention:
|
Versioning Convention:
|
||||||
- Features get dedicated milestones
|
- Features get dedicated milestones
|
||||||
- Pre-release: 0.X.0 for breaking changes, 0.X.Y for patches
|
- Pre-MVP milestones MUST use 0.0.x and MUST start at 0.0.1
|
||||||
- Post-release: X.0.0 for breaking changes
|
- 0.1.0 is reserved for MVP release
|
||||||
- MVP starts at 0.1.0
|
- After MVP, continue semantic progression (0.1.x, 0.2.x, ...)
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-Title, -t TITLE Milestone title/version (e.g., "0.2.0")
|
-Title, -t TITLE Milestone title/version (e.g., "0.0.1")
|
||||||
-Description, -d DESC Milestone description
|
-Description, -d DESC Milestone description
|
||||||
-Due DATE Due date (YYYY-MM-DD format)
|
-Due DATE Due date (YYYY-MM-DD format)
|
||||||
-List List existing milestones
|
-List List existing milestones
|
||||||
@@ -41,8 +41,8 @@ Options:
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
.\milestone-create.ps1 -List
|
.\milestone-create.ps1 -List
|
||||||
.\milestone-create.ps1 -t "0.1.0" -d "MVP Release"
|
.\milestone-create.ps1 -t "0.0.1" -d "Pre-MVP Foundation Sprint"
|
||||||
.\milestone-create.ps1 -t "0.2.0" -d "User Authentication Feature" -Due "2025-03-01"
|
.\milestone-create.ps1 -t "0.1.0" -d "MVP Release" -Due "2025-03-01"
|
||||||
"@
|
"@
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ Create or list milestones on the current repository (Gitea or GitHub).
|
|||||||
|
|
||||||
Versioning Convention:
|
Versioning Convention:
|
||||||
- Features get dedicated milestones
|
- Features get dedicated milestones
|
||||||
- Pre-release: 0.X.0 for breaking changes, 0.X.Y for patches
|
- Pre-MVP milestones MUST use 0.0.x and MUST start at 0.0.1
|
||||||
- Post-release: X.0.0 for breaking changes
|
- 0.1.0 is reserved for MVP release
|
||||||
- MVP starts at 0.1.0
|
- After MVP, continue semantic progression (0.1.x, 0.2.x, ...)
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-t, --title TITLE Milestone title/version (e.g., "0.2.0")
|
-t, --title TITLE Milestone title/version (e.g., "0.0.1")
|
||||||
-d, --desc DESCRIPTION Milestone description
|
-d, --desc DESCRIPTION Milestone description
|
||||||
--due DATE Due date (YYYY-MM-DD format)
|
--due DATE Due date (YYYY-MM-DD format)
|
||||||
--list List existing milestones
|
--list List existing milestones
|
||||||
@@ -34,8 +34,8 @@ Options:
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
$(basename "$0") --list
|
$(basename "$0") --list
|
||||||
$(basename "$0") -t "0.1.0" -d "MVP Release"
|
$(basename "$0") -t "0.0.1" -d "Pre-MVP Foundation Sprint"
|
||||||
$(basename "$0") -t "0.2.0" -d "User Authentication Feature" --due "2025-03-01"
|
$(basename "$0") -t "0.1.0" -d "MVP Release" --due "2025-03-01"
|
||||||
EOF
|
EOF
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|||||||
273
rails/git/pr-ci-wait.sh
Executable file
273
rails/git/pr-ci-wait.sh
Executable file
@@ -0,0 +1,273 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# pr-ci-wait.sh - Wait for PR CI status to reach terminal state (GitHub/Gitea)
|
||||||
|
# Usage: pr-ci-wait.sh -n <pr_number> [-t timeout_sec] [-i interval_sec]
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
source "$SCRIPT_DIR/detect-platform.sh"
|
||||||
|
|
||||||
|
PR_NUMBER=""
|
||||||
|
TIMEOUT_SEC=1800
|
||||||
|
INTERVAL_SEC=15
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") -n <pr_number> [-t timeout_sec] [-i interval_sec]
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-n, --number NUMBER PR number (required)
|
||||||
|
-t, --timeout SECONDS Max wait time in seconds (default: 1800)
|
||||||
|
-i, --interval SECONDS Poll interval in seconds (default: 15)
|
||||||
|
-h, --help Show this help
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
$(basename "$0") -n 643
|
||||||
|
$(basename "$0") -n 643 -t 900 -i 10
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
get_remote_host() {
|
||||||
|
local remote_url
|
||||||
|
remote_url=$(git remote get-url origin 2>/dev/null || true)
|
||||||
|
if [[ -z "$remote_url" ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [[ "$remote_url" =~ ^https?://([^/]+)/ ]]; then
|
||||||
|
echo "${BASH_REMATCH[1]}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
if [[ "$remote_url" =~ ^git@([^:]+): ]]; then
|
||||||
|
echo "${BASH_REMATCH[1]}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
get_gitea_token() {
|
||||||
|
local host="$1"
|
||||||
|
if [[ -n "${GITEA_TOKEN:-}" ]]; then
|
||||||
|
echo "$GITEA_TOKEN"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local creds="$HOME/.git-credentials"
|
||||||
|
if [[ -f "$creds" ]]; then
|
||||||
|
local token
|
||||||
|
token=$(grep -F "$host" "$creds" 2>/dev/null | sed -n 's#https\?://[^@]*:\([^@/]*\)@.*#\1#p' | head -n 1)
|
||||||
|
if [[ -n "$token" ]]; then
|
||||||
|
echo "$token"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
extract_state_from_status_json() {
|
||||||
|
python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
payload = json.load(sys.stdin)
|
||||||
|
except Exception:
|
||||||
|
print("unknown")
|
||||||
|
raise SystemExit(0)
|
||||||
|
|
||||||
|
state = (payload.get("state") or "").lower()
|
||||||
|
if state in {"success", "pending", "failure", "error"}:
|
||||||
|
print(state)
|
||||||
|
raise SystemExit(0)
|
||||||
|
|
||||||
|
statuses = payload.get("statuses") or []
|
||||||
|
values = []
|
||||||
|
for item in statuses:
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
continue
|
||||||
|
value = (item.get("status") or item.get("state") or "").lower()
|
||||||
|
if value:
|
||||||
|
values.append(value)
|
||||||
|
|
||||||
|
if any(v in {"failure", "error"} for v in values):
|
||||||
|
print("failure")
|
||||||
|
elif values and all(v == "success" for v in values):
|
||||||
|
print("success")
|
||||||
|
elif any(v in {"pending", "running", "queued", "waiting"} for v in values):
|
||||||
|
print("pending")
|
||||||
|
else:
|
||||||
|
print("unknown")
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
print_status_summary() {
|
||||||
|
python3 - <<'PY'
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
payload = json.load(sys.stdin)
|
||||||
|
except Exception:
|
||||||
|
print("[pr-ci-wait] status payload unavailable")
|
||||||
|
raise SystemExit(0)
|
||||||
|
|
||||||
|
statuses = payload.get("statuses") or []
|
||||||
|
if not statuses:
|
||||||
|
print("[pr-ci-wait] no status contexts reported yet")
|
||||||
|
raise SystemExit(0)
|
||||||
|
|
||||||
|
for item in statuses:
|
||||||
|
if not isinstance(item, dict):
|
||||||
|
continue
|
||||||
|
name = item.get("context") or item.get("name") or "unknown-context"
|
||||||
|
state = item.get("status") or item.get("state") or "unknown-state"
|
||||||
|
target = item.get("target_url") or item.get("url") or ""
|
||||||
|
if target:
|
||||||
|
print(f"[pr-ci-wait] {name}: {state} ({target})")
|
||||||
|
else:
|
||||||
|
print(f"[pr-ci-wait] {name}: {state}")
|
||||||
|
PY
|
||||||
|
}
|
||||||
|
|
||||||
|
github_get_pr_head_sha() {
|
||||||
|
gh pr view "$PR_NUMBER" --json headRefOid --jq '.headRefOid'
|
||||||
|
}
|
||||||
|
|
||||||
|
github_get_commit_status_json() {
|
||||||
|
local owner="$1"
|
||||||
|
local repo="$2"
|
||||||
|
local sha="$3"
|
||||||
|
gh api "repos/${owner}/${repo}/commits/${sha}/status"
|
||||||
|
}
|
||||||
|
|
||||||
|
gitea_get_pr_head_sha() {
|
||||||
|
local host="$1"
|
||||||
|
local repo="$2"
|
||||||
|
local token="$3"
|
||||||
|
local url="https://${host}/api/v1/repos/${repo}/pulls/${PR_NUMBER}"
|
||||||
|
curl -fsS -H "Authorization: token ${token}" "$url" | python3 -c '
|
||||||
|
import json, sys
|
||||||
|
data = json.load(sys.stdin)
|
||||||
|
print((data.get("head") or {}).get("sha", ""))
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
gitea_get_commit_status_json() {
|
||||||
|
local host="$1"
|
||||||
|
local repo="$2"
|
||||||
|
local token="$3"
|
||||||
|
local sha="$4"
|
||||||
|
local url="https://${host}/api/v1/repos/${repo}/commits/${sha}/status"
|
||||||
|
curl -fsS -H "Authorization: token ${token}" "$url"
|
||||||
|
}
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-n|--number)
|
||||||
|
PR_NUMBER="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-t|--timeout)
|
||||||
|
TIMEOUT_SEC="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-i|--interval)
|
||||||
|
INTERVAL_SEC="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ -z "$PR_NUMBER" ]]; then
|
||||||
|
echo "Error: PR number is required (-n)." >&2
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [[ "$TIMEOUT_SEC" =~ ^[0-9]+$ ]] || ! [[ "$INTERVAL_SEC" =~ ^[0-9]+$ ]]; then
|
||||||
|
echo "Error: timeout and interval must be integer seconds." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
detect_platform > /dev/null
|
||||||
|
|
||||||
|
OWNER=$(get_repo_owner)
|
||||||
|
REPO=$(get_repo_name)
|
||||||
|
START_TS=$(date +%s)
|
||||||
|
DEADLINE_TS=$((START_TS + TIMEOUT_SEC))
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
if ! command -v gh >/dev/null 2>&1; then
|
||||||
|
echo "Error: gh CLI is required for GitHub CI status polling." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
HEAD_SHA=$(github_get_pr_head_sha)
|
||||||
|
if [[ -z "$HEAD_SHA" ]]; then
|
||||||
|
echo "Error: Could not resolve head SHA for PR #$PR_NUMBER." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "[pr-ci-wait] Platform=github PR=#${PR_NUMBER} head_sha=${HEAD_SHA}"
|
||||||
|
elif [[ "$PLATFORM" == "gitea" ]]; then
|
||||||
|
HOST=$(get_remote_host) || {
|
||||||
|
echo "Error: Could not determine remote host." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
TOKEN=$(get_gitea_token "$HOST") || {
|
||||||
|
echo "Error: Gitea token not found. Set GITEA_TOKEN or configure ~/.git-credentials." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
HEAD_SHA=$(gitea_get_pr_head_sha "$HOST" "$OWNER/$REPO" "$TOKEN")
|
||||||
|
if [[ -z "$HEAD_SHA" ]]; then
|
||||||
|
echo "Error: Could not resolve head SHA for PR #$PR_NUMBER." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "[pr-ci-wait] Platform=gitea host=${HOST} PR=#${PR_NUMBER} head_sha=${HEAD_SHA}"
|
||||||
|
else
|
||||||
|
echo "Error: Unsupported platform '${PLATFORM}'." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
NOW_TS=$(date +%s)
|
||||||
|
if (( NOW_TS > DEADLINE_TS )); then
|
||||||
|
echo "Error: Timed out waiting for CI status on PR #$PR_NUMBER after ${TIMEOUT_SEC}s." >&2
|
||||||
|
exit 124
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$PLATFORM" == "github" ]]; then
|
||||||
|
STATUS_JSON=$(github_get_commit_status_json "$OWNER" "$REPO" "$HEAD_SHA")
|
||||||
|
else
|
||||||
|
STATUS_JSON=$(gitea_get_commit_status_json "$HOST" "$OWNER/$REPO" "$TOKEN" "$HEAD_SHA")
|
||||||
|
fi
|
||||||
|
|
||||||
|
STATE=$(printf '%s' "$STATUS_JSON" | extract_state_from_status_json)
|
||||||
|
echo "[pr-ci-wait] state=${STATE} pr=#${PR_NUMBER} sha=${HEAD_SHA}"
|
||||||
|
|
||||||
|
case "$STATE" in
|
||||||
|
success)
|
||||||
|
printf '%s' "$STATUS_JSON" | print_status_summary
|
||||||
|
echo "[pr-ci-wait] CI is green for PR #$PR_NUMBER."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
failure|error)
|
||||||
|
printf '%s' "$STATUS_JSON" | print_status_summary
|
||||||
|
echo "Error: CI reported ${STATE} for PR #$PR_NUMBER." >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
pending|unknown)
|
||||||
|
sleep "$INTERVAL_SEC"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "[pr-ci-wait] Unrecognized state '${STATE}', continuing to poll..."
|
||||||
|
sleep "$INTERVAL_SEC"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
47
rails/git/pr-merge.ps1
Normal file → Executable file
47
rails/git/pr-merge.ps1
Normal file → Executable file
@@ -1,5 +1,5 @@
|
|||||||
# pr-merge.ps1 - Merge pull requests on Gitea or GitHub
|
# pr-merge.ps1 - Merge pull requests on Gitea or GitHub
|
||||||
# Usage: .\pr-merge.ps1 -Number PR_NUMBER [-Method method] [-DeleteBranch]
|
# Usage: .\pr-merge.ps1 -Number PR_NUMBER [-Method squash] [-DeleteBranch]
|
||||||
|
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
@@ -8,12 +8,13 @@ param(
|
|||||||
[int]$Number,
|
[int]$Number,
|
||||||
|
|
||||||
[Alias("m")]
|
[Alias("m")]
|
||||||
[ValidateSet("merge", "squash", "rebase")]
|
[string]$Method = "squash",
|
||||||
[string]$Method = "merge",
|
|
||||||
|
|
||||||
[Alias("d")]
|
[Alias("d")]
|
||||||
[switch]$DeleteBranch,
|
[switch]$DeleteBranch,
|
||||||
|
|
||||||
|
[switch]$SkipQueueGuard,
|
||||||
|
|
||||||
[Alias("h")]
|
[Alias("h")]
|
||||||
[switch]$Help
|
[switch]$Help
|
||||||
)
|
)
|
||||||
@@ -29,14 +30,15 @@ Merge a pull request on the current repository (Gitea or GitHub).
|
|||||||
|
|
||||||
Options:
|
Options:
|
||||||
-Number, -n NUMBER PR number to merge (required)
|
-Number, -n NUMBER PR number to merge (required)
|
||||||
-Method, -m METHOD Merge method: merge, squash, rebase (default: merge)
|
-Method, -m METHOD Merge method: squash only (default: squash)
|
||||||
-DeleteBranch, -d Delete the head branch after merge
|
-DeleteBranch, -d Delete the head branch after merge
|
||||||
|
-SkipQueueGuard Skip CI queue guard wait before merge
|
||||||
-Help, -h Show this help message
|
-Help, -h Show this help message
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
.\pr-merge.ps1 -n 42 # Merge PR #42
|
.\pr-merge.ps1 -n 42 # Merge PR #42
|
||||||
.\pr-merge.ps1 -n 42 -m squash # Squash merge
|
.\pr-merge.ps1 -n 42 -m squash # Squash merge
|
||||||
.\pr-merge.ps1 -n 42 -m rebase -d # Rebase and delete branch
|
.\pr-merge.ps1 -n 42 -d # Squash merge and delete branch
|
||||||
"@
|
"@
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@@ -45,27 +47,42 @@ if ($Help) {
|
|||||||
Show-Usage
|
Show-Usage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($Method -ne "squash") {
|
||||||
|
Write-Error "Mosaic policy enforces squash merge only. Received '$Method'."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
$platform = Get-GitPlatform
|
$platform = Get-GitPlatform
|
||||||
|
|
||||||
switch ($platform) {
|
switch ($platform) {
|
||||||
"github" {
|
"github" {
|
||||||
$cmd = @("gh", "pr", "merge", $Number)
|
$baseRef = (& gh pr view $Number --json baseRefName --jq ".baseRefName").Trim()
|
||||||
switch ($Method) {
|
if ($baseRef -ne "main") {
|
||||||
"merge" { $cmd += "--merge" }
|
Write-Error "Mosaic policy allows merges only for PRs targeting 'main' (found '$baseRef')."
|
||||||
"squash" { $cmd += "--squash" }
|
exit 1
|
||||||
"rebase" { $cmd += "--rebase" }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (-not $SkipQueueGuard) {
|
||||||
|
$timeout = if ($env:MOSAIC_CI_QUEUE_TIMEOUT_SEC) { [int]$env:MOSAIC_CI_QUEUE_TIMEOUT_SEC } else { 900 }
|
||||||
|
$interval = if ($env:MOSAIC_CI_QUEUE_POLL_SEC) { [int]$env:MOSAIC_CI_QUEUE_POLL_SEC } else { 15 }
|
||||||
|
& "$ScriptDir\ci-queue-wait.ps1" -Purpose merge -Branch $baseRef -TimeoutSeconds $timeout -IntervalSeconds $interval
|
||||||
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
|
}
|
||||||
|
|
||||||
|
$cmd = @("gh", "pr", "merge", $Number, "--squash")
|
||||||
if ($DeleteBranch) { $cmd += "--delete-branch" }
|
if ($DeleteBranch) { $cmd += "--delete-branch" }
|
||||||
& $cmd[0] $cmd[1..($cmd.Length-1)]
|
& $cmd[0] $cmd[1..($cmd.Length-1)]
|
||||||
}
|
}
|
||||||
"gitea" {
|
"gitea" {
|
||||||
$cmd = @("tea", "pr", "merge", $Number)
|
if (-not $SkipQueueGuard) {
|
||||||
switch ($Method) {
|
$timeout = if ($env:MOSAIC_CI_QUEUE_TIMEOUT_SEC) { [int]$env:MOSAIC_CI_QUEUE_TIMEOUT_SEC } else { 900 }
|
||||||
"merge" { $cmd += @("--style", "merge") }
|
$interval = if ($env:MOSAIC_CI_QUEUE_POLL_SEC) { [int]$env:MOSAIC_CI_QUEUE_POLL_SEC } else { 15 }
|
||||||
"squash" { $cmd += @("--style", "squash") }
|
& "$ScriptDir\ci-queue-wait.ps1" -Purpose merge -Branch "main" -TimeoutSeconds $timeout -IntervalSeconds $interval
|
||||||
"rebase" { $cmd += @("--style", "rebase") }
|
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$cmd = @("tea", "pr", "merge", $Number, "--style", "squash")
|
||||||
|
|
||||||
if ($DeleteBranch) {
|
if ($DeleteBranch) {
|
||||||
Write-Warning "Branch deletion after merge may need to be done separately with tea"
|
Write-Warning "Branch deletion after merge may need to be done separately with tea"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# pr-merge.sh - Merge pull requests on Gitea or GitHub
|
# pr-merge.sh - Merge pull requests on Gitea or GitHub
|
||||||
# Usage: pr-merge.sh -n PR_NUMBER [-m method] [-d]
|
# Usage: pr-merge.sh -n PR_NUMBER [-m squash] [-d] [--skip-queue-guard]
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
@@ -9,8 +9,9 @@ source "$SCRIPT_DIR/detect-platform.sh"
|
|||||||
|
|
||||||
# Default values
|
# Default values
|
||||||
PR_NUMBER=""
|
PR_NUMBER=""
|
||||||
MERGE_METHOD="merge" # merge, squash, rebase
|
MERGE_METHOD="squash"
|
||||||
DELETE_BRANCH=false
|
DELETE_BRANCH=false
|
||||||
|
SKIP_QUEUE_GUARD=false
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
@@ -20,14 +21,16 @@ Merge a pull request on the current repository (Gitea or GitHub).
|
|||||||
|
|
||||||
Options:
|
Options:
|
||||||
-n, --number NUMBER PR number to merge (required)
|
-n, --number NUMBER PR number to merge (required)
|
||||||
-m, --method METHOD Merge method: merge, squash, rebase (default: merge)
|
-m, --method METHOD Merge method: squash only (default: squash)
|
||||||
-d, --delete-branch Delete the head branch after merge
|
-d, --delete-branch Delete the head branch after merge
|
||||||
|
--skip-queue-guard Skip CI queue guard wait before merge
|
||||||
-h, --help Show this help message
|
-h, --help Show this help message
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
$(basename "$0") -n 42 # Merge PR #42
|
$(basename "$0") -n 42 # Merge PR #42
|
||||||
$(basename "$0") -n 42 -m squash # Squash merge
|
$(basename "$0") -n 42 -m squash # Squash merge
|
||||||
$(basename "$0") -n 42 -m rebase -d # Rebase and delete branch
|
$(basename "$0") -n 42 -d # Squash merge and delete branch
|
||||||
|
$(basename "$0") -n 42 --skip-queue-guard # Skip queue guard wait
|
||||||
EOF
|
EOF
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
@@ -47,6 +50,10 @@ while [[ $# -gt 0 ]]; do
|
|||||||
DELETE_BRANCH=true
|
DELETE_BRANCH=true
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--skip-queue-guard)
|
||||||
|
SKIP_QUEUE_GUARD=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
-h|--help)
|
-h|--help)
|
||||||
usage
|
usage
|
||||||
;;
|
;;
|
||||||
@@ -62,37 +69,36 @@ if [[ -z "$PR_NUMBER" ]]; then
|
|||||||
usage
|
usage
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ "$MERGE_METHOD" != "squash" ]]; then
|
||||||
|
echo "Error: Mosaic policy enforces squash merge only. Received '$MERGE_METHOD'." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BASE_BRANCH="$("$SCRIPT_DIR/pr-metadata.sh" -n "$PR_NUMBER" | python3 -c 'import json, sys; print((json.load(sys.stdin).get("baseRefName") or "").strip())')"
|
||||||
|
if [[ "$BASE_BRANCH" != "main" ]]; then
|
||||||
|
echo "Error: Mosaic policy allows merges only for PRs targeting 'main' (found '$BASE_BRANCH')." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$SKIP_QUEUE_GUARD" != true ]]; then
|
||||||
|
"$SCRIPT_DIR/ci-queue-wait.sh" \
|
||||||
|
--purpose merge \
|
||||||
|
-B "$BASE_BRANCH" \
|
||||||
|
-t "${MOSAIC_CI_QUEUE_TIMEOUT_SEC:-900}" \
|
||||||
|
-i "${MOSAIC_CI_QUEUE_POLL_SEC:-15}"
|
||||||
|
fi
|
||||||
|
|
||||||
PLATFORM=$(detect_platform)
|
PLATFORM=$(detect_platform)
|
||||||
|
|
||||||
case "$PLATFORM" in
|
case "$PLATFORM" in
|
||||||
github)
|
github)
|
||||||
CMD="gh pr merge $PR_NUMBER"
|
CMD="gh pr merge $PR_NUMBER --squash"
|
||||||
case "$MERGE_METHOD" in
|
|
||||||
merge) CMD="$CMD --merge" ;;
|
|
||||||
squash) CMD="$CMD --squash" ;;
|
|
||||||
rebase) CMD="$CMD --rebase" ;;
|
|
||||||
*)
|
|
||||||
echo "Error: Invalid merge method '$MERGE_METHOD'" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
[[ "$DELETE_BRANCH" == true ]] && CMD="$CMD --delete-branch"
|
[[ "$DELETE_BRANCH" == true ]] && CMD="$CMD --delete-branch"
|
||||||
eval "$CMD"
|
eval "$CMD"
|
||||||
;;
|
;;
|
||||||
gitea)
|
gitea)
|
||||||
# tea pr merge syntax
|
# tea pr merge syntax
|
||||||
CMD="tea pr merge $PR_NUMBER"
|
CMD="tea pr merge $PR_NUMBER --style squash"
|
||||||
|
|
||||||
# tea merge style flags
|
|
||||||
case "$MERGE_METHOD" in
|
|
||||||
merge) CMD="$CMD --style merge" ;;
|
|
||||||
squash) CMD="$CMD --style squash" ;;
|
|
||||||
rebase) CMD="$CMD --style rebase" ;;
|
|
||||||
*)
|
|
||||||
echo "Error: Invalid merge method '$MERGE_METHOD'" >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Delete branch after merge if requested
|
# Delete branch after merge if requested
|
||||||
if [[ "$DELETE_BRANCH" == true ]]; then
|
if [[ "$DELETE_BRANCH" == true ]]; then
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ Continuous loop:
|
|||||||
~/.config/mosaic/bin/mosaic-orchestrator-run --poll-sec 10
|
~/.config/mosaic/bin/mosaic-orchestrator-run --poll-sec 10
|
||||||
```
|
```
|
||||||
|
|
||||||
Sync from `docs/tasks.md` to queue:
|
Sync from `docs/TASKS.md` to queue:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~/.config/mosaic/bin/mosaic-orchestrator-sync-tasks --apply
|
~/.config/mosaic/bin/mosaic-orchestrator-sync-tasks --apply
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Sync docs/tasks.md rows into .mosaic/orchestrator/tasks.json."""
|
"""Sync docs/TASKS.md rows into .mosaic/orchestrator/tasks.json."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -89,7 +89,12 @@ def parse_depends(raw: str) -> list[str]:
|
|||||||
return [x.strip() for x in raw.split(",") if x.strip()]
|
return [x.strip() for x in raw.split(",") if x.strip()]
|
||||||
|
|
||||||
|
|
||||||
def build_task(row: dict[str, str], existing: dict[str, Any], runtime_default: str) -> dict[str, Any]:
|
def build_task(
|
||||||
|
row: dict[str, str],
|
||||||
|
existing: dict[str, Any],
|
||||||
|
runtime_default: str,
|
||||||
|
source_path: str,
|
||||||
|
) -> dict[str, Any]:
|
||||||
task_id = row.get("id", "").strip()
|
task_id = row.get("id", "").strip()
|
||||||
description = row.get("description", "").strip()
|
description = row.get("description", "").strip()
|
||||||
issue = row.get("issue", "").strip()
|
issue = row.get("issue", "").strip()
|
||||||
@@ -109,7 +114,7 @@ def build_task(row: dict[str, str], existing: dict[str, Any], runtime_default: s
|
|||||||
metadata = dict(task.get("metadata") or {})
|
metadata = dict(task.get("metadata") or {})
|
||||||
metadata.update(
|
metadata.update(
|
||||||
{
|
{
|
||||||
"source": "docs/tasks.md",
|
"source": source_path,
|
||||||
"issue": issue,
|
"issue": issue,
|
||||||
"repo": repo,
|
"repo": repo,
|
||||||
"branch": branch,
|
"branch": branch,
|
||||||
@@ -120,26 +125,35 @@ def build_task(row: dict[str, str], existing: dict[str, Any], runtime_default: s
|
|||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
parser = argparse.ArgumentParser(description="Sync docs/tasks.md into .mosaic/orchestrator/tasks.json")
|
parser = argparse.ArgumentParser(description="Sync docs/TASKS.md into .mosaic/orchestrator/tasks.json")
|
||||||
parser.add_argument("--repo", default=os.getcwd(), help="Repository root (default: cwd)")
|
parser.add_argument("--repo", default=os.getcwd(), help="Repository root (default: cwd)")
|
||||||
parser.add_argument("--docs", default="docs/tasks.md", help="Path to tasks markdown (repo-relative)")
|
parser.add_argument("--docs", default="docs/TASKS.md", help="Path to tasks markdown (repo-relative)")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--tasks-json",
|
"--tasks-json",
|
||||||
default=".mosaic/orchestrator/tasks.json",
|
default=".mosaic/orchestrator/tasks.json",
|
||||||
help="Path to orchestrator tasks JSON (repo-relative)",
|
help="Path to orchestrator tasks JSON (repo-relative)",
|
||||||
)
|
)
|
||||||
parser.add_argument("--keep-unlisted", action="store_true", help="Retain tasks already in JSON but missing from docs/tasks.md")
|
parser.add_argument("--keep-unlisted", action="store_true", help="Retain tasks already in JSON but missing from docs/TASKS.md")
|
||||||
parser.add_argument("--apply", action="store_true", help="Write changes (default is dry-run)")
|
parser.add_argument("--apply", action="store_true", help="Write changes (default is dry-run)")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
repo = pathlib.Path(args.repo).resolve()
|
repo = pathlib.Path(args.repo).resolve()
|
||||||
docs_path = (repo / args.docs).resolve()
|
docs_path = (repo / args.docs).resolve()
|
||||||
|
# Backward compatibility: fall back to legacy lowercase path when default path is absent.
|
||||||
|
if args.docs == "docs/TASKS.md" and not docs_path.exists():
|
||||||
|
legacy_docs_path = (repo / "docs/tasks.md").resolve()
|
||||||
|
if legacy_docs_path.exists():
|
||||||
|
docs_path = legacy_docs_path
|
||||||
tasks_path = (repo / args.tasks_json).resolve()
|
tasks_path = (repo / args.tasks_json).resolve()
|
||||||
config_path = repo / ".mosaic" / "orchestrator" / "config.json"
|
config_path = repo / ".mosaic" / "orchestrator" / "config.json"
|
||||||
config = load_json(config_path, {})
|
config = load_json(config_path, {})
|
||||||
runtime_default = str(config.get("worker", {}).get("runtime") or "codex")
|
runtime_default = str(config.get("worker", {}).get("runtime") or "codex")
|
||||||
|
|
||||||
rows = parse_tasks_markdown(docs_path)
|
rows = parse_tasks_markdown(docs_path)
|
||||||
|
try:
|
||||||
|
source_path = str(docs_path.relative_to(repo))
|
||||||
|
except ValueError:
|
||||||
|
source_path = str(docs_path)
|
||||||
existing_payload = load_json(tasks_path, {"tasks": []})
|
existing_payload = load_json(tasks_path, {"tasks": []})
|
||||||
existing_tasks = existing_payload.get("tasks", [])
|
existing_tasks = existing_payload.get("tasks", [])
|
||||||
if not isinstance(existing_tasks, list):
|
if not isinstance(existing_tasks, list):
|
||||||
@@ -153,7 +167,14 @@ def main() -> int:
|
|||||||
if not task_id:
|
if not task_id:
|
||||||
continue
|
continue
|
||||||
seen.add(task_id)
|
seen.add(task_id)
|
||||||
out_tasks.append(build_task(row, existing_by_id.get(task_id, {}), runtime_default))
|
out_tasks.append(
|
||||||
|
build_task(
|
||||||
|
row,
|
||||||
|
existing_by_id.get(task_id, {}),
|
||||||
|
runtime_default,
|
||||||
|
source_path,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
if args.keep_unlisted:
|
if args.keep_unlisted:
|
||||||
for task in existing_tasks:
|
for task in existing_tasks:
|
||||||
|
|||||||
@@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
## MANDATORY — Read Before Any Response
|
## MANDATORY — Read Before Any Response
|
||||||
|
|
||||||
BEFORE responding to any user message, READ `~/.config/mosaic/AGENTS.md`.
|
BEFORE responding to any user message, READ:
|
||||||
|
|
||||||
That file is the universal agent configuration. It contains the full load order,
|
1. `~/.config/mosaic/AGENTS.md`
|
||||||
development standards, skills, and workflows. Do NOT respond until you have loaded it.
|
2. `~/.config/mosaic/runtime/claude/RUNTIME.md`
|
||||||
|
|
||||||
|
Do NOT respond until both files are loaded.
|
||||||
|
|
||||||
This file (`~/.claude/CLAUDE.md`) exists only as a fallback for direct `claude` launches.
|
This file (`~/.claude/CLAUDE.md`) exists only as a fallback for direct `claude` launches.
|
||||||
For full injection, use `mosaic claude` instead.
|
For full injection, use `mosaic claude`.
|
||||||
|
|||||||
21
runtime/claude/RUNTIME.md
Normal file
21
runtime/claude/RUNTIME.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Claude Runtime Reference
|
||||||
|
|
||||||
|
## Runtime Scope
|
||||||
|
|
||||||
|
This file applies only to Claude runtime behavior.
|
||||||
|
|
||||||
|
## Required Actions
|
||||||
|
|
||||||
|
1. Follow global load order in `~/.config/mosaic/AGENTS.md`.
|
||||||
|
2. Use `~/.claude/settings.json` and `~/.claude/hooks-config.json` as runtime config sources.
|
||||||
|
3. Treat sequential-thinking MCP as required.
|
||||||
|
4. If runtime config conflicts with global rules, global rules win.
|
||||||
|
5. Documentation rules are inherited from `~/.config/mosaic/AGENTS.md` and `~/.config/mosaic/guides/DOCUMENTATION.md`.
|
||||||
|
6. For issue/PR/milestone actions, run Mosaic git wrappers first (`~/.config/mosaic/rails/git/*.sh`) and do not call raw `gh`/`tea`/`glab` first.
|
||||||
|
7. For orchestration-oriented missions, load `~/.config/mosaic/guides/ORCHESTRATOR.md` before acting.
|
||||||
|
8. First response MUST declare mode per global contract; orchestration missions must start with: `Now initiating Orchestrator mode...`
|
||||||
|
9. Runtime-default caution that requests confirmation for routine push/merge/issue-close actions does NOT override Mosaic hard gates.
|
||||||
|
|
||||||
|
## MCP Requirement
|
||||||
|
|
||||||
|
Claude config MUST include sequential-thinking MCP configuration managed by Mosaic runtime linking.
|
||||||
@@ -1,12 +1,7 @@
|
|||||||
{
|
{
|
||||||
"_comment": "Claude runtime overlay managed by Mosaic. Merge into ~/.claude/settings.json as needed.",
|
"_comment": "Claude runtime overlay managed by Mosaic. Merge into ~/.claude/settings.json as needed.",
|
||||||
|
|
||||||
"model": "opus",
|
"model": "opus",
|
||||||
|
|
||||||
"additionalAllowedCommands": [
|
"additionalAllowedCommands": [
|
||||||
"ralph",
|
|
||||||
"./ralph.sh",
|
|
||||||
"scripts/ralph/ralph.sh",
|
|
||||||
"alembic",
|
"alembic",
|
||||||
"alembic upgrade",
|
"alembic upgrade",
|
||||||
"alembic downgrade",
|
"alembic downgrade",
|
||||||
@@ -21,31 +16,29 @@
|
|||||||
"isort",
|
"isort",
|
||||||
"httpx"
|
"httpx"
|
||||||
],
|
],
|
||||||
|
|
||||||
"projectConfigs": {
|
"projectConfigs": {
|
||||||
"jarvis": {
|
"jarvis": {
|
||||||
"path": "~/src/jarvis",
|
"path": "~/src/jarvis",
|
||||||
"model": "opus",
|
"model": "opus",
|
||||||
"skills": ["jarvis", "ralph", "prd"],
|
"skills": ["jarvis", "prd"],
|
||||||
"guides": ["backend", "frontend", "authentication"],
|
"guides": ["E2E-DELIVERY", "PRD", "BACKEND", "FRONTEND", "AUTHENTICATION", "QA-TESTING", "CODE-REVIEW"],
|
||||||
"env": {
|
"env": {
|
||||||
"PYTHONPATH": "packages/plugins"
|
"PYTHONPATH": "packages/plugins"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"presets": {
|
"presets": {
|
||||||
"jarvis-ralph": {
|
"jarvis-loop": {
|
||||||
"description": "Ralph autonomous development for Jarvis",
|
"description": "Embedded E2E delivery cycle for Jarvis",
|
||||||
"model": "opus",
|
"model": "opus",
|
||||||
"skills": ["jarvis", "ralph"],
|
"skills": ["jarvis", "prd"],
|
||||||
"systemPrompt": "You are an autonomous coding agent following the Ralph pattern. Focus on one story at a time, run quality checks, and commit only when passing."
|
"systemPrompt": "You are an autonomous coding agent. For each logical unit, execute: plan, code, test, review, remediate, review, commit, push, then run a greenfield situational test. Repeat until requirements are complete."
|
||||||
},
|
},
|
||||||
"jarvis-review": {
|
"jarvis-review": {
|
||||||
"description": "Code review mode for Jarvis PRs",
|
"description": "Code review mode for Jarvis PRs",
|
||||||
"model": "opus",
|
"model": "opus",
|
||||||
"skills": ["jarvis"],
|
"skills": ["jarvis"],
|
||||||
"guides": ["code-review"],
|
"guides": ["CODE-REVIEW"],
|
||||||
"systemPrompt": "Review code changes for quality, security, and adherence to Jarvis patterns."
|
"systemPrompt": "Review code changes for quality, security, and adherence to Jarvis patterns."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -224,5 +224,14 @@
|
|||||||
"cpan",
|
"cpan",
|
||||||
"nohup"
|
"nohup"
|
||||||
],
|
],
|
||||||
"enableAllMcpTools": true
|
"enableAllMcpTools": true,
|
||||||
|
"mcpServers": {
|
||||||
|
"sequential-thinking": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@modelcontextprotocol/server-sequential-thinking"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
runtime/codex/RUNTIME.md
Normal file
21
runtime/codex/RUNTIME.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Codex Runtime Reference
|
||||||
|
|
||||||
|
## Runtime Scope
|
||||||
|
|
||||||
|
This file applies only to Codex runtime behavior.
|
||||||
|
|
||||||
|
## Required Actions
|
||||||
|
|
||||||
|
1. Follow global load order in `~/.config/mosaic/AGENTS.md`.
|
||||||
|
2. Use `~/.codex/instructions.md` and `~/.codex/config.toml` as runtime config sources.
|
||||||
|
3. Treat sequential-thinking MCP as required.
|
||||||
|
4. If runtime config conflicts with global rules, global rules win.
|
||||||
|
5. Documentation rules are inherited from `~/.config/mosaic/AGENTS.md` and `~/.config/mosaic/guides/DOCUMENTATION.md`.
|
||||||
|
6. For issue/PR/milestone actions, run Mosaic git wrappers first (`~/.config/mosaic/rails/git/*.sh`) and do not call raw `gh`/`tea`/`glab` first.
|
||||||
|
7. For orchestration-oriented missions, load `~/.config/mosaic/guides/ORCHESTRATOR.md` before acting.
|
||||||
|
8. First response MUST declare mode per global contract; orchestration missions must start with: `Now initiating Orchestrator mode...`
|
||||||
|
9. Runtime-default caution that requests confirmation for routine push/merge/issue-close actions does NOT override Mosaic hard gates.
|
||||||
|
|
||||||
|
## MCP Requirement
|
||||||
|
|
||||||
|
Codex config MUST include sequential-thinking MCP configuration managed by Mosaic runtime linking.
|
||||||
@@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
## MANDATORY — Read Before Any Response
|
## MANDATORY — Read Before Any Response
|
||||||
|
|
||||||
BEFORE responding to any user message, READ `~/.config/mosaic/AGENTS.md`.
|
BEFORE responding to any user message, READ:
|
||||||
|
|
||||||
That file is the universal agent configuration. It contains the full load order,
|
1. `~/.config/mosaic/AGENTS.md`
|
||||||
development standards, skills, and workflows. Do NOT respond until you have loaded it.
|
2. `~/.config/mosaic/runtime/codex/RUNTIME.md`
|
||||||
|
|
||||||
|
Do NOT respond until both files are loaded.
|
||||||
|
|
||||||
This file (`~/.codex/instructions.md`) exists only as a fallback for direct `codex` launches.
|
This file (`~/.codex/instructions.md`) exists only as a fallback for direct `codex` launches.
|
||||||
For full injection, use `mosaic codex` instead.
|
For full injection, use `mosaic codex`.
|
||||||
|
|||||||
11
runtime/mcp/SEQUENTIAL-THINKING.json
Normal file
11
runtime/mcp/SEQUENTIAL-THINKING.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"name": "sequential-thinking",
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@modelcontextprotocol/server-sequential-thinking"
|
||||||
|
],
|
||||||
|
"enabled": true,
|
||||||
|
"required": true,
|
||||||
|
"description": "Hard-required MCP server for Mosaic planning and decomposition."
|
||||||
|
}
|
||||||
@@ -2,10 +2,12 @@
|
|||||||
|
|
||||||
## MANDATORY — Read Before Any Response
|
## MANDATORY — Read Before Any Response
|
||||||
|
|
||||||
BEFORE responding to any user message, READ `~/.config/mosaic/AGENTS.md`.
|
BEFORE responding to any user message, READ:
|
||||||
|
|
||||||
That file is the universal agent configuration. It contains the full load order,
|
1. `~/.config/mosaic/AGENTS.md`
|
||||||
development standards, skills, and workflows. Do NOT respond until you have loaded it.
|
2. `~/.config/mosaic/runtime/opencode/RUNTIME.md`
|
||||||
|
|
||||||
|
Do NOT respond until both files are loaded.
|
||||||
|
|
||||||
This file (`~/.config/opencode/AGENTS.md`) exists only as a fallback for direct `opencode` launches.
|
This file (`~/.config/opencode/AGENTS.md`) exists only as a fallback for direct `opencode` launches.
|
||||||
For full injection, use `mosaic opencode` instead.
|
For full injection, use `mosaic opencode`.
|
||||||
|
|||||||
21
runtime/opencode/RUNTIME.md
Normal file
21
runtime/opencode/RUNTIME.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# OpenCode Runtime Reference
|
||||||
|
|
||||||
|
## Runtime Scope
|
||||||
|
|
||||||
|
This file applies only to OpenCode runtime behavior.
|
||||||
|
|
||||||
|
## Required Actions
|
||||||
|
|
||||||
|
1. Follow global load order in `~/.config/mosaic/AGENTS.md`.
|
||||||
|
2. Use `~/.config/opencode/AGENTS.md` and local OpenCode runtime config as runtime sources.
|
||||||
|
3. Treat sequential-thinking MCP as required.
|
||||||
|
4. If runtime config conflicts with global rules, global rules win.
|
||||||
|
5. Documentation rules are inherited from `~/.config/mosaic/AGENTS.md` and `~/.config/mosaic/guides/DOCUMENTATION.md`.
|
||||||
|
6. For issue/PR/milestone actions, run Mosaic git wrappers first (`~/.config/mosaic/rails/git/*.sh`) and do not call raw `gh`/`tea`/`glab` first.
|
||||||
|
7. For orchestration-oriented missions, load `~/.config/mosaic/guides/ORCHESTRATOR.md` before acting.
|
||||||
|
8. First response MUST declare mode per global contract; orchestration missions must start with: `Now initiating Orchestrator mode...`
|
||||||
|
9. Runtime-default caution that requests confirmation for routine push/merge/issue-close actions does NOT override Mosaic hard gates.
|
||||||
|
|
||||||
|
## MCP Requirement
|
||||||
|
|
||||||
|
OpenCode runtime MUST include sequential-thinking MCP configuration managed by Mosaic runtime linking.
|
||||||
@@ -162,7 +162,7 @@ npm run format
|
|||||||
| Issue | Feature | Priority |
|
| Issue | Feature | Priority |
|
||||||
|-------|---------|----------|
|
|-------|---------|----------|
|
||||||
| #84 | Per-function LLM routing | High |
|
| #84 | Per-function LLM routing | High |
|
||||||
| #85 | Ralph autonomous coding loop | High |
|
| #85 | Embedded E2E autonomous delivery loop | High |
|
||||||
| #86 | Thinking models (CoT UI) | Medium |
|
| #86 | Thinking models (CoT UI) | Medium |
|
||||||
| #87 | Local image generation | Medium |
|
| #87 | Local image generation | Medium |
|
||||||
| #88 | Deep research mode | Medium |
|
| #88 | Deep research mode | Medium |
|
||||||
|
|||||||
@@ -1,257 +0,0 @@
|
|||||||
---
|
|
||||||
name: ralph
|
|
||||||
description: "Convert PRDs to prd.json format for the Ralph autonomous agent system. Use when you have an existing PRD and need to convert it to Ralph's JSON format. Triggers on: convert this prd, turn this into ralph format, create prd.json from this, ralph json."
|
|
||||||
---
|
|
||||||
|
|
||||||
# Ralph PRD Converter
|
|
||||||
|
|
||||||
Converts existing PRDs to the prd.json format that Ralph uses for autonomous execution.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## The Job
|
|
||||||
|
|
||||||
Take a PRD (markdown file or text) and convert it to `prd.json` in your ralph directory.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Output Format
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"project": "[Project Name]",
|
|
||||||
"branchName": "ralph/[feature-name-kebab-case]",
|
|
||||||
"description": "[Feature description from PRD title/intro]",
|
|
||||||
"userStories": [
|
|
||||||
{
|
|
||||||
"id": "US-001",
|
|
||||||
"title": "[Story title]",
|
|
||||||
"description": "As a [user], I want [feature] so that [benefit]",
|
|
||||||
"acceptanceCriteria": [
|
|
||||||
"Criterion 1",
|
|
||||||
"Criterion 2",
|
|
||||||
"Typecheck passes"
|
|
||||||
],
|
|
||||||
"priority": 1,
|
|
||||||
"passes": false,
|
|
||||||
"notes": ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Story Size: The Number One Rule
|
|
||||||
|
|
||||||
**Each story must be completable in ONE Ralph iteration (one context window).**
|
|
||||||
|
|
||||||
Ralph spawns a fresh Amp instance per iteration with no memory of previous work. If a story is too big, the LLM runs out of context before finishing and produces broken code.
|
|
||||||
|
|
||||||
### Right-sized stories:
|
|
||||||
- Add a database column and migration
|
|
||||||
- Add a UI component to an existing page
|
|
||||||
- Update a server action with new logic
|
|
||||||
- Add a filter dropdown to a list
|
|
||||||
|
|
||||||
### Too big (split these):
|
|
||||||
- "Build the entire dashboard" - Split into: schema, queries, UI components, filters
|
|
||||||
- "Add authentication" - Split into: schema, middleware, login UI, session handling
|
|
||||||
- "Refactor the API" - Split into one story per endpoint or pattern
|
|
||||||
|
|
||||||
**Rule of thumb:** If you cannot describe the change in 2-3 sentences, it is too big.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Story Ordering: Dependencies First
|
|
||||||
|
|
||||||
Stories execute in priority order. Earlier stories must not depend on later ones.
|
|
||||||
|
|
||||||
**Correct order:**
|
|
||||||
1. Schema/database changes (migrations)
|
|
||||||
2. Server actions / backend logic
|
|
||||||
3. UI components that use the backend
|
|
||||||
4. Dashboard/summary views that aggregate data
|
|
||||||
|
|
||||||
**Wrong order:**
|
|
||||||
1. UI component (depends on schema that does not exist yet)
|
|
||||||
2. Schema change
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Acceptance Criteria: Must Be Verifiable
|
|
||||||
|
|
||||||
Each criterion must be something Ralph can CHECK, not something vague.
|
|
||||||
|
|
||||||
### Good criteria (verifiable):
|
|
||||||
- "Add `status` column to tasks table with default 'pending'"
|
|
||||||
- "Filter dropdown has options: All, Active, Completed"
|
|
||||||
- "Clicking delete shows confirmation dialog"
|
|
||||||
- "Typecheck passes"
|
|
||||||
- "Tests pass"
|
|
||||||
|
|
||||||
### Bad criteria (vague):
|
|
||||||
- "Works correctly"
|
|
||||||
- "User can do X easily"
|
|
||||||
- "Good UX"
|
|
||||||
- "Handles edge cases"
|
|
||||||
|
|
||||||
### Always include as final criterion:
|
|
||||||
```
|
|
||||||
"Typecheck passes"
|
|
||||||
```
|
|
||||||
|
|
||||||
For stories with testable logic, also include:
|
|
||||||
```
|
|
||||||
"Tests pass"
|
|
||||||
```
|
|
||||||
|
|
||||||
### For stories that change UI, also include:
|
|
||||||
```
|
|
||||||
"Verify in browser using dev-browser skill"
|
|
||||||
```
|
|
||||||
|
|
||||||
Frontend stories are NOT complete until visually verified. Ralph will use the dev-browser skill to navigate to the page, interact with the UI, and confirm changes work.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Conversion Rules
|
|
||||||
|
|
||||||
1. **Each user story becomes one JSON entry**
|
|
||||||
2. **IDs**: Sequential (US-001, US-002, etc.)
|
|
||||||
3. **Priority**: Based on dependency order, then document order
|
|
||||||
4. **All stories**: `passes: false` and empty `notes`
|
|
||||||
5. **branchName**: Derive from feature name, kebab-case, prefixed with `ralph/`
|
|
||||||
6. **Always add**: "Typecheck passes" to every story's acceptance criteria
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Splitting Large PRDs
|
|
||||||
|
|
||||||
If a PRD has big features, split them:
|
|
||||||
|
|
||||||
**Original:**
|
|
||||||
> "Add user notification system"
|
|
||||||
|
|
||||||
**Split into:**
|
|
||||||
1. US-001: Add notifications table to database
|
|
||||||
2. US-002: Create notification service for sending notifications
|
|
||||||
3. US-003: Add notification bell icon to header
|
|
||||||
4. US-004: Create notification dropdown panel
|
|
||||||
5. US-005: Add mark-as-read functionality
|
|
||||||
6. US-006: Add notification preferences page
|
|
||||||
|
|
||||||
Each is one focused change that can be completed and verified independently.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
**Input PRD:**
|
|
||||||
```markdown
|
|
||||||
# Task Status Feature
|
|
||||||
|
|
||||||
Add ability to mark tasks with different statuses.
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
- Toggle between pending/in-progress/done on task list
|
|
||||||
- Filter list by status
|
|
||||||
- Show status badge on each task
|
|
||||||
- Persist status in database
|
|
||||||
```
|
|
||||||
|
|
||||||
**Output prd.json:**
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"project": "TaskApp",
|
|
||||||
"branchName": "ralph/task-status",
|
|
||||||
"description": "Task Status Feature - Track task progress with status indicators",
|
|
||||||
"userStories": [
|
|
||||||
{
|
|
||||||
"id": "US-001",
|
|
||||||
"title": "Add status field to tasks table",
|
|
||||||
"description": "As a developer, I need to store task status in the database.",
|
|
||||||
"acceptanceCriteria": [
|
|
||||||
"Add status column: 'pending' | 'in_progress' | 'done' (default 'pending')",
|
|
||||||
"Generate and run migration successfully",
|
|
||||||
"Typecheck passes"
|
|
||||||
],
|
|
||||||
"priority": 1,
|
|
||||||
"passes": false,
|
|
||||||
"notes": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "US-002",
|
|
||||||
"title": "Display status badge on task cards",
|
|
||||||
"description": "As a user, I want to see task status at a glance.",
|
|
||||||
"acceptanceCriteria": [
|
|
||||||
"Each task card shows colored status badge",
|
|
||||||
"Badge colors: gray=pending, blue=in_progress, green=done",
|
|
||||||
"Typecheck passes",
|
|
||||||
"Verify in browser using dev-browser skill"
|
|
||||||
],
|
|
||||||
"priority": 2,
|
|
||||||
"passes": false,
|
|
||||||
"notes": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "US-003",
|
|
||||||
"title": "Add status toggle to task list rows",
|
|
||||||
"description": "As a user, I want to change task status directly from the list.",
|
|
||||||
"acceptanceCriteria": [
|
|
||||||
"Each row has status dropdown or toggle",
|
|
||||||
"Changing status saves immediately",
|
|
||||||
"UI updates without page refresh",
|
|
||||||
"Typecheck passes",
|
|
||||||
"Verify in browser using dev-browser skill"
|
|
||||||
],
|
|
||||||
"priority": 3,
|
|
||||||
"passes": false,
|
|
||||||
"notes": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "US-004",
|
|
||||||
"title": "Filter tasks by status",
|
|
||||||
"description": "As a user, I want to filter the list to see only certain statuses.",
|
|
||||||
"acceptanceCriteria": [
|
|
||||||
"Filter dropdown: All | Pending | In Progress | Done",
|
|
||||||
"Filter persists in URL params",
|
|
||||||
"Typecheck passes",
|
|
||||||
"Verify in browser using dev-browser skill"
|
|
||||||
],
|
|
||||||
"priority": 4,
|
|
||||||
"passes": false,
|
|
||||||
"notes": ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Archiving Previous Runs
|
|
||||||
|
|
||||||
**Before writing a new prd.json, check if there is an existing one from a different feature:**
|
|
||||||
|
|
||||||
1. Read the current `prd.json` if it exists
|
|
||||||
2. Check if `branchName` differs from the new feature's branch name
|
|
||||||
3. If different AND `progress.txt` has content beyond the header:
|
|
||||||
- Create archive folder: `archive/YYYY-MM-DD-feature-name/`
|
|
||||||
- Copy current `prd.json` and `progress.txt` to archive
|
|
||||||
- Reset `progress.txt` with fresh header
|
|
||||||
|
|
||||||
**The ralph.sh script handles this automatically** when you run it, but if you are manually updating prd.json between runs, archive first.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Checklist Before Saving
|
|
||||||
|
|
||||||
Before writing prd.json, verify:
|
|
||||||
|
|
||||||
- [ ] **Previous run archived** (if prd.json exists with different branchName, archive it first)
|
|
||||||
- [ ] Each story is completable in one iteration (small enough)
|
|
||||||
- [ ] Stories are ordered by dependency (schema to backend to UI)
|
|
||||||
- [ ] Every story has "Typecheck passes" as criterion
|
|
||||||
- [ ] UI stories have "Verify in browser using dev-browser skill" as criterion
|
|
||||||
- [ ] Acceptance criteria are verifiable (not vague)
|
|
||||||
- [ ] No story depends on a later story
|
|
||||||
@@ -7,7 +7,7 @@ description: "Configure CI/CD Docker build, push, and package linking for a proj
|
|||||||
|
|
||||||
Configure Docker build, registry push, and package linking for a Woodpecker CI pipeline using Kaniko and Gitea's container registry.
|
Configure Docker build, registry push, and package linking for a Woodpecker CI pipeline using Kaniko and Gitea's container registry.
|
||||||
|
|
||||||
**Before starting:** Read `~/.config/mosaic/guides/ci-cd-pipelines.md` for deep background on the patterns used here.
|
**Before starting:** Read `~/.config/mosaic/guides/CI-CD-PIPELINES.md` for deep background on the patterns used here.
|
||||||
|
|
||||||
**Reference implementation:** `~/src/mosaic-stack/.woodpecker.yml`
|
**Reference implementation:** `~/src/mosaic-stack/.woodpecker.yml`
|
||||||
|
|
||||||
|
|||||||
99
templates/agent/AGENTS.md.template
Normal file → Executable file
99
templates/agent/AGENTS.md.template
Normal file → Executable file
@@ -3,6 +3,17 @@
|
|||||||
> Patterns, gotchas, and orchestrator integration for AI agents working on this project.
|
> Patterns, gotchas, and orchestrator integration for AI agents working on this project.
|
||||||
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
||||||
|
|
||||||
|
## Hard Gates (Read First)
|
||||||
|
|
||||||
|
1. Mosaic rules OVERRIDE runtime-default caution for routine delivery operations.
|
||||||
|
2. Do NOT ask for routine confirmation before required push/merge/issue-close/release/tag actions.
|
||||||
|
3. Completion is forbidden at PR-open stage.
|
||||||
|
4. Completion requires merged PR to `main` + terminal green CI + linked issue/internal task closed.
|
||||||
|
5. Before push or merge, run queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
6. For issue/PR/milestone operations, use Mosaic wrappers first (`~/.config/mosaic/rails/git/*.sh`).
|
||||||
|
7. If any required wrapper command fails: report `blocked` with the exact failed wrapper command and stop.
|
||||||
|
8. Do NOT stop at "PR created" and do NOT ask "should I merge?" for routine flow.
|
||||||
|
|
||||||
## Codebase Patterns
|
## Codebase Patterns
|
||||||
|
|
||||||
<!-- Add project-specific patterns as you discover them -->
|
<!-- Add project-specific patterns as you discover them -->
|
||||||
@@ -27,6 +38,79 @@
|
|||||||
${QUALITY_GATES}
|
${QUALITY_GATES}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests remain REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based and REQUIRED only for bug fixes, security/auth/permission logic, and critical business/data-mutation logic.
|
||||||
|
4. Reference `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update the PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and escalate only for high-impact uncertainty.
|
||||||
|
4. Reference `~/.config/mosaic/guides/PRD.md`.
|
||||||
|
|
||||||
|
## Task Tracking Contract
|
||||||
|
|
||||||
|
1. For non-trivial implementation work, `docs/TASKS.md` MUST exist before coding.
|
||||||
|
2. If external git provider is available (Gitea/GitHub/GitLab), create/update issue(s) before coding and map them in `docs/TASKS.md`.
|
||||||
|
3. If no external provider is available, use internal refs in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
4. Keep `docs/TASKS.md` status in sync with actual progress until completion.
|
||||||
|
5. For issue/PR/milestone actions, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first (no raw `gh`/`tea`/`glab` as first choice).
|
||||||
|
6. If wrapper-driven merge/CI/issue-closure fails, report blocker with the exact failed wrapper command and stop (do not claim completion).
|
||||||
|
|
||||||
|
## Documentation Contract
|
||||||
|
|
||||||
|
Documentation is a hard delivery gate.
|
||||||
|
If code/API/auth/infra changes, required documentation updates MUST be completed before task closure.
|
||||||
|
Keep `docs/` root clean and store reports/artifacts in scoped folders (`docs/reports/`, `docs/tasks/`, `docs/releases/`, `docs/scratchpads/`).
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
- `~/.config/mosaic/guides/DOCUMENTATION.md`
|
||||||
|
- `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md`
|
||||||
|
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Shift to conservative strategy when budget pressure rises (smaller scope, fewer parallel actions, reduced re-reading).
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
|
## Merge Strategy (Hard Rule)
|
||||||
|
|
||||||
|
1. Create short-lived branches from `main`.
|
||||||
|
2. Open PRs to `main` for delivery changes.
|
||||||
|
3. Do not push directly to `main`.
|
||||||
|
4. Merge PRs to `main` with squash strategy only.
|
||||||
|
5. Do not mark implementation complete until PR is merged.
|
||||||
|
6. Do not mark implementation complete until CI/pipeline status is terminal green.
|
||||||
|
7. Close linked issues/tasks only after merge + green CI.
|
||||||
|
8. Before push or merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
|
||||||
|
## Container Release Strategy (When Applicable)
|
||||||
|
|
||||||
|
1. Use immutable image tags: `sha-<shortsha>` and `v{base-version}-rc.{build}`.
|
||||||
|
2. Use mutable environment tags only as pointers (`testing`, optional `staging`, `prod`).
|
||||||
|
3. Deploy/promote by immutable digest; do not deploy by mutable tag alone.
|
||||||
|
4. Do not use `latest` or `dev` as deployment references.
|
||||||
|
5. Use blue-green by default; use canary only with automated metrics and rollback gates.
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns end-to-end delivery: plan, code, test, review, remediate, commit, push, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Code review is agent-executed and REQUIRED for any source-code change.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Orchestrator Integration
|
## Orchestrator Integration
|
||||||
|
|
||||||
### Task Prefix
|
### Task Prefix
|
||||||
@@ -43,14 +127,17 @@ Use `${TASK_PREFIX}` as the prefix for orchestrated tasks (e.g., `${TASK_PREFIX}
|
|||||||
|
|
||||||
### Worker Checklist
|
### Worker Checklist
|
||||||
When completing an orchestrated task:
|
When completing an orchestrated task:
|
||||||
1. Read the finding details from the report
|
1. Read `docs/PRD.md` or `docs/PRD.json`
|
||||||
2. Implement the fix following existing code patterns
|
2. Read the finding details from the report
|
||||||
3. Run quality gates (ALL must pass)
|
3. Implement the fix following existing code patterns
|
||||||
4. Commit with: `git commit -m "fix({finding_id}): brief description"`
|
4. Run quality gates (ALL must pass)
|
||||||
5. Report result as JSON to orchestrator
|
5. Complete required documentation updates (if applicable)
|
||||||
|
6. Commit with: `git commit -m "fix({finding_id}): brief description"`
|
||||||
|
7. Report result as JSON to orchestrator
|
||||||
|
|
||||||
### Post-Coding Review
|
### Post-Coding Review
|
||||||
After implementing changes, the orchestrator will run:
|
After implementing changes, code review is REQUIRED for any source-code modification.
|
||||||
|
For orchestrated tasks, the orchestrator will run:
|
||||||
1. **Codex code review** — `~/.config/mosaic/rails/codex/codex-code-review.sh --uncommitted`
|
1. **Codex code review** — `~/.config/mosaic/rails/codex/codex-code-review.sh --uncommitted`
|
||||||
2. **Codex security review** — `~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted`
|
2. **Codex security review** — `~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted`
|
||||||
3. If blockers/critical findings: remediation task created
|
3. If blockers/critical findings: remediation task created
|
||||||
|
|||||||
102
templates/agent/CLAUDE.md.template
Normal file → Executable file
102
templates/agent/CLAUDE.md.template
Normal file → Executable file
@@ -1,4 +1,4 @@
|
|||||||
# ${PROJECT_NAME} — Claude Code Instructions
|
# ${PROJECT_NAME} — Runtime Compatibility Instructions
|
||||||
|
|
||||||
> **Project:** ${PROJECT_DESCRIPTION}
|
> **Project:** ${PROJECT_DESCRIPTION}
|
||||||
> **Repository:** ${REPO_URL}
|
> **Repository:** ${REPO_URL}
|
||||||
@@ -20,18 +20,21 @@ git push
|
|||||||
|
|
||||||
## Conditional Documentation Loading
|
## Conditional Documentation Loading
|
||||||
|
|
||||||
**Read the relevant guide before starting work:**
|
**Load `~/.config/mosaic/guides/E2E-DELIVERY.md` first, then load the relevant guide before starting work:**
|
||||||
|
|
||||||
| Task Type | Guide |
|
| Task Type | Guide |
|
||||||
|-----------|-------|
|
|-----------|-------|
|
||||||
| Bootstrapping this project | `~/.config/mosaic/guides/bootstrap.md` |
|
| End-to-end implementation and validation | `~/.config/mosaic/guides/E2E-DELIVERY.md` |
|
||||||
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/orchestrator.md` |
|
| PRD creation and requirements definition | `~/.config/mosaic/guides/PRD.md` |
|
||||||
| Code review | `~/.config/mosaic/guides/code-review.md` |
|
| Bootstrapping this project | `~/.config/mosaic/guides/BOOTSTRAP.md` |
|
||||||
| Frontend development | `~/.config/mosaic/guides/frontend.md` |
|
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/ORCHESTRATOR.md` |
|
||||||
| Backend/API development | `~/.config/mosaic/guides/backend.md` |
|
| Code review | `~/.config/mosaic/guides/CODE-REVIEW.md` |
|
||||||
| Authentication/Authorization | `~/.config/mosaic/guides/authentication.md` |
|
| Documentation updates and standards | `~/.config/mosaic/guides/DOCUMENTATION.md` |
|
||||||
| Infrastructure/DevOps | `~/.config/mosaic/guides/infrastructure.md` |
|
| Frontend development | `~/.config/mosaic/guides/FRONTEND.md` |
|
||||||
| QA/Testing | `~/.config/mosaic/guides/qa-testing.md` |
|
| Backend/API development | `~/.config/mosaic/guides/BACKEND.md` |
|
||||||
|
| Authentication/Authorization | `~/.config/mosaic/guides/AUTHENTICATION.md` |
|
||||||
|
| Infrastructure/DevOps | `~/.config/mosaic/guides/INFRASTRUCTURE.md` |
|
||||||
|
| QA/Testing | `~/.config/mosaic/guides/QA-TESTING.md` |
|
||||||
|
|
||||||
## Technology Stack
|
## Technology Stack
|
||||||
|
|
||||||
@@ -50,6 +53,7 @@ ${PROJECT_DIR}/
|
|||||||
├── CLAUDE.md # This file
|
├── CLAUDE.md # This file
|
||||||
├── AGENTS.md # Agent-specific patterns and gotchas
|
├── AGENTS.md # Agent-specific patterns and gotchas
|
||||||
├── docs/
|
├── docs/
|
||||||
|
│ ├── PRD.md # Requirements source (or PRD.json)
|
||||||
│ ├── scratchpads/ # Per-issue working documents
|
│ ├── scratchpads/ # Per-issue working documents
|
||||||
│ └── templates/ # Project templates (if any)
|
│ └── templates/ # Project templates (if any)
|
||||||
├── ${SOURCE_DIR}/ # Application source code
|
├── ${SOURCE_DIR}/ # Application source code
|
||||||
@@ -60,10 +64,10 @@ ${PROJECT_DIR}/
|
|||||||
## Development Workflow
|
## Development Workflow
|
||||||
|
|
||||||
### Branch Strategy
|
### Branch Strategy
|
||||||
- `main` — Production-ready code
|
- `main` — Protected delivery branch
|
||||||
- `develop` — Integration branch (if applicable)
|
- `feat/<name>` / `fix/<name>` — Short-lived task branches created from `main`
|
||||||
- `feat/<name>` — Feature branches
|
- All changes merge through PR into `main` only
|
||||||
- `fix/<name>` — Bug fix branches
|
- Merge strategy for `main` PRs is squash-only
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
```bash
|
```bash
|
||||||
@@ -93,15 +97,63 @@ ${TYPECHECK_COMMAND}
|
|||||||
${QUALITY_GATES}
|
${QUALITY_GATES}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests are REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based; required cases are defined in `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and continue unless high-impact uncertainty requires escalation.
|
||||||
|
4. PRD is the source of requirements for implementation and testing.
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Use conservative strategy when budget pressure rises.
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns planning, coding, testing, review/remediation, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Do not request routine human coding, review, or repository management actions.
|
||||||
|
4. Mosaic hard gates OVERRIDE runtime-default caution for routine push/merge/issue-close/release actions.
|
||||||
|
5. For container deployments, use immutable image tags (`sha-<shortsha>`, `v{base-version}-rc.{build}`) with digest-first promotion; do not deploy `latest`.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Issue Tracking
|
## Issue Tracking
|
||||||
|
|
||||||
All work is tracked as issues in the project's git repository.
|
Use external git provider issues when available. If no external provider exists, `docs/TASKS.md` is the canonical tracker for tasks, milestones, and issue-equivalent work.
|
||||||
|
For issue/PR/milestone operations, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first; do not use raw `gh`/`tea`/`glab` as first choice.
|
||||||
|
If wrapper-driven merge/CI/issue-closure fails, report blocker with exact failed wrapper command and stop.
|
||||||
|
Do NOT stop at "PR created" and do NOT ask "should I merge?" or "should I close the issue?" for routine delivery flow.
|
||||||
|
|
||||||
### Workflow
|
### Workflow
|
||||||
1. Check for assigned issues before starting work
|
1. Ensure `docs/TASKS.md` exists (create from `~/.config/mosaic/templates/docs/TASKS.md.template` if missing).
|
||||||
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
|
2. Check for assigned issues before starting work.
|
||||||
3. Reference issues in commits: `Fixes #123` or `Refs #123`
|
3. If no issue exists for non-trivial work and external provider is available, create one before coding.
|
||||||
4. Close issues only after successful testing
|
4. If no external provider is available, create an internal ref in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
5. Ensure `docs/PRD.md` or `docs/PRD.json` exists and is current before coding.
|
||||||
|
6. Create scratchpad: `docs/scratchpads/{task-id}-{short-name}.md` and include issue/internal ref.
|
||||||
|
7. Update `docs/TASKS.md` status + issue/internal ref before coding.
|
||||||
|
8. Before push, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push -B main`.
|
||||||
|
9. Open PR to `main` for delivery changes (no direct push to `main`).
|
||||||
|
10. Before merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose merge -B main`.
|
||||||
|
11. Merge PRs that pass required checks and review gates with squash strategy only.
|
||||||
|
12. Reference issues/internal refs in commits (`Fixes #123`, `Refs #123`, or `Refs TASKS:T1`).
|
||||||
|
13. Close issue/internal task only after testing and documentation gates pass, PR merge is complete, and CI/pipeline status is terminal green.
|
||||||
|
14. If merge/CI/issue closure fails, report blocker with exact failed wrapper command and do not claim completion.
|
||||||
|
|
||||||
### Labels
|
### Labels
|
||||||
Use consistent labels: `epic`, `feature`, `bug`, `task`, `documentation`, `security`, `breaking`
|
Use consistent labels: `epic`, `feature`, `bug`, `task`, `documentation`, `security`, `breaking`
|
||||||
@@ -119,7 +171,8 @@ Types: `feat`, `fix`, `docs`, `test`, `refactor`, `chore`
|
|||||||
## Code Review
|
## Code Review
|
||||||
|
|
||||||
### Independent Review (Automated)
|
### Independent Review (Automated)
|
||||||
After completing code changes, run independent reviews:
|
If you modify source code, independent code review is REQUIRED before completion.
|
||||||
|
Run independent reviews:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Code quality review (Codex)
|
# Code quality review (Codex)
|
||||||
@@ -132,7 +185,8 @@ After completing code changes, run independent reviews:
|
|||||||
**Fallback:** If Codex is unavailable, use Claude's built-in review skills.
|
**Fallback:** If Codex is unavailable, use Claude's built-in review skills.
|
||||||
|
|
||||||
### Review Checklist
|
### Review Checklist
|
||||||
See `~/.config/mosaic/guides/code-review.md` for the full review checklist.
|
See `~/.config/mosaic/guides/CODE-REVIEW.md` for the full review checklist.
|
||||||
|
See `~/.config/mosaic/guides/DOCUMENTATION.md` for required documentation deliverables.
|
||||||
|
|
||||||
## Secrets Management
|
## Secrets Management
|
||||||
|
|
||||||
@@ -149,3 +203,9 @@ When multiple agents work on this project:
|
|||||||
1. `git pull --rebase` before editing
|
1. `git pull --rebase` before editing
|
||||||
2. `git pull --rebase` before pushing
|
2. `git pull --rebase` before pushing
|
||||||
3. If conflicts, **alert the user** — don't auto-resolve data conflicts
|
3. If conflicts, **alert the user** — don't auto-resolve data conflicts
|
||||||
|
|
||||||
|
## Runtime Notes
|
||||||
|
|
||||||
|
- This file is runtime-compatibility context.
|
||||||
|
- Global rules are defined in `~/.config/mosaic/AGENTS.md`.
|
||||||
|
- Runtime-specific behavior is defined in `~/.config/mosaic/runtime/<runtime>/RUNTIME.md`.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
> Defines what "well-configured" means for AI agent development across all coding projects.
|
> Defines what "well-configured" means for AI agent development across all coding projects.
|
||||||
|
|
||||||
## CLAUDE.md — Required Sections
|
## Runtime Context File — Required Sections
|
||||||
|
|
||||||
### Tier 1 (Required — blocks audit pass)
|
### Tier 1 (Required — blocks audit pass)
|
||||||
|
|
||||||
@@ -54,10 +54,10 @@ The `agent-lint.sh` tool checks for these markers:
|
|||||||
|
|
||||||
| Check | Pass Criteria |
|
| Check | Pass Criteria |
|
||||||
|-------|---------------|
|
|-------|---------------|
|
||||||
| CLAUDE.md exists | File present at project root |
|
| Runtime context file exists | `CLAUDE.md` or `RUNTIME.md` present at project root |
|
||||||
| AGENTS.md exists | File present at project root |
|
| AGENTS.md exists | File present at project root |
|
||||||
| Conditional context/loading | CLAUDE.md contains `~/.config/mosaic/guides` or `Conditional` + `Loading/Context` |
|
| Conditional context/loading | Runtime context file contains `~/.config/mosaic/guides` or `Conditional` + `Loading/Context` |
|
||||||
| Quality gates | CLAUDE.md contains `Quality Gates` or quality commands (test, lint, typecheck) |
|
| Quality gates | Runtime context file contains `Quality Gates` or quality commands (test, lint, typecheck) |
|
||||||
| Monorepo sub-agents | Each app/package dir with own manifest has AGENTS.md |
|
| Monorepo sub-agents | Each app/package dir with own manifest has AGENTS.md |
|
||||||
|
|
||||||
## Fragment Sources
|
## Fragment Sources
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
## Code Review
|
## Code Review
|
||||||
|
|
||||||
After completing code changes, run independent reviews:
|
If you modify source code, independent code review is REQUIRED before completion.
|
||||||
|
Run independent reviews:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Code quality review (Codex)
|
# Code quality review (Codex)
|
||||||
@@ -11,4 +12,4 @@ After completing code changes, run independent reviews:
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Fallback:** If Codex is unavailable, use Claude's built-in review skills.
|
**Fallback:** If Codex is unavailable, use Claude's built-in review skills.
|
||||||
See `~/.config/mosaic/guides/code-review.md` for the full review checklist.
|
See `~/.config/mosaic/guides/CODE-REVIEW.md` for the full review checklist.
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
## Conditional Documentation Loading
|
## Conditional Documentation Loading
|
||||||
|
|
||||||
**Read the relevant guide before starting work:**
|
**Load `~/.config/mosaic/guides/E2E-DELIVERY.md` first, then load the relevant guide before starting work:**
|
||||||
|
|
||||||
| Task Type | Guide |
|
| Task Type | Guide |
|
||||||
|-----------|-------|
|
|-----------|-------|
|
||||||
| Bootstrapping a new project | `~/.config/mosaic/guides/bootstrap.md` |
|
| End-to-end implementation and validation | `~/.config/mosaic/guides/E2E-DELIVERY.md` |
|
||||||
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/orchestrator.md` |
|
| Bootstrapping a new project | `~/.config/mosaic/guides/BOOTSTRAP.md` |
|
||||||
| Ralph autonomous development | `~/.config/mosaic/guides/ralph-autonomous.md` |
|
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/ORCHESTRATOR.md` |
|
||||||
| Frontend development | `~/.config/mosaic/guides/frontend.md` |
|
| Frontend development | `~/.config/mosaic/guides/FRONTEND.md` |
|
||||||
| Backend/API development | `~/.config/mosaic/guides/backend.md` |
|
| Backend/API development | `~/.config/mosaic/guides/BACKEND.md` |
|
||||||
| TypeScript strict typing | `~/.config/mosaic/guides/typescript.md` |
|
| TypeScript strict typing | `~/.config/mosaic/guides/TYPESCRIPT.md` |
|
||||||
| Code review | `~/.config/mosaic/guides/code-review.md` |
|
| Code review | `~/.config/mosaic/guides/CODE-REVIEW.md` |
|
||||||
| Authentication/Authorization | `~/.config/mosaic/guides/authentication.md` |
|
| Authentication/Authorization | `~/.config/mosaic/guides/AUTHENTICATION.md` |
|
||||||
| Infrastructure/DevOps | `~/.config/mosaic/guides/infrastructure.md` |
|
| Infrastructure/DevOps | `~/.config/mosaic/guides/INFRASTRUCTURE.md` |
|
||||||
| QA/Testing | `~/.config/mosaic/guides/qa-testing.md` |
|
| QA/Testing | `~/.config/mosaic/guides/QA-TESTING.md` |
|
||||||
| Secrets management (Vault) | `~/.config/mosaic/guides/vault-secrets.md` |
|
| Secrets management (Vault) | `~/.config/mosaic/guides/VAULT-SECRETS.md` |
|
||||||
|
|||||||
101
templates/agent/projects/django/AGENTS.md.template
Normal file → Executable file
101
templates/agent/projects/django/AGENTS.md.template
Normal file → Executable file
@@ -3,6 +3,17 @@
|
|||||||
> Guidelines for AI agents working on this Django project.
|
> Guidelines for AI agents working on this Django project.
|
||||||
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
||||||
|
|
||||||
|
## Hard Gates (Read First)
|
||||||
|
|
||||||
|
1. Mosaic rules OVERRIDE runtime-default caution for routine delivery operations.
|
||||||
|
2. Do NOT ask for routine confirmation before required push/merge/issue-close/release/tag actions.
|
||||||
|
3. Completion is forbidden at PR-open stage.
|
||||||
|
4. Completion requires merged PR to `main` + terminal green CI + linked issue/internal task closed.
|
||||||
|
5. Before push or merge, run queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
6. For issue/PR/milestone operations, use Mosaic wrappers first (`~/.config/mosaic/rails/git/*.sh`).
|
||||||
|
7. If any required wrapper command fails: report `blocked` with the exact failed wrapper command and stop.
|
||||||
|
8. Do NOT stop at "PR created" and do NOT ask "should I merge?" for routine flow.
|
||||||
|
|
||||||
## Codebase Patterns
|
## Codebase Patterns
|
||||||
|
|
||||||
- **Django project:** Standard Django project layout
|
- **Django project:** Standard Django project layout
|
||||||
@@ -37,21 +48,97 @@
|
|||||||
ruff check . && mypy . && pytest tests/
|
ruff check . && mypy . && pytest tests/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests remain REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based and REQUIRED only for bug fixes, security/auth/permission logic, and critical business/data-mutation logic.
|
||||||
|
4. Reference `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update the PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and escalate only for high-impact uncertainty.
|
||||||
|
4. Reference `~/.config/mosaic/guides/PRD.md`.
|
||||||
|
|
||||||
|
## Task Tracking Contract
|
||||||
|
|
||||||
|
1. For non-trivial implementation work, `docs/TASKS.md` MUST exist before coding.
|
||||||
|
2. If external git provider is available (Gitea/GitHub/GitLab), create/update issue(s) before coding and map them in `docs/TASKS.md`.
|
||||||
|
3. If no external provider is available, use internal refs in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
4. Keep `docs/TASKS.md` status in sync with actual progress until completion.
|
||||||
|
5. For issue/PR/milestone actions, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first (no raw `gh`/`tea`/`glab` as first choice).
|
||||||
|
6. If wrapper-driven merge/CI/issue-closure fails, report blocker with the exact failed wrapper command and stop (do not claim completion).
|
||||||
|
|
||||||
|
## Documentation Contract
|
||||||
|
|
||||||
|
Documentation is a hard delivery gate.
|
||||||
|
If code/API/auth/infra changes, required documentation updates MUST be completed before task closure.
|
||||||
|
Keep `docs/` root clean and store reports/artifacts in scoped folders (`docs/reports/`, `docs/tasks/`, `docs/releases/`, `docs/scratchpads/`).
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
- `~/.config/mosaic/guides/DOCUMENTATION.md`
|
||||||
|
- `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md`
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Shift to conservative strategy when budget pressure rises (smaller scope, fewer parallel actions, reduced re-reading).
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
|
## Merge Strategy (Hard Rule)
|
||||||
|
|
||||||
|
1. Create short-lived branches from `main`.
|
||||||
|
2. Open PRs to `main` for delivery changes.
|
||||||
|
3. Do not push directly to `main`.
|
||||||
|
4. Merge PRs to `main` with squash strategy only.
|
||||||
|
5. Do not mark implementation complete until PR is merged.
|
||||||
|
6. Do not mark implementation complete until CI/pipeline status is terminal green.
|
||||||
|
7. Close linked issues/tasks only after merge + green CI.
|
||||||
|
8. Before push or merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
|
||||||
|
|
||||||
|
## Container Release Strategy (When Applicable)
|
||||||
|
|
||||||
|
1. Use immutable image tags: `sha-<shortsha>` and `v{base-version}-rc.{build}`.
|
||||||
|
2. Use mutable environment tags only as pointers (`testing`, optional `staging`, `prod`).
|
||||||
|
3. Deploy/promote by immutable digest; do not deploy by mutable tag alone.
|
||||||
|
4. Do not use `latest` or `dev` as deployment references.
|
||||||
|
5. Use blue-green by default; use canary only with automated metrics and rollback gates.
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns end-to-end delivery: plan, code, test, review, remediate, commit, push, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Code review is agent-executed and REQUIRED for any source-code change.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Orchestrator Integration
|
## Orchestrator Integration
|
||||||
|
|
||||||
### Task Prefix
|
### Task Prefix
|
||||||
Use `${TASK_PREFIX}` for orchestrated tasks (e.g., `${TASK_PREFIX}-SEC-001`).
|
Use `${TASK_PREFIX}` for orchestrated tasks (e.g., `${TASK_PREFIX}-SEC-001`).
|
||||||
|
|
||||||
### Worker Checklist
|
### Worker Checklist
|
||||||
1. Read the finding details from the report
|
1. Read `docs/PRD.md` or `docs/PRD.json`
|
||||||
2. Implement the fix following existing patterns
|
2. Read the finding details from the report
|
||||||
3. Run quality gates (ALL must pass)
|
3. Implement the fix following existing patterns
|
||||||
4. Commit: `git commit -m "fix({finding_id}): brief description"`
|
4. Run quality gates (ALL must pass)
|
||||||
5. Push: `git push origin {branch}`
|
5. Complete required documentation updates (if applicable)
|
||||||
6. Report result as JSON
|
6. Commit: `git commit -m "fix({finding_id}): brief description"`
|
||||||
|
7. Push: `git push origin {branch}`
|
||||||
|
8. Report result as JSON
|
||||||
|
|
||||||
### Post-Coding Review
|
### Post-Coding Review
|
||||||
After implementing changes, the orchestrator will run:
|
After implementing changes, code review is REQUIRED for any source-code modification.
|
||||||
|
For orchestrated tasks, the orchestrator will run:
|
||||||
1. **Codex code review** — `~/.config/mosaic/rails/codex/codex-code-review.sh --uncommitted`
|
1. **Codex code review** — `~/.config/mosaic/rails/codex/codex-code-review.sh --uncommitted`
|
||||||
2. **Codex security review** — `~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted`
|
2. **Codex security review** — `~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted`
|
||||||
3. If blockers/critical findings: remediation task created
|
3. If blockers/critical findings: remediation task created
|
||||||
|
|||||||
85
templates/agent/projects/django/CLAUDE.md.template
Normal file → Executable file
85
templates/agent/projects/django/CLAUDE.md.template
Normal file → Executable file
@@ -6,11 +6,13 @@
|
|||||||
|
|
||||||
| When working on... | Load this guide |
|
| When working on... | Load this guide |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Bootstrapping this project | `~/.config/mosaic/guides/bootstrap.md` |
|
| Bootstrapping this project | `~/.config/mosaic/guides/BOOTSTRAP.md` |
|
||||||
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/orchestrator.md` |
|
| PRD creation and requirements definition | `~/.config/mosaic/guides/PRD.md` |
|
||||||
| Backend/API development | `~/.config/mosaic/guides/backend.md` |
|
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/ORCHESTRATOR.md` |
|
||||||
| Code review | `~/.config/mosaic/guides/code-review.md` |
|
| Backend/API development | `~/.config/mosaic/guides/BACKEND.md` |
|
||||||
| QA/Testing | `~/.config/mosaic/guides/qa-testing.md` |
|
| Code review | `~/.config/mosaic/guides/CODE-REVIEW.md` |
|
||||||
|
| Documentation updates and standards | `~/.config/mosaic/guides/DOCUMENTATION.md` |
|
||||||
|
| QA/Testing | `~/.config/mosaic/guides/QA-TESTING.md` |
|
||||||
|
|
||||||
## Technology Stack
|
## Technology Stack
|
||||||
|
|
||||||
@@ -39,6 +41,7 @@ ${PROJECT_DIR}/
|
|||||||
│ └── apps/ # Django applications
|
│ └── apps/ # Django applications
|
||||||
├── tests/ # Test files
|
├── tests/ # Test files
|
||||||
├── docs/
|
├── docs/
|
||||||
|
│ ├── PRD.md # Requirements source (or PRD.json)
|
||||||
│ ├── scratchpads/ # Per-issue working documents
|
│ ├── scratchpads/ # Per-issue working documents
|
||||||
│ └── templates/ # Project templates
|
│ └── templates/ # Project templates
|
||||||
├── pyproject.toml # Python project configuration
|
├── pyproject.toml # Python project configuration
|
||||||
@@ -49,10 +52,10 @@ ${PROJECT_DIR}/
|
|||||||
## Development Workflow
|
## Development Workflow
|
||||||
|
|
||||||
### Branch Strategy
|
### Branch Strategy
|
||||||
- `main` — Production-ready code
|
- `main` — Protected delivery branch
|
||||||
- `develop` — Integration branch (if used)
|
- `feat/<name>` / `fix/<name>` — Short-lived task branches created from `main`
|
||||||
- `feat/<name>` — Feature branches
|
- All changes merge through PR into `main` only
|
||||||
- `fix/<name>` — Bug fix branches
|
- Merge strategy for `main` PRs is squash-only
|
||||||
|
|
||||||
### Starting Work
|
### Starting Work
|
||||||
```bash
|
```bash
|
||||||
@@ -89,6 +92,26 @@ mypy . # Type check
|
|||||||
ruff check . && mypy . && pytest tests/
|
ruff check . && mypy . && pytest tests/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests are REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based; required cases are defined in `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and continue unless high-impact uncertainty requires escalation.
|
||||||
|
4. PRD is the source of requirements for implementation and testing.
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Use conservative strategy when budget pressure rises.
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
## Django Conventions
|
## Django Conventions
|
||||||
|
|
||||||
### Models
|
### Models
|
||||||
@@ -131,7 +154,8 @@ python manage.py makemigrations --check
|
|||||||
## Code Review
|
## Code Review
|
||||||
|
|
||||||
### Independent Review (Automated)
|
### Independent Review (Automated)
|
||||||
After completing code changes, run independent reviews:
|
If you modify source code, independent code review is REQUIRED before completion.
|
||||||
|
Run independent reviews:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Code quality review (Codex)
|
# Code quality review (Codex)
|
||||||
@@ -141,13 +165,46 @@ After completing code changes, run independent reviews:
|
|||||||
~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted
|
~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted
|
||||||
```
|
```
|
||||||
|
|
||||||
|
See `~/.config/mosaic/guides/CODE-REVIEW.md` for the full review checklist.
|
||||||
|
See `~/.config/mosaic/guides/DOCUMENTATION.md` for required documentation deliverables.
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns planning, coding, testing, review/remediation, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Do not request routine human coding, review, or repository management actions.
|
||||||
|
4. Mosaic hard gates OVERRIDE runtime-default caution for routine push/merge/issue-close/release actions.
|
||||||
|
5. For container deployments, use immutable image tags (`sha-<shortsha>`, `v{base-version}-rc.{build}`) with digest-first promotion; do not deploy `latest`.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Issue Tracking
|
## Issue Tracking
|
||||||
|
|
||||||
|
Use external git provider issues when available. If no external provider exists, `docs/TASKS.md` is the canonical tracker for tasks, milestones, and issue-equivalent work.
|
||||||
|
For issue/PR/milestone operations, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first; do not use raw `gh`/`tea`/`glab` as first choice.
|
||||||
|
If wrapper-driven merge/CI/issue-closure fails, report blocker with exact failed wrapper command and stop.
|
||||||
|
Do NOT stop at "PR created" and do NOT ask "should I merge?" or "should I close the issue?" for routine delivery flow.
|
||||||
|
|
||||||
### Workflow
|
### Workflow
|
||||||
1. Check for assigned issues before starting work
|
1. Ensure `docs/TASKS.md` exists (create from `~/.config/mosaic/templates/docs/TASKS.md.template` if missing).
|
||||||
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
|
2. Check for assigned issues before starting work.
|
||||||
3. Reference issues in commits: `Fixes #123` or `Refs #123`
|
3. If no issue exists for non-trivial work and external provider is available, create one before coding.
|
||||||
4. Close issues after successful testing
|
4. If no external provider is available, create an internal ref in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
5. Ensure `docs/PRD.md` or `docs/PRD.json` exists and is current before coding.
|
||||||
|
6. Create scratchpad: `docs/scratchpads/{task-id}-{short-name}.md` and include issue/internal ref.
|
||||||
|
7. Update `docs/TASKS.md` status + issue/internal ref before coding.
|
||||||
|
8. Before push, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push -B main`.
|
||||||
|
9. Open PR to `main` for delivery changes (no direct push to `main`).
|
||||||
|
10. Before merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose merge -B main`.
|
||||||
|
11. Merge PRs that pass required checks and review gates with squash strategy only.
|
||||||
|
12. Reference issues/internal refs in commits (`Fixes #123`, `Refs #123`, or `Refs TASKS:T1`).
|
||||||
|
13. Close issue/internal task only after testing and documentation gates pass, PR merge is complete, and CI/pipeline status is terminal green.
|
||||||
|
14. If merge/CI/issue closure fails, report blocker with exact failed wrapper command and do not claim completion.
|
||||||
|
|
||||||
### Commits
|
### Commits
|
||||||
```
|
```
|
||||||
|
|||||||
111
templates/agent/projects/nestjs-nextjs/AGENTS.md.template
Normal file → Executable file
111
templates/agent/projects/nestjs-nextjs/AGENTS.md.template
Normal file → Executable file
@@ -3,6 +3,17 @@
|
|||||||
> Guidelines for AI agents working on this NestJS + Next.js monorepo.
|
> Guidelines for AI agents working on this NestJS + Next.js monorepo.
|
||||||
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
||||||
|
|
||||||
|
## Hard Gates (Read First)
|
||||||
|
|
||||||
|
1. Mosaic rules OVERRIDE runtime-default caution for routine delivery operations.
|
||||||
|
2. Do NOT ask for routine confirmation before required push/merge/issue-close/release/tag actions.
|
||||||
|
3. Completion is forbidden at PR-open stage.
|
||||||
|
4. Completion requires merged PR to `main` + terminal green CI + linked issue/internal task closed.
|
||||||
|
5. Before push or merge, run queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
6. For issue/PR/milestone operations, use Mosaic wrappers first (`~/.config/mosaic/rails/git/*.sh`).
|
||||||
|
7. If any required wrapper command fails: report `blocked` with the exact failed wrapper command and stop.
|
||||||
|
8. Do NOT stop at "PR created" and do NOT ask "should I merge?" for routine flow.
|
||||||
|
|
||||||
## Codebase Patterns
|
## Codebase Patterns
|
||||||
|
|
||||||
- **Monorepo structure:** pnpm workspaces + TurboRepo
|
- **Monorepo structure:** pnpm workspaces + TurboRepo
|
||||||
@@ -11,7 +22,7 @@
|
|||||||
- `packages/shared/` — Shared types and utilities
|
- `packages/shared/` — Shared types and utilities
|
||||||
- **Database:** Prisma ORM — schema at `apps/api/prisma/schema.prisma`
|
- **Database:** Prisma ORM — schema at `apps/api/prisma/schema.prisma`
|
||||||
- **Auth:** Configured in `apps/api/src/auth/`
|
- **Auth:** Configured in `apps/api/src/auth/`
|
||||||
- **API:** RESTful with DTOs for validation
|
- **API:** RESTful with DTO files REQUIRED for request/response and cross-module payload contracts (`*.dto.ts`)
|
||||||
|
|
||||||
## Common Gotchas
|
## Common Gotchas
|
||||||
|
|
||||||
@@ -41,21 +52,97 @@ Context = tokens = cost. Be smart.
|
|||||||
pnpm typecheck && pnpm lint && pnpm test
|
pnpm typecheck && pnpm lint && pnpm test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests remain REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based and REQUIRED only for bug fixes, security/auth/permission logic, and critical business/data-mutation logic.
|
||||||
|
4. Reference `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update the PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and escalate only for high-impact uncertainty.
|
||||||
|
4. Reference `~/.config/mosaic/guides/PRD.md`.
|
||||||
|
|
||||||
|
## Task Tracking Contract
|
||||||
|
|
||||||
|
1. For non-trivial implementation work, `docs/TASKS.md` MUST exist before coding.
|
||||||
|
2. If external git provider is available (Gitea/GitHub/GitLab), create/update issue(s) before coding and map them in `docs/TASKS.md`.
|
||||||
|
3. If no external provider is available, use internal refs in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
4. Keep `docs/TASKS.md` status in sync with actual progress until completion.
|
||||||
|
5. For issue/PR/milestone actions, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first (no raw `gh`/`tea`/`glab` as first choice).
|
||||||
|
6. If wrapper-driven merge/CI/issue-closure fails, report blocker with the exact failed wrapper command and stop (do not claim completion).
|
||||||
|
|
||||||
|
## Documentation Contract
|
||||||
|
|
||||||
|
Documentation is a hard delivery gate.
|
||||||
|
If code/API/auth/infra changes, required documentation updates MUST be completed before task closure.
|
||||||
|
Keep `docs/` root clean and store reports/artifacts in scoped folders (`docs/reports/`, `docs/tasks/`, `docs/releases/`, `docs/scratchpads/`).
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
- `~/.config/mosaic/guides/DOCUMENTATION.md`
|
||||||
|
- `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md`
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Shift to conservative strategy when budget pressure rises (smaller scope, fewer parallel actions, reduced re-reading).
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
|
## Merge Strategy (Hard Rule)
|
||||||
|
|
||||||
|
1. Create short-lived branches from `main`.
|
||||||
|
2. Open PRs to `main` for delivery changes.
|
||||||
|
3. Do not push directly to `main`.
|
||||||
|
4. Merge PRs to `main` with squash strategy only.
|
||||||
|
5. Do not mark implementation complete until PR is merged.
|
||||||
|
6. Do not mark implementation complete until CI/pipeline status is terminal green.
|
||||||
|
7. Close linked issues/tasks only after merge + green CI.
|
||||||
|
8. Before push or merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
|
||||||
|
|
||||||
|
## Container Release Strategy (When Applicable)
|
||||||
|
|
||||||
|
1. Use immutable image tags: `sha-<shortsha>` and `v{base-version}-rc.{build}`.
|
||||||
|
2. Use mutable environment tags only as pointers (`testing`, optional `staging`, `prod`).
|
||||||
|
3. Deploy/promote by immutable digest; do not deploy by mutable tag alone.
|
||||||
|
4. Do not use `latest` or `dev` as deployment references.
|
||||||
|
5. Use blue-green by default; use canary only with automated metrics and rollback gates.
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns end-to-end delivery: plan, code, test, review, remediate, commit, push, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Code review is agent-executed and REQUIRED for any source-code change.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Orchestrator Integration
|
## Orchestrator Integration
|
||||||
|
|
||||||
### Task Prefix
|
### Task Prefix
|
||||||
Use `${TASK_PREFIX}` for orchestrated tasks (e.g., `${TASK_PREFIX}-SEC-001`).
|
Use `${TASK_PREFIX}` for orchestrated tasks (e.g., `${TASK_PREFIX}-SEC-001`).
|
||||||
|
|
||||||
### Worker Checklist
|
### Worker Checklist
|
||||||
1. Read the finding details from the report
|
1. Read `docs/PRD.md` or `docs/PRD.json`
|
||||||
2. Implement the fix following existing patterns
|
2. Read the finding details from the report
|
||||||
3. Run quality gates (ALL must pass)
|
3. Implement the fix following existing patterns
|
||||||
4. Commit: `git commit -m "fix({finding_id}): brief description"`
|
4. Run quality gates (ALL must pass)
|
||||||
5. Push: `git push origin {branch}`
|
5. Complete required documentation updates (if applicable)
|
||||||
6. Report result as JSON
|
6. Commit: `git commit -m "fix({finding_id}): brief description"`
|
||||||
|
7. Push: `git push origin {branch}`
|
||||||
|
8. Report result as JSON
|
||||||
|
|
||||||
### Post-Coding Review
|
### Post-Coding Review
|
||||||
After implementing changes, the orchestrator will run:
|
After implementing changes, code review is REQUIRED for any source-code modification.
|
||||||
|
For orchestrated tasks, the orchestrator will run:
|
||||||
1. **Codex code review** — `~/.config/mosaic/rails/codex/codex-code-review.sh --uncommitted`
|
1. **Codex code review** — `~/.config/mosaic/rails/codex/codex-code-review.sh --uncommitted`
|
||||||
2. **Codex security review** — `~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted`
|
2. **Codex security review** — `~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted`
|
||||||
3. If blockers/critical findings: remediation task created
|
3. If blockers/critical findings: remediation task created
|
||||||
@@ -65,15 +152,15 @@ After implementing changes, the orchestrator will run:
|
|||||||
|
|
||||||
```
|
```
|
||||||
1. Branch → git checkout -b feature/XX-description
|
1. Branch → git checkout -b feature/XX-description
|
||||||
2. Code → TDD: write test (RED), implement (GREEN), refactor
|
2. Code → Implement with required tests; use TDD where required by policy
|
||||||
3. Test → pnpm test (must pass)
|
3. Test → pnpm test (must pass)
|
||||||
4. Push → git push origin feature/XX-description
|
4. Push → git push origin feature/XX-description
|
||||||
5. PR → Create PR to develop (not main)
|
5. PR → Create PR to main
|
||||||
6. Review → Wait for approval or self-merge if authorized
|
6. Review → Wait for approval or self-merge if authorized using squash only
|
||||||
7. Close → Close related issues
|
7. Close → Close related issues
|
||||||
```
|
```
|
||||||
|
|
||||||
**Never merge directly to develop without a PR.**
|
**Never push directly to main. Always use a PR to main.**
|
||||||
|
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
||||||
|
|||||||
96
templates/agent/projects/nestjs-nextjs/CLAUDE.md.template
Normal file → Executable file
96
templates/agent/projects/nestjs-nextjs/CLAUDE.md.template
Normal file → Executable file
@@ -6,14 +6,16 @@
|
|||||||
|
|
||||||
| When working on... | Load this guide |
|
| When working on... | Load this guide |
|
||||||
|---|---|
|
|---|---|
|
||||||
| Bootstrapping this project | `~/.config/mosaic/guides/bootstrap.md` |
|
| Bootstrapping this project | `~/.config/mosaic/guides/BOOTSTRAP.md` |
|
||||||
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/orchestrator.md` |
|
| PRD creation and requirements definition | `~/.config/mosaic/guides/PRD.md` |
|
||||||
| Frontend development | `~/.config/mosaic/guides/frontend.md` |
|
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/ORCHESTRATOR.md` |
|
||||||
| Backend/API development | `~/.config/mosaic/guides/backend.md` |
|
| Frontend development | `~/.config/mosaic/guides/FRONTEND.md` |
|
||||||
| Code review | `~/.config/mosaic/guides/code-review.md` |
|
| Backend/API development | `~/.config/mosaic/guides/BACKEND.md` |
|
||||||
| TypeScript strict typing | `~/.config/mosaic/guides/typescript.md` |
|
| Code review | `~/.config/mosaic/guides/CODE-REVIEW.md` |
|
||||||
| Authentication/Authorization | `~/.config/mosaic/guides/authentication.md` |
|
| Documentation updates and standards | `~/.config/mosaic/guides/DOCUMENTATION.md` |
|
||||||
| QA/Testing | `~/.config/mosaic/guides/qa-testing.md` |
|
| TypeScript strict typing | `~/.config/mosaic/guides/TYPESCRIPT.md` |
|
||||||
|
| Authentication/Authorization | `~/.config/mosaic/guides/AUTHENTICATION.md` |
|
||||||
|
| QA/Testing | `~/.config/mosaic/guides/QA-TESTING.md` |
|
||||||
|
|
||||||
## Technology Stack
|
## Technology Stack
|
||||||
|
|
||||||
@@ -47,6 +49,7 @@ ${PROJECT_DIR}/
|
|||||||
│ ├── ui/ # Shared UI components
|
│ ├── ui/ # Shared UI components
|
||||||
│ └── config/ # Shared configuration
|
│ └── config/ # Shared configuration
|
||||||
├── docs/
|
├── docs/
|
||||||
|
│ ├── PRD.md # Requirements source (or PRD.json)
|
||||||
│ ├── scratchpads/ # Per-issue working documents
|
│ ├── scratchpads/ # Per-issue working documents
|
||||||
│ └── templates/ # Project templates
|
│ └── templates/ # Project templates
|
||||||
├── tests/ # Integration/E2E tests
|
├── tests/ # Integration/E2E tests
|
||||||
@@ -60,15 +63,15 @@ ${PROJECT_DIR}/
|
|||||||
## Development Workflow
|
## Development Workflow
|
||||||
|
|
||||||
### Branch Strategy
|
### Branch Strategy
|
||||||
- `main` — Stable releases only
|
- `main` — Protected delivery branch
|
||||||
- `develop` — Active development (default working branch)
|
- `feature/*` / `fix/*` — Short-lived task branches created from `main`
|
||||||
- `feature/*` — Feature branches from develop
|
- All changes merge through PR into `main` only
|
||||||
- `fix/*` — Bug fix branches
|
- Merge strategy for `main` PRs is squash-only
|
||||||
|
|
||||||
### Starting Work
|
### Starting Work
|
||||||
```bash
|
```bash
|
||||||
git checkout develop
|
git checkout main
|
||||||
git pull --rebase
|
git pull --rebase origin main
|
||||||
pnpm install
|
pnpm install
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -102,10 +105,31 @@ pnpm format # Prettier formatting
|
|||||||
pnpm typecheck && pnpm lint && pnpm test
|
pnpm typecheck && pnpm lint && pnpm test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests are REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based; required cases are defined in `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and continue unless high-impact uncertainty requires escalation.
|
||||||
|
4. PRD is the source of requirements for implementation and testing.
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Use conservative strategy when budget pressure rises.
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
## API Conventions
|
## API Conventions
|
||||||
|
|
||||||
### NestJS Patterns
|
### NestJS Patterns
|
||||||
- Controllers handle HTTP, Services handle business logic
|
- Controllers handle HTTP, Services handle business logic
|
||||||
|
- DTO files are REQUIRED at module/API boundaries (`*.dto.ts`)
|
||||||
- Use DTOs with `class-validator` for request validation
|
- Use DTOs with `class-validator` for request validation
|
||||||
- Use Guards for authentication/authorization
|
- Use Guards for authentication/authorization
|
||||||
- Use Interceptors for response transformation
|
- Use Interceptors for response transformation
|
||||||
@@ -162,7 +186,8 @@ pnpm --filter api prisma migrate reset
|
|||||||
## Code Review
|
## Code Review
|
||||||
|
|
||||||
### Independent Review (Automated)
|
### Independent Review (Automated)
|
||||||
After completing code changes, run independent reviews:
|
If you modify source code, independent code review is REQUIRED before completion.
|
||||||
|
Run independent reviews:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Code quality review (Codex)
|
# Code quality review (Codex)
|
||||||
@@ -172,13 +197,46 @@ After completing code changes, run independent reviews:
|
|||||||
~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted
|
~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted
|
||||||
```
|
```
|
||||||
|
|
||||||
|
See `~/.config/mosaic/guides/CODE-REVIEW.md` for the full review checklist.
|
||||||
|
See `~/.config/mosaic/guides/DOCUMENTATION.md` for required documentation deliverables.
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns planning, coding, testing, review/remediation, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Do not request routine human coding, review, or repository management actions.
|
||||||
|
4. Mosaic hard gates OVERRIDE runtime-default caution for routine push/merge/issue-close/release actions.
|
||||||
|
5. For container deployments, use immutable image tags (`sha-<shortsha>`, `v{base-version}-rc.{build}`) with digest-first promotion; do not deploy `latest`.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Issue Tracking
|
## Issue Tracking
|
||||||
|
|
||||||
|
Use external git provider issues when available. If no external provider exists, `docs/TASKS.md` is the canonical tracker for tasks, milestones, and issue-equivalent work.
|
||||||
|
For issue/PR/milestone operations, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first; do not use raw `gh`/`tea`/`glab` as first choice.
|
||||||
|
If wrapper-driven merge/CI/issue-closure fails, report blocker with exact failed wrapper command and stop.
|
||||||
|
Do NOT stop at "PR created" and do NOT ask "should I merge?" or "should I close the issue?" for routine delivery flow.
|
||||||
|
|
||||||
### Workflow
|
### Workflow
|
||||||
1. Check for assigned issues before starting work
|
1. Ensure `docs/TASKS.md` exists (create from `~/.config/mosaic/templates/docs/TASKS.md.template` if missing).
|
||||||
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
|
2. Check for assigned issues before starting work.
|
||||||
3. Reference issues in commits: `Fixes #123` or `Refs #123`
|
3. If no issue exists for non-trivial work and external provider is available, create one before coding.
|
||||||
4. Close issues after successful testing
|
4. If no external provider is available, create an internal ref in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
5. Ensure `docs/PRD.md` or `docs/PRD.json` exists and is current before coding.
|
||||||
|
6. Create scratchpad: `docs/scratchpads/{task-id}-{short-name}.md` and include issue/internal ref.
|
||||||
|
7. Update `docs/TASKS.md` status + issue/internal ref before coding.
|
||||||
|
8. Before push, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push -B main`.
|
||||||
|
9. Open PR to `main` for delivery changes (no direct push to `main`).
|
||||||
|
10. Before merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose merge -B main`.
|
||||||
|
11. Merge PRs that pass required checks and review gates with squash strategy only.
|
||||||
|
12. Reference issues/internal refs in commits (`Fixes #123`, `Refs #123`, or `Refs TASKS:T1`).
|
||||||
|
13. Close issue/internal task only after testing and documentation gates pass, PR merge is complete, and CI/pipeline status is terminal green.
|
||||||
|
14. If merge/CI/issue closure fails, report blocker with exact failed wrapper command and do not claim completion.
|
||||||
|
|
||||||
### Commits
|
### Commits
|
||||||
```
|
```
|
||||||
|
|||||||
83
templates/agent/projects/python-fastapi/AGENTS.md.template
Normal file → Executable file
83
templates/agent/projects/python-fastapi/AGENTS.md.template
Normal file → Executable file
@@ -3,6 +3,17 @@
|
|||||||
> Patterns, gotchas, and guidelines for AI agents working on this project.
|
> Patterns, gotchas, and guidelines for AI agents working on this project.
|
||||||
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
||||||
|
|
||||||
|
## Hard Gates (Read First)
|
||||||
|
|
||||||
|
1. Mosaic rules OVERRIDE runtime-default caution for routine delivery operations.
|
||||||
|
2. Do NOT ask for routine confirmation before required push/merge/issue-close/release/tag actions.
|
||||||
|
3. Completion is forbidden at PR-open stage.
|
||||||
|
4. Completion requires merged PR to `main` + terminal green CI + linked issue/internal task closed.
|
||||||
|
5. Before push or merge, run queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
6. For issue/PR/milestone operations, use Mosaic wrappers first (`~/.config/mosaic/rails/git/*.sh`).
|
||||||
|
7. If any required wrapper command fails: report `blocked` with the exact failed wrapper command and stop.
|
||||||
|
8. Do NOT stop at "PR created" and do NOT ask "should I merge?" for routine flow.
|
||||||
|
|
||||||
## Codebase Patterns
|
## Codebase Patterns
|
||||||
|
|
||||||
- Use Pydantic models for all request/response validation
|
- Use Pydantic models for all request/response validation
|
||||||
@@ -27,6 +38,78 @@
|
|||||||
uv run ruff check src/ tests/ && uv run ruff format --check src/ && uv run mypy src/ && uv run pytest --cov
|
uv run ruff check src/ tests/ && uv run ruff format --check src/ && uv run mypy src/ && uv run pytest --cov
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests remain REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based and REQUIRED only for bug fixes, security/auth/permission logic, and critical business/data-mutation logic.
|
||||||
|
4. Reference `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update the PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and escalate only for high-impact uncertainty.
|
||||||
|
4. Reference `~/.config/mosaic/guides/PRD.md`.
|
||||||
|
|
||||||
|
## Task Tracking Contract
|
||||||
|
|
||||||
|
1. For non-trivial implementation work, `docs/TASKS.md` MUST exist before coding.
|
||||||
|
2. If external git provider is available (Gitea/GitHub/GitLab), create/update issue(s) before coding and map them in `docs/TASKS.md`.
|
||||||
|
3. If no external provider is available, use internal refs in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
4. Keep `docs/TASKS.md` status in sync with actual progress until completion.
|
||||||
|
5. For issue/PR/milestone actions, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first (no raw `gh`/`tea`/`glab` as first choice).
|
||||||
|
6. If wrapper-driven merge/CI/issue-closure fails, report blocker with the exact failed wrapper command and stop (do not claim completion).
|
||||||
|
|
||||||
|
## Documentation Contract
|
||||||
|
|
||||||
|
Documentation is a hard delivery gate.
|
||||||
|
If code/API/auth/infra changes, required documentation updates MUST be completed before task closure.
|
||||||
|
Keep `docs/` root clean and store reports/artifacts in scoped folders (`docs/reports/`, `docs/tasks/`, `docs/releases/`, `docs/scratchpads/`).
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
- `~/.config/mosaic/guides/DOCUMENTATION.md`
|
||||||
|
- `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md`
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Shift to conservative strategy when budget pressure rises (smaller scope, fewer parallel actions, reduced re-reading).
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
|
## Merge Strategy (Hard Rule)
|
||||||
|
|
||||||
|
1. Create short-lived branches from `main`.
|
||||||
|
2. Open PRs to `main` for delivery changes.
|
||||||
|
3. Do not push directly to `main`.
|
||||||
|
4. Merge PRs to `main` with squash strategy only.
|
||||||
|
5. Do not mark implementation complete until PR is merged.
|
||||||
|
6. Do not mark implementation complete until CI/pipeline status is terminal green.
|
||||||
|
7. Close linked issues/tasks only after merge + green CI.
|
||||||
|
8. Before push or merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
|
||||||
|
## Container Release Strategy (When Applicable)
|
||||||
|
|
||||||
|
1. Use immutable image tags: `sha-<shortsha>` and `v{base-version}-rc.{build}`.
|
||||||
|
2. Use mutable environment tags only as pointers (`testing`, optional `staging`, `prod`).
|
||||||
|
3. Deploy/promote by immutable digest; do not deploy by mutable tag alone.
|
||||||
|
4. Do not use `latest` or `dev` as deployment references.
|
||||||
|
5. Use blue-green by default; use canary only with automated metrics and rollback gates.
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns end-to-end delivery: plan, code, test, review, remediate, commit, push, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Code review is agent-executed and REQUIRED for any source-code change.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
||||||
| File | Purpose |
|
| File | Purpose |
|
||||||
|
|||||||
92
templates/agent/projects/python-fastapi/CLAUDE.md.template
Normal file → Executable file
92
templates/agent/projects/python-fastapi/CLAUDE.md.template
Normal file → Executable file
@@ -9,15 +9,17 @@
|
|||||||
|
|
||||||
| Task Type | Guide |
|
| Task Type | Guide |
|
||||||
|-----------|-------|
|
|-----------|-------|
|
||||||
| Bootstrapping this project | `~/.config/mosaic/guides/bootstrap.md` |
|
| End-to-end implementation and validation | `~/.config/mosaic/guides/E2E-DELIVERY.md` |
|
||||||
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/orchestrator.md` |
|
| PRD creation and requirements definition | `~/.config/mosaic/guides/PRD.md` |
|
||||||
| Ralph autonomous development | `~/.config/mosaic/guides/ralph-autonomous.md` |
|
| Bootstrapping this project | `~/.config/mosaic/guides/BOOTSTRAP.md` |
|
||||||
| Backend/API development | `~/.config/mosaic/guides/backend.md` |
|
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/ORCHESTRATOR.md` |
|
||||||
| Authentication/Authorization | `~/.config/mosaic/guides/authentication.md` |
|
| Backend/API development | `~/.config/mosaic/guides/BACKEND.md` |
|
||||||
| Code review | `~/.config/mosaic/guides/code-review.md` |
|
| Authentication/Authorization | `~/.config/mosaic/guides/AUTHENTICATION.md` |
|
||||||
| QA/Testing | `~/.config/mosaic/guides/qa-testing.md` |
|
| Code review | `~/.config/mosaic/guides/CODE-REVIEW.md` |
|
||||||
| Infrastructure/DevOps | `~/.config/mosaic/guides/infrastructure.md` |
|
| Documentation updates and standards | `~/.config/mosaic/guides/DOCUMENTATION.md` |
|
||||||
| Secrets management (Vault) | `~/.config/mosaic/guides/vault-secrets.md` |
|
| QA/Testing | `~/.config/mosaic/guides/QA-TESTING.md` |
|
||||||
|
| Infrastructure/DevOps | `~/.config/mosaic/guides/INFRASTRUCTURE.md` |
|
||||||
|
| Secrets management (Vault) | `~/.config/mosaic/guides/VAULT-SECRETS.md` |
|
||||||
|
|
||||||
## Technology Stack
|
## Technology Stack
|
||||||
|
|
||||||
@@ -43,6 +45,7 @@ ${PROJECT_DIR}/
|
|||||||
│ └── ${PROJECT_SLUG}/ # Main package
|
│ └── ${PROJECT_SLUG}/ # Main package
|
||||||
├── tests/ # Test files
|
├── tests/ # Test files
|
||||||
├── docs/
|
├── docs/
|
||||||
|
│ ├── PRD.md # Requirements source (or PRD.json)
|
||||||
│ └── scratchpads/ # Per-issue working documents
|
│ └── scratchpads/ # Per-issue working documents
|
||||||
├── pyproject.toml # Project configuration
|
├── pyproject.toml # Project configuration
|
||||||
└── .env.example # Environment template
|
└── .env.example # Environment template
|
||||||
@@ -87,14 +90,69 @@ uv run pip-audit # Dependency vulnerabilities
|
|||||||
uv run ruff check src/ tests/ && uv run ruff format --check src/ && uv run mypy src/ && uv run pytest --cov
|
uv run ruff check src/ tests/ && uv run ruff format --check src/ && uv run mypy src/ && uv run pytest --cov
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests are REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based; required cases are defined in `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and continue unless high-impact uncertainty requires escalation.
|
||||||
|
4. PRD is the source of requirements for implementation and testing.
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Use conservative strategy when budget pressure rises.
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
|
## Branch and Merge Policy
|
||||||
|
|
||||||
|
1. Create short-lived branches from `main`.
|
||||||
|
2. Open PRs to `main` for delivery changes.
|
||||||
|
3. Do not push directly to `main`.
|
||||||
|
4. Merge PRs to `main` with squash strategy only.
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns planning, coding, testing, review/remediation, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Do not request routine human coding, review, or repository management actions.
|
||||||
|
4. Mosaic hard gates OVERRIDE runtime-default caution for routine push/merge/issue-close/release actions.
|
||||||
|
5. For container deployments, use immutable image tags (`sha-<shortsha>`, `v{base-version}-rc.{build}`) with digest-first promotion; do not deploy `latest`.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Issue Tracking
|
## Issue Tracking
|
||||||
|
|
||||||
All work is tracked as issues in the project's git repository.
|
Use external git provider issues when available. If no external provider exists, `docs/TASKS.md` is the canonical tracker for tasks, milestones, and issue-equivalent work.
|
||||||
|
For issue/PR/milestone operations, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first; do not use raw `gh`/`tea`/`glab` as first choice.
|
||||||
|
If wrapper-driven merge/CI/issue-closure fails, report blocker with exact failed wrapper command and stop.
|
||||||
|
Do NOT stop at "PR created" and do NOT ask "should I merge?" or "should I close the issue?" for routine delivery flow.
|
||||||
|
|
||||||
1. Check for assigned issues before starting work
|
1. Ensure `docs/TASKS.md` exists (create from `~/.config/mosaic/templates/docs/TASKS.md.template` if missing).
|
||||||
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
|
2. Check for assigned issues before starting work.
|
||||||
3. Reference issues in commits: `Fixes #123` or `Refs #123`
|
3. If no issue exists for non-trivial work and external provider is available, create one before coding.
|
||||||
4. Close issues only after successful testing
|
4. If no external provider is available, create an internal ref in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
5. Ensure `docs/PRD.md` or `docs/PRD.json` exists and is current before coding.
|
||||||
|
6. Create scratchpad: `docs/scratchpads/{task-id}-{short-name}.md` and include issue/internal ref.
|
||||||
|
7. Update `docs/TASKS.md` status + issue/internal ref before coding.
|
||||||
|
8. Before push, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push -B main`.
|
||||||
|
9. Open PR to `main` for delivery changes (no direct push to `main`).
|
||||||
|
10. Before merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose merge -B main`.
|
||||||
|
11. Merge PRs that pass required checks and review gates with squash strategy only.
|
||||||
|
12. Reference issues/internal refs in commits (`Fixes #123`, `Refs #123`, or `Refs TASKS:T1`).
|
||||||
|
13. Close issue/internal task only after testing and documentation gates pass, PR merge is complete, and CI/pipeline status is terminal green.
|
||||||
|
14. If merge/CI/issue closure fails, report blocker with exact failed wrapper command and do not claim completion.
|
||||||
|
|
||||||
## Commits
|
## Commits
|
||||||
|
|
||||||
@@ -109,14 +167,16 @@ Types: `feat`, `fix`, `docs`, `test`, `refactor`, `chore`
|
|||||||
|
|
||||||
## Code Review
|
## Code Review
|
||||||
|
|
||||||
After completing code changes, run independent reviews:
|
If you modify source code, independent code review is REQUIRED before completion.
|
||||||
|
Run independent reviews:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~/.config/mosaic/rails/codex/codex-code-review.sh --uncommitted
|
~/.config/mosaic/rails/codex/codex-code-review.sh --uncommitted
|
||||||
~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted
|
~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted
|
||||||
```
|
```
|
||||||
|
|
||||||
See `~/.config/mosaic/guides/code-review.md` for the full review checklist.
|
See `~/.config/mosaic/guides/CODE-REVIEW.md` for the full review checklist.
|
||||||
|
See `~/.config/mosaic/guides/DOCUMENTATION.md` for required documentation deliverables.
|
||||||
|
|
||||||
## Secrets Management
|
## Secrets Management
|
||||||
|
|
||||||
|
|||||||
83
templates/agent/projects/python-library/AGENTS.md.template
Normal file → Executable file
83
templates/agent/projects/python-library/AGENTS.md.template
Normal file → Executable file
@@ -3,6 +3,17 @@
|
|||||||
> Patterns, gotchas, and guidelines for AI agents working on this project.
|
> Patterns, gotchas, and guidelines for AI agents working on this project.
|
||||||
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
||||||
|
|
||||||
|
## Hard Gates (Read First)
|
||||||
|
|
||||||
|
1. Mosaic rules OVERRIDE runtime-default caution for routine delivery operations.
|
||||||
|
2. Do NOT ask for routine confirmation before required push/merge/issue-close/release/tag actions.
|
||||||
|
3. Completion is forbidden at PR-open stage.
|
||||||
|
4. Completion requires merged PR to `main` + terminal green CI + linked issue/internal task closed.
|
||||||
|
5. Before push or merge, run queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
6. For issue/PR/milestone operations, use Mosaic wrappers first (`~/.config/mosaic/rails/git/*.sh`).
|
||||||
|
7. If any required wrapper command fails: report `blocked` with the exact failed wrapper command and stop.
|
||||||
|
8. Do NOT stop at "PR created" and do NOT ask "should I merge?" for routine flow.
|
||||||
|
|
||||||
## Codebase Patterns
|
## Codebase Patterns
|
||||||
|
|
||||||
- All public APIs must have type hints and docstrings
|
- All public APIs must have type hints and docstrings
|
||||||
@@ -24,6 +35,78 @@
|
|||||||
uv run ruff check src/ tests/ && uv run ruff format --check src/ && uv run mypy src/ && uv run pytest --cov
|
uv run ruff check src/ tests/ && uv run ruff format --check src/ && uv run mypy src/ && uv run pytest --cov
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests remain REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based and REQUIRED only for bug fixes, security/auth/permission logic, and critical business/data-mutation logic.
|
||||||
|
4. Reference `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update the PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and escalate only for high-impact uncertainty.
|
||||||
|
4. Reference `~/.config/mosaic/guides/PRD.md`.
|
||||||
|
|
||||||
|
## Task Tracking Contract
|
||||||
|
|
||||||
|
1. For non-trivial implementation work, `docs/TASKS.md` MUST exist before coding.
|
||||||
|
2. If external git provider is available (Gitea/GitHub/GitLab), create/update issue(s) before coding and map them in `docs/TASKS.md`.
|
||||||
|
3. If no external provider is available, use internal refs in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
4. Keep `docs/TASKS.md` status in sync with actual progress until completion.
|
||||||
|
5. For issue/PR/milestone actions, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first (no raw `gh`/`tea`/`glab` as first choice).
|
||||||
|
6. If wrapper-driven merge/CI/issue-closure fails, report blocker with the exact failed wrapper command and stop (do not claim completion).
|
||||||
|
|
||||||
|
## Documentation Contract
|
||||||
|
|
||||||
|
Documentation is a hard delivery gate.
|
||||||
|
If code/API/auth/infra changes, required documentation updates MUST be completed before task closure.
|
||||||
|
Keep `docs/` root clean and store reports/artifacts in scoped folders (`docs/reports/`, `docs/tasks/`, `docs/releases/`, `docs/scratchpads/`).
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
- `~/.config/mosaic/guides/DOCUMENTATION.md`
|
||||||
|
- `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md`
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Shift to conservative strategy when budget pressure rises (smaller scope, fewer parallel actions, reduced re-reading).
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
|
## Merge Strategy (Hard Rule)
|
||||||
|
|
||||||
|
1. Create short-lived branches from `main`.
|
||||||
|
2. Open PRs to `main` for delivery changes.
|
||||||
|
3. Do not push directly to `main`.
|
||||||
|
4. Merge PRs to `main` with squash strategy only.
|
||||||
|
5. Do not mark implementation complete until PR is merged.
|
||||||
|
6. Do not mark implementation complete until CI/pipeline status is terminal green.
|
||||||
|
7. Close linked issues/tasks only after merge + green CI.
|
||||||
|
8. Before push or merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
|
||||||
|
## Container Release Strategy (When Applicable)
|
||||||
|
|
||||||
|
1. Use immutable image tags: `sha-<shortsha>` and `v{base-version}-rc.{build}`.
|
||||||
|
2. Use mutable environment tags only as pointers (`testing`, optional `staging`, `prod`).
|
||||||
|
3. Deploy/promote by immutable digest; do not deploy by mutable tag alone.
|
||||||
|
4. Do not use `latest` or `dev` as deployment references.
|
||||||
|
5. Use blue-green by default; use canary only with automated metrics and rollback gates.
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns end-to-end delivery: plan, code, test, review, remediate, commit, push, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Code review is agent-executed and REQUIRED for any source-code change.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
||||||
| File | Purpose |
|
| File | Purpose |
|
||||||
|
|||||||
86
templates/agent/projects/python-library/CLAUDE.md.template
Normal file → Executable file
86
templates/agent/projects/python-library/CLAUDE.md.template
Normal file → Executable file
@@ -9,12 +9,14 @@
|
|||||||
|
|
||||||
| Task Type | Guide |
|
| Task Type | Guide |
|
||||||
|-----------|-------|
|
|-----------|-------|
|
||||||
| Bootstrapping this project | `~/.config/mosaic/guides/bootstrap.md` |
|
| End-to-end implementation and validation | `~/.config/mosaic/guides/E2E-DELIVERY.md` |
|
||||||
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/orchestrator.md` |
|
| PRD creation and requirements definition | `~/.config/mosaic/guides/PRD.md` |
|
||||||
| Ralph autonomous development | `~/.config/mosaic/guides/ralph-autonomous.md` |
|
| Bootstrapping this project | `~/.config/mosaic/guides/BOOTSTRAP.md` |
|
||||||
| Backend/API development | `~/.config/mosaic/guides/backend.md` |
|
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/ORCHESTRATOR.md` |
|
||||||
| Code review | `~/.config/mosaic/guides/code-review.md` |
|
| Backend/API development | `~/.config/mosaic/guides/BACKEND.md` |
|
||||||
| QA/Testing | `~/.config/mosaic/guides/qa-testing.md` |
|
| Code review | `~/.config/mosaic/guides/CODE-REVIEW.md` |
|
||||||
|
| Documentation updates and standards | `~/.config/mosaic/guides/DOCUMENTATION.md` |
|
||||||
|
| QA/Testing | `~/.config/mosaic/guides/QA-TESTING.md` |
|
||||||
|
|
||||||
## Technology Stack
|
## Technology Stack
|
||||||
|
|
||||||
@@ -37,6 +39,7 @@ ${PROJECT_DIR}/
|
|||||||
│ └── ${PROJECT_SLUG}/ # Main package
|
│ └── ${PROJECT_SLUG}/ # Main package
|
||||||
├── tests/ # Test files
|
├── tests/ # Test files
|
||||||
├── docs/
|
├── docs/
|
||||||
|
│ ├── PRD.md # Requirements source (or PRD.json)
|
||||||
│ └── scratchpads/ # Per-issue working documents
|
│ └── scratchpads/ # Per-issue working documents
|
||||||
└── pyproject.toml # Project configuration
|
└── pyproject.toml # Project configuration
|
||||||
```
|
```
|
||||||
@@ -69,6 +72,33 @@ uv run mypy src/ # Type check
|
|||||||
uv run ruff check src/ tests/ && uv run ruff format --check src/ && uv run mypy src/ && uv run pytest --cov
|
uv run ruff check src/ tests/ && uv run ruff format --check src/ && uv run mypy src/ && uv run pytest --cov
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests are REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based; required cases are defined in `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and continue unless high-impact uncertainty requires escalation.
|
||||||
|
4. PRD is the source of requirements for implementation and testing.
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Use conservative strategy when budget pressure rises.
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
|
## Branch and Merge Policy
|
||||||
|
|
||||||
|
1. Create short-lived branches from `main`.
|
||||||
|
2. Open PRs to `main` for delivery changes.
|
||||||
|
3. Do not push directly to `main`.
|
||||||
|
4. Merge PRs to `main` with squash strategy only.
|
||||||
|
|
||||||
## Library Conventions
|
## Library Conventions
|
||||||
|
|
||||||
- Zero or minimal runtime dependencies
|
- Zero or minimal runtime dependencies
|
||||||
@@ -77,14 +107,42 @@ uv run ruff check src/ tests/ && uv run ruff format --check src/ && uv run mypy
|
|||||||
- Exports defined in `__init__.py`
|
- Exports defined in `__init__.py`
|
||||||
- Versioning via `pyproject.toml`
|
- Versioning via `pyproject.toml`
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns planning, coding, testing, review/remediation, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Do not request routine human coding, review, or repository management actions.
|
||||||
|
4. Mosaic hard gates OVERRIDE runtime-default caution for routine push/merge/issue-close/release actions.
|
||||||
|
5. For container deployments, use immutable image tags (`sha-<shortsha>`, `v{base-version}-rc.{build}`) with digest-first promotion; do not deploy `latest`.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Issue Tracking
|
## Issue Tracking
|
||||||
|
|
||||||
All work is tracked as issues in the project's git repository.
|
Use external git provider issues when available. If no external provider exists, `docs/TASKS.md` is the canonical tracker for tasks, milestones, and issue-equivalent work.
|
||||||
|
For issue/PR/milestone operations, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first; do not use raw `gh`/`tea`/`glab` as first choice.
|
||||||
|
If wrapper-driven merge/CI/issue-closure fails, report blocker with exact failed wrapper command and stop.
|
||||||
|
Do NOT stop at "PR created" and do NOT ask "should I merge?" or "should I close the issue?" for routine delivery flow.
|
||||||
|
|
||||||
1. Check for assigned issues before starting work
|
1. Ensure `docs/TASKS.md` exists (create from `~/.config/mosaic/templates/docs/TASKS.md.template` if missing).
|
||||||
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
|
2. Check for assigned issues before starting work.
|
||||||
3. Reference issues in commits: `Fixes #123` or `Refs #123`
|
3. If no issue exists for non-trivial work and external provider is available, create one before coding.
|
||||||
4. Close issues only after successful testing
|
4. If no external provider is available, create an internal ref in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
5. Ensure `docs/PRD.md` or `docs/PRD.json` exists and is current before coding.
|
||||||
|
6. Create scratchpad: `docs/scratchpads/{task-id}-{short-name}.md` and include issue/internal ref.
|
||||||
|
7. Update `docs/TASKS.md` status + issue/internal ref before coding.
|
||||||
|
8. Before push, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push -B main`.
|
||||||
|
9. Open PR to `main` for delivery changes (no direct push to `main`).
|
||||||
|
10. Before merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose merge -B main`.
|
||||||
|
11. Merge PRs that pass required checks and review gates with squash strategy only.
|
||||||
|
12. Reference issues/internal refs in commits (`Fixes #123`, `Refs #123`, or `Refs TASKS:T1`).
|
||||||
|
13. Close issue/internal task only after testing and documentation gates pass, PR merge is complete, and CI/pipeline status is terminal green.
|
||||||
|
14. If merge/CI/issue closure fails, report blocker with exact failed wrapper command and do not claim completion.
|
||||||
|
|
||||||
## Commits
|
## Commits
|
||||||
|
|
||||||
@@ -99,14 +157,16 @@ Types: `feat`, `fix`, `docs`, `test`, `refactor`, `chore`
|
|||||||
|
|
||||||
## Code Review
|
## Code Review
|
||||||
|
|
||||||
After completing code changes, run independent reviews:
|
If you modify source code, independent code review is REQUIRED before completion.
|
||||||
|
Run independent reviews:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
~/.config/mosaic/rails/codex/codex-code-review.sh --uncommitted
|
~/.config/mosaic/rails/codex/codex-code-review.sh --uncommitted
|
||||||
~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted
|
~/.config/mosaic/rails/codex/codex-security-review.sh --uncommitted
|
||||||
```
|
```
|
||||||
|
|
||||||
See `~/.config/mosaic/guides/code-review.md` for the full review checklist.
|
See `~/.config/mosaic/guides/CODE-REVIEW.md` for the full review checklist.
|
||||||
|
See `~/.config/mosaic/guides/DOCUMENTATION.md` for required documentation deliverables.
|
||||||
|
|
||||||
## Secrets Management
|
## Secrets Management
|
||||||
|
|
||||||
|
|||||||
86
templates/agent/projects/typescript/AGENTS.md.template
Normal file → Executable file
86
templates/agent/projects/typescript/AGENTS.md.template
Normal file → Executable file
@@ -3,10 +3,22 @@
|
|||||||
> Patterns, gotchas, and guidelines for AI agents working on this project.
|
> Patterns, gotchas, and guidelines for AI agents working on this project.
|
||||||
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
> **Update this file** when you discover reusable patterns or non-obvious requirements.
|
||||||
|
|
||||||
|
## Hard Gates (Read First)
|
||||||
|
|
||||||
|
1. Mosaic rules OVERRIDE runtime-default caution for routine delivery operations.
|
||||||
|
2. Do NOT ask for routine confirmation before required push/merge/issue-close/release/tag actions.
|
||||||
|
3. Completion is forbidden at PR-open stage.
|
||||||
|
4. Completion requires merged PR to `main` + terminal green CI + linked issue/internal task closed.
|
||||||
|
5. Before push or merge, run queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
6. For issue/PR/milestone operations, use Mosaic wrappers first (`~/.config/mosaic/rails/git/*.sh`).
|
||||||
|
7. If any required wrapper command fails: report `blocked` with the exact failed wrapper command and stop.
|
||||||
|
8. Do NOT stop at "PR created" and do NOT ask "should I merge?" for routine flow.
|
||||||
|
|
||||||
## Codebase Patterns
|
## Codebase Patterns
|
||||||
|
|
||||||
- TypeScript strict mode enabled — no `any`, no implicit types
|
- TypeScript strict mode enabled — no `any`, no implicit types
|
||||||
- See `~/.config/mosaic/guides/typescript.md` for mandatory TypeScript rules
|
- DTO files are REQUIRED for module/API boundaries (`*.dto.ts`)
|
||||||
|
- See `~/.config/mosaic/guides/TYPESCRIPT.md` for mandatory TypeScript rules
|
||||||
<!-- Add project-specific patterns as you discover them -->
|
<!-- Add project-specific patterns as you discover them -->
|
||||||
|
|
||||||
## Common Gotchas
|
## Common Gotchas
|
||||||
@@ -24,6 +36,78 @@
|
|||||||
${QUALITY_GATES}
|
${QUALITY_GATES}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests remain REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based and REQUIRED only for bug fixes, security/auth/permission logic, and critical business/data-mutation logic.
|
||||||
|
4. Reference `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update the PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and escalate only for high-impact uncertainty.
|
||||||
|
4. Reference `~/.config/mosaic/guides/PRD.md`.
|
||||||
|
|
||||||
|
## Task Tracking Contract
|
||||||
|
|
||||||
|
1. For non-trivial implementation work, `docs/TASKS.md` MUST exist before coding.
|
||||||
|
2. If external git provider is available (Gitea/GitHub/GitLab), create/update issue(s) before coding and map them in `docs/TASKS.md`.
|
||||||
|
3. If no external provider is available, use internal refs in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
4. Keep `docs/TASKS.md` status in sync with actual progress until completion.
|
||||||
|
5. For issue/PR/milestone actions, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first (no raw `gh`/`tea`/`glab` as first choice).
|
||||||
|
6. If wrapper-driven merge/CI/issue-closure fails, report blocker with the exact failed wrapper command and stop (do not claim completion).
|
||||||
|
|
||||||
|
## Documentation Contract
|
||||||
|
|
||||||
|
Documentation is a hard delivery gate.
|
||||||
|
If code/API/auth/infra changes, required documentation updates MUST be completed before task closure.
|
||||||
|
Keep `docs/` root clean and store reports/artifacts in scoped folders (`docs/reports/`, `docs/tasks/`, `docs/releases/`, `docs/scratchpads/`).
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
- `~/.config/mosaic/guides/DOCUMENTATION.md`
|
||||||
|
- `~/.config/mosaic/templates/docs/DOCUMENTATION-CHECKLIST.md`
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Shift to conservative strategy when budget pressure rises (smaller scope, fewer parallel actions, reduced re-reading).
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
|
## Merge Strategy (Hard Rule)
|
||||||
|
|
||||||
|
1. Create short-lived branches from `main`.
|
||||||
|
2. Open PRs to `main` for delivery changes.
|
||||||
|
3. Do not push directly to `main`.
|
||||||
|
4. Merge PRs to `main` with squash strategy only.
|
||||||
|
5. Do not mark implementation complete until PR is merged.
|
||||||
|
6. Do not mark implementation complete until CI/pipeline status is terminal green.
|
||||||
|
7. Close linked issues/tasks only after merge + green CI.
|
||||||
|
8. Before push or merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push|merge -B main`.
|
||||||
|
|
||||||
|
## Container Release Strategy (When Applicable)
|
||||||
|
|
||||||
|
1. Use immutable image tags: `sha-<shortsha>` and `v{base-version}-rc.{build}`.
|
||||||
|
2. Use mutable environment tags only as pointers (`testing`, optional `staging`, `prod`).
|
||||||
|
3. Deploy/promote by immutable digest; do not deploy by mutable tag alone.
|
||||||
|
4. Do not use `latest` or `dev` as deployment references.
|
||||||
|
5. Use blue-green by default; use canary only with automated metrics and rollback gates.
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns end-to-end delivery: plan, code, test, review, remediate, commit, push, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Code review is agent-executed and REQUIRED for any source-code change.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Key Files
|
## Key Files
|
||||||
|
|
||||||
| File | Purpose |
|
| File | Purpose |
|
||||||
|
|||||||
95
templates/agent/projects/typescript/CLAUDE.md.template
Normal file → Executable file
95
templates/agent/projects/typescript/CLAUDE.md.template
Normal file → Executable file
@@ -9,13 +9,15 @@
|
|||||||
|
|
||||||
| Task Type | Guide |
|
| Task Type | Guide |
|
||||||
|-----------|-------|
|
|-----------|-------|
|
||||||
| Bootstrapping this project | `~/.config/mosaic/guides/bootstrap.md` |
|
| End-to-end implementation and validation | `~/.config/mosaic/guides/E2E-DELIVERY.md` |
|
||||||
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/orchestrator.md` |
|
| PRD creation and requirements definition | `~/.config/mosaic/guides/PRD.md` |
|
||||||
| Ralph autonomous development | `~/.config/mosaic/guides/ralph-autonomous.md` |
|
| Bootstrapping this project | `~/.config/mosaic/guides/BOOTSTRAP.md` |
|
||||||
| Frontend development | `~/.config/mosaic/guides/frontend.md` |
|
| Orchestrating autonomous tasks | `~/.config/mosaic/guides/ORCHESTRATOR.md` |
|
||||||
| TypeScript strict typing | `~/.config/mosaic/guides/typescript.md` |
|
| Frontend development | `~/.config/mosaic/guides/FRONTEND.md` |
|
||||||
| Code review | `~/.config/mosaic/guides/code-review.md` |
|
| TypeScript strict typing | `~/.config/mosaic/guides/TYPESCRIPT.md` |
|
||||||
| QA/Testing | `~/.config/mosaic/guides/qa-testing.md` |
|
| Code review | `~/.config/mosaic/guides/CODE-REVIEW.md` |
|
||||||
|
| Documentation updates and standards | `~/.config/mosaic/guides/DOCUMENTATION.md` |
|
||||||
|
| QA/Testing | `~/.config/mosaic/guides/QA-TESTING.md` |
|
||||||
|
|
||||||
## Technology Stack
|
## Technology Stack
|
||||||
|
|
||||||
@@ -37,6 +39,7 @@ ${PROJECT_DIR}/
|
|||||||
├── src/ # Source code
|
├── src/ # Source code
|
||||||
├── tests/ # Test files
|
├── tests/ # Test files
|
||||||
├── docs/
|
├── docs/
|
||||||
|
│ ├── PRD.md # Requirements source (or PRD.json)
|
||||||
│ └── scratchpads/ # Per-issue working documents
|
│ └── scratchpads/ # Per-issue working documents
|
||||||
└── ${CONFIG_FILES} # Configuration files
|
└── ${CONFIG_FILES} # Configuration files
|
||||||
```
|
```
|
||||||
@@ -67,14 +70,76 @@ ${TYPECHECK_COMMAND}
|
|||||||
${QUALITY_GATES}
|
${QUALITY_GATES}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Testing Policy
|
||||||
|
|
||||||
|
1. Situational tests are the PRIMARY validation gate.
|
||||||
|
2. Baseline tests are REQUIRED for all software changes.
|
||||||
|
3. TDD is risk-based; required cases are defined in `~/.config/mosaic/guides/QA-TESTING.md`.
|
||||||
|
|
||||||
|
## PRD Requirement
|
||||||
|
|
||||||
|
1. Before coding begins, `docs/PRD.md` or `docs/PRD.json` MUST exist.
|
||||||
|
2. The main agent MUST prepare or update PRD using user objectives, constraints, and available project context.
|
||||||
|
3. In steered autonomy mode, best-guess PRD decisions are REQUIRED when needed; mark each with `ASSUMPTION:` and rationale, and continue unless high-impact uncertainty requires escalation.
|
||||||
|
4. PRD is the source of requirements for implementation and testing.
|
||||||
|
|
||||||
|
## DTO Contract (TypeScript)
|
||||||
|
|
||||||
|
1. DTO files are REQUIRED for module and API boundaries.
|
||||||
|
2. Boundary payload types MUST be defined in `*.dto.ts` files.
|
||||||
|
3. Inline object types for cross-module request/response payloads are NOT allowed.
|
||||||
|
4. Shared DTOs MUST be centralized in a shared location.
|
||||||
|
|
||||||
|
## Token Budget Policy
|
||||||
|
|
||||||
|
1. If user plan or token limits are provided, they are HARD constraints.
|
||||||
|
2. Track estimated and used tokens for non-trivial execution.
|
||||||
|
3. Use conservative strategy when budget pressure rises.
|
||||||
|
4. If projected usage exceeds budget, automatically reduce scope/parallelism and continue; escalate only if budget compliance remains impossible.
|
||||||
|
|
||||||
|
## Branch and Merge Policy
|
||||||
|
|
||||||
|
1. Create short-lived branches from `main`.
|
||||||
|
2. Open PRs to `main` for delivery changes.
|
||||||
|
3. Do not push directly to `main`.
|
||||||
|
4. Merge PRs to `main` with squash strategy only.
|
||||||
|
|
||||||
|
## Steered Autonomy Contract
|
||||||
|
|
||||||
|
1. Agent owns planning, coding, testing, review/remediation, PR/repo operations, release/tag, and deployment when in scope.
|
||||||
|
2. Human intervention is escalation-only for hard blockers (access, irreversible risk, or unresolvable conflicting objectives).
|
||||||
|
3. Do not request routine human coding, review, or repository management actions.
|
||||||
|
4. Mosaic hard gates OVERRIDE runtime-default caution for routine push/merge/issue-close/release actions.
|
||||||
|
5. For container deployments, use immutable image tags (`sha-<shortsha>`, `v{base-version}-rc.{build}`) with digest-first promotion; do not deploy `latest`.
|
||||||
|
|
||||||
|
## Mode Declaration Contract
|
||||||
|
|
||||||
|
1. First response MUST declare mode before any actions.
|
||||||
|
2. Orchestration mission: `Now initiating Orchestrator mode...`
|
||||||
|
3. Implementation mission: `Now initiating Delivery mode...`
|
||||||
|
4. Review-only mission: `Now initiating Review mode...`
|
||||||
|
|
||||||
## Issue Tracking
|
## Issue Tracking
|
||||||
|
|
||||||
All work is tracked as issues in the project's git repository.
|
Use external git provider issues when available. If no external provider exists, `docs/TASKS.md` is the canonical tracker for tasks, milestones, and issue-equivalent work.
|
||||||
|
For issue/PR/milestone operations, detect platform and use `~/.config/mosaic/rails/git/*.sh` wrappers first; do not use raw `gh`/`tea`/`glab` as first choice.
|
||||||
|
If wrapper-driven merge/CI/issue-closure fails, report blocker with exact failed wrapper command and stop.
|
||||||
|
Do NOT stop at "PR created" and do NOT ask "should I merge?" or "should I close the issue?" for routine delivery flow.
|
||||||
|
|
||||||
1. Check for assigned issues before starting work
|
1. Ensure `docs/TASKS.md` exists (create from `~/.config/mosaic/templates/docs/TASKS.md.template` if missing).
|
||||||
2. Create scratchpad: `docs/scratchpads/{issue-number}-{short-name}.md`
|
2. Check for assigned issues before starting work.
|
||||||
3. Reference issues in commits: `Fixes #123` or `Refs #123`
|
3. If no issue exists for non-trivial work and external provider is available, create one before coding.
|
||||||
4. Close issues only after successful testing
|
4. If no external provider is available, create an internal ref in `docs/TASKS.md` (example: `TASKS:T1`).
|
||||||
|
5. Ensure `docs/PRD.md` or `docs/PRD.json` exists and is current before coding.
|
||||||
|
6. Create scratchpad: `docs/scratchpads/{task-id}-{short-name}.md` and include issue/internal ref.
|
||||||
|
7. Update `docs/TASKS.md` status + issue/internal ref before coding.
|
||||||
|
8. Before push, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose push -B main`.
|
||||||
|
9. Open PR to `main` for delivery changes (no direct push to `main`).
|
||||||
|
10. Before merge, run CI queue guard: `~/.config/mosaic/rails/git/ci-queue-wait.sh --purpose merge -B main`.
|
||||||
|
11. Merge PRs that pass required checks and review gates with squash strategy only.
|
||||||
|
12. Reference issues/internal refs in commits (`Fixes #123`, `Refs #123`, or `Refs TASKS:T1`).
|
||||||
|
13. Close issue/internal task only after testing and documentation gates pass, PR merge is complete, and CI/pipeline status is terminal green.
|
||||||
|
14. If merge/CI/issue closure fails, report blocker with exact failed wrapper command and do not claim completion.
|
||||||
|
|
||||||
## Commits
|
## Commits
|
||||||
|
|
||||||
@@ -89,7 +154,8 @@ Types: `feat`, `fix`, `docs`, `test`, `refactor`, `chore`
|
|||||||
|
|
||||||
## Code Review
|
## Code Review
|
||||||
|
|
||||||
After completing code changes, run independent reviews:
|
If you modify source code, independent code review is REQUIRED before completion.
|
||||||
|
Run independent reviews:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Code quality review (Codex)
|
# Code quality review (Codex)
|
||||||
@@ -100,7 +166,8 @@ After completing code changes, run independent reviews:
|
|||||||
```
|
```
|
||||||
|
|
||||||
**Fallback:** If Codex is unavailable, use Claude's built-in review skills.
|
**Fallback:** If Codex is unavailable, use Claude's built-in review skills.
|
||||||
See `~/.config/mosaic/guides/code-review.md` for the full review checklist.
|
See `~/.config/mosaic/guides/CODE-REVIEW.md` for the full review checklist.
|
||||||
|
See `~/.config/mosaic/guides/DOCUMENTATION.md` for required documentation deliverables.
|
||||||
|
|
||||||
## Secrets Management
|
## Secrets Management
|
||||||
|
|
||||||
|
|||||||
49
templates/docs/DOCUMENTATION-CHECKLIST.md
Normal file
49
templates/docs/DOCUMENTATION-CHECKLIST.md
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
# Documentation Completion Checklist
|
||||||
|
|
||||||
|
Use this checklist for every task that changes code, API contracts, auth, or operations.
|
||||||
|
|
||||||
|
## Required Artifacts
|
||||||
|
|
||||||
|
- [ ] `docs/PRD.md` or `docs/PRD.json` exists and is current
|
||||||
|
- [ ] `docs/USER-GUIDE/` updated as needed
|
||||||
|
- [ ] `docs/ADMIN-GUIDE/` updated as needed
|
||||||
|
- [ ] `docs/DEVELOPER-GUIDE/` updated as needed
|
||||||
|
- [ ] `docs/API/OPENAPI.yaml` (or `.json`) updated for API changes
|
||||||
|
- [ ] `docs/API/ENDPOINTS.md` updated for API changes
|
||||||
|
- [ ] `docs/SITEMAP.md` updated for navigation changes
|
||||||
|
|
||||||
|
## API Coverage
|
||||||
|
|
||||||
|
- [ ] All public endpoints are documented
|
||||||
|
- [ ] All private/internal endpoints are documented
|
||||||
|
- [ ] All API input schemas are documented
|
||||||
|
- [ ] All API output schemas are documented
|
||||||
|
- [ ] All endpoint auth/permission requirements are documented
|
||||||
|
- [ ] Error codes and failure behavior are documented
|
||||||
|
|
||||||
|
## Structural Standards (Book/Chapter/Page)
|
||||||
|
|
||||||
|
- [ ] `docs/USER-GUIDE/README.md` indexes user chapters/pages
|
||||||
|
- [ ] `docs/ADMIN-GUIDE/README.md` indexes admin chapters/pages
|
||||||
|
- [ ] `docs/DEVELOPER-GUIDE/README.md` indexes developer chapters/pages
|
||||||
|
|
||||||
|
## Docs Root Hygiene
|
||||||
|
|
||||||
|
- [ ] `docs/` root is clean and only contains canonical root docs (PRD, TASKS when active, SITEMAP, optional README) plus category directories
|
||||||
|
- [ ] Reports are under `docs/reports/<category>/` (not `docs/` root)
|
||||||
|
- [ ] Deferred findings are under `docs/reports/deferred/`
|
||||||
|
- [ ] Orchestrator learnings are under `docs/tasks/orchestrator-learnings.json`
|
||||||
|
- [ ] Release notes are under `docs/releases/`
|
||||||
|
- [ ] Archived task snapshots are under `docs/tasks/`
|
||||||
|
- [ ] Scratchpads are under `docs/scratchpads/`
|
||||||
|
|
||||||
|
## Review Gate
|
||||||
|
|
||||||
|
- [ ] Documentation changes are in the same logical change set as code/API changes
|
||||||
|
- [ ] Code review verified documentation completeness
|
||||||
|
- [ ] Missing docs were treated as blocker findings
|
||||||
|
|
||||||
|
## Publishing
|
||||||
|
|
||||||
|
- [ ] Publishing target was confirmed with user if unspecified
|
||||||
|
- [ ] Canonical source remains in-repo unless user explicitly declares otherwise
|
||||||
75
templates/docs/PRD.md.template
Normal file
75
templates/docs/PRD.md.template
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
# PRD: {PROJECT_OR_FEATURE_NAME}
|
||||||
|
|
||||||
|
## Metadata
|
||||||
|
|
||||||
|
- Owner: {owner}
|
||||||
|
- Date: {yyyy-mm-dd}
|
||||||
|
- Status: draft|approved|in-progress|completed
|
||||||
|
- Best-Guess Mode: true|false
|
||||||
|
|
||||||
|
## Problem Statement
|
||||||
|
|
||||||
|
{what problem is being solved and why now}
|
||||||
|
|
||||||
|
## Objectives
|
||||||
|
|
||||||
|
1. {objective-1}
|
||||||
|
2. {objective-2}
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
### In Scope
|
||||||
|
|
||||||
|
1. {in-scope-item}
|
||||||
|
|
||||||
|
### Out of Scope
|
||||||
|
|
||||||
|
1. {out-of-scope-item}
|
||||||
|
|
||||||
|
## User/Stakeholder Requirements
|
||||||
|
|
||||||
|
1. {requirement}
|
||||||
|
|
||||||
|
## Functional Requirements
|
||||||
|
|
||||||
|
1. {functional-requirement}
|
||||||
|
|
||||||
|
## Non-Functional Requirements
|
||||||
|
|
||||||
|
1. Security: {requirements}
|
||||||
|
2. Performance: {requirements}
|
||||||
|
3. Reliability: {requirements}
|
||||||
|
4. Observability: {requirements}
|
||||||
|
|
||||||
|
## Acceptance Criteria
|
||||||
|
|
||||||
|
1. {ac-1}
|
||||||
|
2. {ac-2}
|
||||||
|
|
||||||
|
## Constraints and Dependencies
|
||||||
|
|
||||||
|
1. {constraint-or-dependency}
|
||||||
|
|
||||||
|
## Risks and Open Questions
|
||||||
|
|
||||||
|
1. Risk: {risk}
|
||||||
|
2. Open Question: {question}
|
||||||
|
|
||||||
|
## Testing and Verification Expectations
|
||||||
|
|
||||||
|
1. Baseline checks: {lint/type/unit/integration expectations}
|
||||||
|
2. Situational testing: {required situational checks}
|
||||||
|
3. Evidence format: {how verification will be reported}
|
||||||
|
|
||||||
|
## Milestone / Delivery Intent
|
||||||
|
|
||||||
|
1. Target milestone/version: {e.g., 0.0.2}
|
||||||
|
2. Definition of done: {completion conditions}
|
||||||
|
|
||||||
|
## Assumptions
|
||||||
|
|
||||||
|
List only if Best-Guess Mode is true.
|
||||||
|
Prefix each entry with `ASSUMPTION:`.
|
||||||
|
|
||||||
|
1. ASSUMPTION: {guessed decision and rationale}
|
||||||
|
|
||||||
17
templates/docs/TASKS.md.template
Normal file
17
templates/docs/TASKS.md.template
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# TASKS
|
||||||
|
|
||||||
|
Canonical tracking for active work. Keep this file current.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
1. Update status as work progresses.
|
||||||
|
2. Link every non-trivial task to a provider issue (`#123`) or internal ref (`TASKS:T1`) if no provider is available.
|
||||||
|
3. Keep one row per active task.
|
||||||
|
4. Do not set `status=done` for source-code work until PR is merged, CI/pipeline is terminal green, and linked issue/ref is closed.
|
||||||
|
5. If merge/CI/issue closure fails, set `status=blocked` and record the exact failed wrapper command in `notes`.
|
||||||
|
|
||||||
|
## Tasks
|
||||||
|
|
||||||
|
| id | status | description | issue | repo | branch | depends_on | blocks | agent | started_at | completed_at | estimate | used | notes |
|
||||||
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
|
| T1 | not-started | Example task description | TASKS:T1 | app | feat/example | | | | | | | | |
|
||||||
@@ -24,7 +24,7 @@ Commands:
|
|||||||
|
|
||||||
Options:
|
Options:
|
||||||
--poll-sec N Poll interval (default: 15)
|
--poll-sec N Poll interval (default: 15)
|
||||||
--no-sync Skip docs/tasks.md -> orchestrator queue sync before run
|
--no-sync Skip docs/TASKS.md -> orchestrator queue sync before run
|
||||||
USAGE
|
USAGE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user