226 lines
12 KiB
Markdown
226 lines
12 KiB
Markdown
---
|
|
name: development-scripts-3darch
|
|
description: >
|
|
Create, refactor, review, document, and maintain shell script modules under a repository's
|
|
.scripts/ directory — the api/ + lib/ split, the --index.sh / --index-api.sh /
|
|
--env-vars-reader.sh / --env-vars-validator.sh bootstrap chain, module and root Taskfile.yml
|
|
integration, logging through the shared loggers module, and shared helpers from the base
|
|
module. Use when adding a new script module or a new command to an existing one; writing an
|
|
api/ wrapper or a lib/ implementation function; adding a CLI flag or a required environment
|
|
variable; wiring a module into task; debugging a script that produces no output, cannot find
|
|
a function, or unexpectedly loads .env; or reviewing shell module work for naming, sourcing
|
|
order, and secret-safety — even when the user only says ".scripts", "Taskfile", "task
|
|
runner", "shell module", or names a specific module like loggers or base.
|
|
license: Proprietary
|
|
metadata:
|
|
author: workspace-skills-code-agent
|
|
version: "1.0"
|
|
spec: agentskills.io/specification
|
|
compatibility: Requires bash. Taskfile (task) needed only for task-runner integration. Designed for Cline, Claude Code, GitHub Copilot, OpenAI Codex, and other compatible agent environments
|
|
---
|
|
|
|
# Repository Script Modules
|
|
|
|
## 3D Architecture Wizzard Project Adoption
|
|
|
|
This is the primary project-adopted skill for **3D Architecture Wizzard** (`3darch`).
|
|
|
|
- Central source: https://gitea.lego-cloud.eu/home-v1-skills-code-agent/development-scripts
|
|
- Source branch: `test`
|
|
- Source commit: `5960d5e74713e6b95a403962f479b2b97cb76286`
|
|
- Adopted repository: https://gitea.lego-cloud.eu/corp-v1-3darch-skills-code-agent/development-scripts-3darch
|
|
- Application: https://gitea.lego-cloud.eu/corp-v1-3darch/corp-v1-3darch
|
|
- Documentation: https://gitea.lego-cloud.eu/corp-v1-3darch/corp-v1-3darch-documentation
|
|
- Environment namespace: `CORP_V1_3DARCH_*`
|
|
- Global diagram skill: https://gitea.lego-cloud.eu/home-v1-skills-code-agent/diagrams-drawio
|
|
- Global glossary skill: https://gitea.lego-cloud.eu/home-v1-skills-code-agent/corp-v1-glossary
|
|
- Project automation: none; no scheduler job is authorized.
|
|
|
|
Project engineering peers:
|
|
- `development-branching-strategy-3darch` — https://gitea.lego-cloud.eu/corp-v1-3darch-skills-code-agent/development-branching-strategy-3darch
|
|
- `development-gitops-argo-cd-3darch` — https://gitea.lego-cloud.eu/corp-v1-3darch-skills-code-agent/development-gitops-argo-cd-3darch
|
|
- `development-monorepo-pnpm-3darch` — https://gitea.lego-cloud.eu/corp-v1-3darch-skills-code-agent/development-monorepo-pnpm-3darch
|
|
- `development-scripts-3darch` — https://gitea.lego-cloud.eu/corp-v1-3darch-skills-code-agent/development-scripts-3darch
|
|
- `devsecops-ci-cd-gitea-3darch` — https://gitea.lego-cloud.eu/corp-v1-3darch-skills-code-agent/devsecops-ci-cd-gitea-3darch
|
|
- `documentation-docusaurus-3darch` — https://gitea.lego-cloud.eu/corp-v1-3darch-skills-code-agent/documentation-docusaurus-3darch
|
|
- `template-engine-copier-3darch` — https://gitea.lego-cloud.eu/corp-v1-3darch-skills-code-agent/template-engine-copier-3darch
|
|
|
|
|
|
Work rules for shell automation organised as modules under a repository's `.scripts/`
|
|
directory, with a strict public/private split and a fixed sourcing order.
|
|
|
|
The whole model rests on one idea: **`api/` is what people run, `lib/` is what the code
|
|
calls, and a single bootstrap chain guarantees that by the time an implementation function
|
|
runs, its environment has been read, validated, and its dependencies sourced.**
|
|
|
|
## Scope routing
|
|
|
|
Pick the reference that matches the change; do not load all of them.
|
|
|
|
| The change touches | Read |
|
|
|---|---|
|
|
| A reader, validator, implementation function, or `api/` wrapper | `references/module-anatomy.md` |
|
|
| The `loggers` or `base` module, or logging that produces no output | `references/shared-modules.md` |
|
|
| `.env` files, per-environment layers, or shipping `.scripts/` into a rendered repo | `references/environment-model.md` |
|
|
| A module `Taskfile.yml` or the root `Taskfile.yml` | `references/taskfile.md` |
|
|
| Creating a module, changing one, or checking work before delivery | `references/workflows.md` |
|
|
| Deciding what kind of module something should be | `references/module-patterns.md` |
|
|
|
|
Copy-ready modules live in `assets/`: `module-example-v1/` is the scaffold for a new module;
|
|
`loggers/` and `base/` are working reference implementations.
|
|
|
|
## 1. Repository model
|
|
|
|
```text
|
|
<target-repository>/
|
|
Taskfile.yml # root task runner, includes module Taskfiles
|
|
.scripts/
|
|
<module>/
|
|
api/ # public command wrappers — what users run
|
|
lib/ # implementation functions — what the code calls
|
|
Taskfile.yml # only when the module is exposed through task
|
|
```
|
|
|
|
Commands always run **from the repository root**, never from inside the module:
|
|
|
|
```bash
|
|
./.scripts/<module>/api/<command>.sh [args]
|
|
task <module-alias>:<task-name> -- [args]
|
|
```
|
|
|
|
Every `.` source path in every file is written relative to the repository root
|
|
(`. ./.scripts/loggers/lib/--index-api.sh`). This is why running a script from inside its own
|
|
directory fails to find its dependencies — that is the convention working as designed, not a
|
|
bug to patch with `dirname "$0"`.
|
|
|
|
## 2. Module anatomy
|
|
|
|
```text
|
|
.scripts/<module>/
|
|
api/
|
|
<command-name>.sh
|
|
lib/
|
|
--env-vars-reader.sh # defaults + CLI flag parsing
|
|
--env-vars-validator.sh # required-input checks
|
|
--index-api.sh # sources dependencies + this module's implementations
|
|
--index.sh # full runtime bootstrap
|
|
-<command-name>.sh # one implementation function per command
|
|
Taskfile.yml # optional
|
|
```
|
|
|
|
| File | Responsibility |
|
|
|---|---|
|
|
| `api/<command>.sh` | Thin public entrypoint. Sources `lib/--index.sh`, calls one function. |
|
|
| `lib/-<command>.sh` | The command implementation function. |
|
|
| `lib/--index-api.sh` | Sources upstream module APIs, then this module's implementation files. |
|
|
| `lib/--index.sh` | Runtime bootstrap: reader, then validator, then API index. |
|
|
| `lib/--env-vars-reader.sh` | Exports defaults and parses CLI arguments into environment variables. |
|
|
| `lib/--env-vars-validator.sh` | Validates required variables, failing with an actionable log. |
|
|
| `Taskfile.yml` | Maps task names to `api/` scripts, forwarding `{{.CLI_ARGS}}`. |
|
|
|
|
Not every module has every file — a support-only library like `loggers` has no `api/` and no
|
|
`Taskfile.yml`. See `references/module-patterns.md`.
|
|
|
|
## 3. Standard runtime flow
|
|
|
|
```text
|
|
api/<command>.sh
|
|
└── source lib/--index.sh
|
|
├── source lib/--env-vars-reader.sh # defaults + CLI flags → env vars
|
|
├── source lib/--env-vars-validator.sh # required vars present?
|
|
└── source lib/--index-api.sh
|
|
├── source dependencies (loggers, base, …)
|
|
└── source lib/-<command>.sh # defines the function
|
|
└── call _<moduleNamespace>_<commandFunction>
|
|
```
|
|
|
|
**The order is load-bearing.** The reader runs before the validator so the validator has
|
|
something to check; both run before the API index so implementation functions see a
|
|
fully-prepared environment. Reordering produces failures that look like missing variables.
|
|
|
|
Arguments reach the reader because sourcing happens with the wrapper's own arguments still in
|
|
scope — this is why `api/` wrappers need no argument forwarding of their own.
|
|
|
|
## 4. Naming conventions
|
|
|
|
| Kind | Convention | Example |
|
|
|---|---|---|
|
|
| Module directory | lowercase kebab-case | `module-example-v1`, `repositories-nodejs` |
|
|
| Public command | lowercase kebab-case, action-oriented | `initialize-one.sh`, `find-many-by-query.sh` |
|
|
| Implementation file | single leading dash | `lib/-initialize-one.sh` |
|
|
| Index / lifecycle file | double leading dash | `lib/--index.sh`, `lib/--env-vars-reader.sh` |
|
|
| Function | `_<moduleNamespace>_<actionName>` | `_moduleExampleV1_initializeOne` |
|
|
| Environment variable | uppercase module prefix | `MODULE_EXAMPLE_V1_OUTPUT_DIR` |
|
|
|
|
Kebab-case module names convert to camelCase function namespaces:
|
|
|
|
| Module | Function prefix | Env prefix |
|
|
|---|---|---|
|
|
| `module-example-v1` | `_moduleExampleV1_` | `MODULE_EXAMPLE_V1_` |
|
|
| `repositories-nodejs` | `_repositoriesNodejs_` | `REPOSITORIES_NODEJS_` |
|
|
| `operation-utilities` | `_operationUtilities_` | `OPERATION_UTILITIES_` |
|
|
|
|
The dash count is not decoration — it is how you tell at a glance whether a file defines a
|
|
command (`-name.sh`) or wires the module together (`--name.sh`).
|
|
|
|
## 5. Non-negotiable rules
|
|
|
|
- **`api/` wrappers stay thin.** Source `lib/--index.sh`, call one function, nothing else. No
|
|
implementation, no argument parsing, no validation.
|
|
- **CLI flags are parsed only in `--env-vars-reader.sh`.** Never in an implementation file.
|
|
- **Every new `lib/-*.sh` gets added to `lib/--index-api.sh`.** Forgetting this is the most
|
|
common cause of "command not found" for a function that plainly exists.
|
|
- **Readers preserve already-exported values** — `export X="${X:-default}"` — so a caller can
|
|
override any setting before invoking the module. A module reader never sources `.env` files
|
|
itself; the `base` module owns that. See `references/environment-model.md`.
|
|
- **Log through `_loggers_*` helpers, never raw `echo`.** Loggers write to `stderr`, keeping
|
|
`stdout` clean for real output.
|
|
- **Never log secrets.** Redact tokens, API keys, passwords, and kube config.
|
|
- **Quote variable expansions** unless word splitting is intended.
|
|
- **`return` non-zero from implementation functions; reserve `exit 1` for validators and
|
|
bootstrap.** An `exit` inside a sourced library kills the caller's shell.
|
|
|
|
## 6. Creating a module
|
|
|
|
Full walkthrough in `references/workflows.md`. The short path:
|
|
|
|
1. Copy `assets/module-example-v1/` to `.scripts/<new-module>/`.
|
|
2. Replace every `module-example-v1` path, the `MODULE_EXAMPLE_V1_` env prefix, and the
|
|
`_moduleExampleV1_` function prefix.
|
|
3. Add implementation files as `lib/-<command>.sh` and source them from `lib/--index-api.sh`.
|
|
4. Add `api/<command>.sh` wrappers for user-facing commands only.
|
|
5. Add a module `Taskfile.yml`, and a root include only if the namespace is stable.
|
|
6. Validate (section 7).
|
|
|
|
## 7. Validation
|
|
|
|
```bash
|
|
# Syntax-check every script in the module
|
|
find .scripts/<module> -name '*.sh' -print0 | xargs -0 -n1 bash -n
|
|
|
|
# Confirm task exposure resolves
|
|
task --list
|
|
|
|
# Run the command itself, from the repository root
|
|
./.scripts/<module>/api/<command>.sh --dry-run
|
|
```
|
|
|
|
`bash -n` catches syntax errors but **not** a missing entry in `--index-api.sh` — that only
|
|
surfaces at call time. Always run the command once, from the repository root, before
|
|
delivering. A dry-run flag is worth adding precisely so this check is cheap.
|
|
|
|
## 8. Mistakes to avoid
|
|
|
|
- Putting implementation logic into `api/*.sh`.
|
|
- Adding a `lib/-*.sh` file and forgetting to source it from `lib/--index-api.sh`.
|
|
- Parsing CLI flags in an implementation function instead of the reader.
|
|
- Sourcing `base/lib/--index.sh` from a library function — it reads `.env` and
|
|
environment-specific files as a side effect. Use `base/lib/--index-api.sh` when you only
|
|
need shared functions.
|
|
- Writing source paths relative to the script instead of the repository root.
|
|
- Using `exit` inside a sourced implementation function.
|
|
- Printing secrets, or documenting their values.
|
|
- Adding a root `Taskfile.yml` include for an experimental module.
|
|
- Assuming logging works because the code compiles — a logger whose level flags were never
|
|
exported is silent and returns 0. See `references/shared-modules.md` §3.
|