Files
2026-04-18 22:03:43 +03:00

11 KiB
Raw Permalink Blame History

name, description
name description
monorepo-onboard Adds a new component (submodule / package / workspace member) to a monorepo as a single atomic operation. Updates the component registry (`.gitmodules` / `package.json` workspaces / `Cargo.toml` / etc.), places or extends unified docs, updates CI/compose/env artifacts, and appends an entry to `_docs/_repo-config.yaml`. Intentionally monolithic — onboarding is one user intent that spans multiple artifact domains. Use when the user says "onboard X", "add service Y to the monorepo", "register new repo".

Monorepo Onboard

Onboards a new component atomically. Spans registry + docs + CI + env + config in one coordinated run — because onboarding is a single user intent, and splitting it across multiple skills would fragment the user experience, cause duplicate input collection, and create inconsistent intermediate states in the config file.

Why this skill is monolithic

Onboarding ONE component requires updating ~8 artifacts. If the user had to invoke monorepo-document, monorepo-cicd, and a registry skill separately, they would answer overlapping questions 23 times, and the config file would pass through invalid states between runs. Monolithic preserves atomicity and consistency.

Sync operations (after onboarding is done) ARE split by artifact — see monorepo-document and monorepo-cicd.

Preconditions (hard gates)

  1. _docs/_repo-config.yaml exists.
  2. Top-level confirmed_by_user: true.
  3. The component is NOT already in components: — if it is, redirect to monorepo-document or monorepo-cicd (it's an update, not an onboarding).

Mitigations (M1M7)

  • M1 Separation: this skill does not invoke monorepo-discover automatically. If _repo-config.yaml needs regeneration first, tell the user.
  • M3 Factual vs. interpretive vs. conventional: all user inputs below are CONVENTIONAL (project choices) — always ASK, never infer.
  • M4 Batch inputs in one question round.
  • M5 Skip over guess: if the user's answer doesn't match enumerable options in config (e.g., unknown deployment tier), stop and ask whether to extend config or adjust answer.
  • M6 Assumptions footer + config assumptions_log append.
  • M7 Drift detection: before writing anything, verify every artifact path that will be touched exists (or will be created) — stop on unexpected conditions.

Required inputs (batch-ask, M4)

Collect ALL of these upfront. If any missing, stop and ask. Offer choices from config when the input has a constrained domain (e.g., conventions.deployment_tiers).

Input Example Enumerable?
name satellite-provider No — open-ended, follow conventions.component_naming
location git URL / path No
stack .NET 10, Python 3.12 No — open-ended
purpose (one line) "Fetches satellite imagery" No
doc_placement "extend _docs/07_admin.md" OR "new _docs/NN_satellite.md" Yes — offer options based on docs.*
ci_required Which pipelines (or "none") Yes — infer from ci.tooling
deployment_tier edge Yes — conventions.deployment_tiers
ports "5010/http" or "none" No
depends_on Other components called Yes — list from components: names
env_vars Name + placeholder value No (never real secrets)

If the user provides an answer outside the enumerable set (e.g., deployment tier not in config), stop and ask whether to extend the config or pick from the existing set (M5).

Workflow

Phase 1: Drift check (M7)

Before writing:

  1. Verify repo.component_registry exists on disk.
  2. Verify docs.root exists.
  3. If doc_placement = extend existing doc, verify that doc exists.
  4. Verify every file in ci.orchestration_files and ci.env_template exists.
  5. Verify ci.service_registry_doc exists (if set).

Any missing → stop, ask whether to run monorepo-discover first or proceed skipping that artifact.

Phase 2: Register in component registry

Based on repo.type:

Registry Action
git-submodules Append [submodule "<name>"] stanza to .gitmodules. Preserve existing indentation style exactly.
npm-workspaces Add path to workspaces array in package.json. Preserve JSON formatting.
pnpm-workspace Add to packages: in pnpm-workspace.yaml.
cargo-workspace Add to members: in Cargo.toml.
go-workspace Add to use (...) block in go.work.
adhoc Update the registry file that config points to.

Do NOT run git submodule add, npm install, or equivalent commands. Produce the text diff; the user runs the actual registration command after review.

Phase 3: Root README update

If the root README contains a component/services table (check repo.root_readme):

  1. Insert a new row following existing ordering (alphabetical or deployment-order — match what's there).
  2. Match column widths and punctuation exactly.

If there's an ASCII architecture diagram and deployment_tier implies new runtime presence, ask the user where to place the new box — don't invent a position.

Phase 4: Unified docs placement

If extending an existing doc:

  1. Read the target file.
  2. Add a new H2 section at the appropriate position. If ambiguous (the file has multiple possible sections), ask.
  3. Update file's internal TOC if present.
  4. Update docs.index ONLY if that index has a cross-reference table that includes sub-sections (check the file).

If creating a new doc file:

  1. Determine the filename via docs.file_convention and docs.next_unused_prefix (e.g., 13_satellite_provider.md).

  2. Create using this template:

    # <Component Name>
    
    ## Overview
    <expanded purpose from user input>
    
    ## API
    <endpoints or "None">
    
    ## Data model
    <if applicable, else "None">
    
    ## Configuration
    <env vars from user input>
    
  3. Update docs.index (_docs/README.md or equivalent):

    • Add row to docs table, matching existing format
    • If the component introduces a permission AND the index has a permission → feature matrix, update that too
  4. After creating, update docs.next_unused_prefix in _docs/_repo-config.yaml.

Phase 5: Cross-cutting docs

For each docs.cross_cutting entry whose owns: matches a fact provided by the user, update that doc:

  • depends_on non-empty → architecture/communication doc
  • New schema/tables → schema doc (ask user for schema details if not provided)
  • New permission/role → permissions doc

If a cross-cutting concern is implied by inputs but has no owner in config → add to unresolved: in config and ask.

Phase 6: CI/CD integration

Update:

  • ci.service_registry_doc: add new row to the service table in that file (if set). Match existing format.
  • Orchestration files (ci.orchestration_files): add service block if component is a runtime service. Use ci.image_tag_format for the image string. Include depends_on, ports, environment, volumes based on user inputs and existing service-block structure.
  • ci.env_template: append new env vars with placeholder values. NEVER real secrets.

Phase 7: Per-component CI — guidance ONLY

For <component>/.woodpecker/*.yml, <component>/.github/workflows/*, etc.:

Do NOT create these files. They live inside the component's own repo/workspace.

Instead, output the ci.pipeline_template (from config) customized for this component, so the user can copy it into the component's workspace themselves.

Phase 8: Update _docs/_repo-config.yaml

Append new entry to components::

  - name: <name>
    path: <path>/
    stack: <stack>
    confirmed: true            # user explicitly onboarded = confirmed
    evidence: [user_onboarded]
    primary_doc: <new doc path>
    secondary_docs: [...]
    ci_config: <component>/.<ci_tool>/  # expected location
    deployment_tier: <tier>
    ports: [...]
    depends_on: [...]
    env_vars: [...]

If docs.next_unused_prefix was consumed, increment it.

Append to assumptions_log::

  - date: <date>
    skill: monorepo-onboard
    run_notes: "Onboarded <name>"
    assumptions:
      - "<list>"

Do NOT change confirmed_by_user — only human sets that.

monorepo-onboard run complete — onboarded `<name>`.

Files modified (N):
  - .gitmodules — added submodule entry
  - README.md — added row in Services table
  - _docs/NN_<name>.md — created
  - _docs/README.md — added index row + permission-matrix row
  - _docs/00_top_level_architecture.md — added to Communication section
  - docker-compose.run.yml — added service block
  - .env.example — added <NAME>_API_KEY placeholder
  - ci_steps.md — added service-table row
  - _docs/_repo-config.yaml — recorded component + updated next_unused_prefix

Files NOT modified but the user must handle:
  - <component>/.woodpecker/build-*.yml — create inside the component's own workspace
    (template below)
  - CI system UI — activate the new repo

Next manual actions:
  1. Actually add the component: `git submodule add <url> <path>` (or equivalent)
  2. Create per-component CI config using the template
  3. Activate the repo in your CI system
  4. Review the full diff, then commit with `<commit_prefix> Onboard <name>`

Pipeline template for <name>:
<rendered ci.pipeline_template with <service> replaced>

Assumptions used this run:
  - Doc filename convention: <from config>
  - Image tag format: <from config>
  - Alphabetical ordering in Services table (observed)

What this skill will NEVER do

  • Run git submodule add, npm install, or any network/install-touching command
  • Create per-component CI configs inside component directories
  • Invent env vars, ports, permissions, or ticket IDs — all from user
  • Auto-commit
  • Reorder existing table rows beyond inserting the new one
  • Set confirmed_by_user: true in config
  • Touch a file outside the explicit scope

Rollback (pre-commit)

Before the user commits, revert is straightforward:

git checkout -- <every file listed in the report>

For the new doc file, remove it explicitly:

rm _docs/NN_<name>.md

The component itself (if already registered via git submodule add or workspace install) requires manual cleanup — outside this skill's scope.

Edge cases

  • Component already in config (not registry) or vice versa → state mismatch. Redirect to monorepo-discover to reconcile.
  • User input contradicts config convention (e.g., new deployment tier not in conventions.deployment_tiers): stop, ask — extend config, or choose from existing.
  • docs.next_unused_prefix collides with an existing file (race condition): bump and retry once; if still colliding, stop.
  • No docs.root in config: cannot place a doc. Ask user to run monorepo-discover or manually set it in the config first.