forgedock 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/bin/forgedock.mjs +496 -364
- package/bin/labels.json +152 -0
- package/commands/audit-agents.md +4 -2
- package/commands/autopilot.md +19 -11
- package/commands/cleanup.md +27 -12
- package/commands/deploy-info.md +36 -17
- package/commands/incident-response.md +15 -10
- package/commands/issue.md +8 -6
- package/commands/milestone.md +97 -48
- package/commands/orchestrate.md +109 -65
- package/commands/pipeline-health.md +8 -1
- package/commands/qa-sweep.md +14 -3
- package/commands/review-pr-agents.md +1 -1
- package/commands/review-pr-staging.md +129 -23
- package/commands/review-pr.md +237 -90
- package/commands/rollback.md +26 -7
- package/commands/security-audit.md +27 -25
- package/commands/sync-ecosystem.md +2 -2
- package/commands/work-on/build/architect.md +154 -2
- package/commands/work-on/build/context.md +131 -3
- package/commands/work-on/build/validate.md +32 -13
- package/commands/work-on/decompose.md +2 -0
- package/commands/work-on-monolithic.md +9 -5
- package/commands/work-on.md +67 -23
- package/docs/CONFIG.md +117 -0
- package/package.json +2 -1
- package/scripts/verify-route-registration.sh +36 -15
- package/scripts/verify-sops-chain.sh +18 -0
- package/templates/devdocs/README.md +96 -0
- package/templates/devdocs/agent/using-forgedock.md +245 -0
- package/templates/devdocs/agent/using-github.md +325 -0
- package/templates/devdocs/project/architecture.md +122 -0
- package/templates/devdocs/project/conventions.md +158 -0
- package/templates/devdocs/project/custom-instructions.md +73 -0
- package/templates/devdocs/project/glossary.md +84 -0
- package/templates/devdocs/project/stack.md +80 -0
- package/templates/devdocs/templates/commit-convention.md +147 -0
- package/templates/devdocs/templates/issue.md +141 -0
- package/templates/devdocs/templates/pull-request.md +115 -0
- package/templates/devdocs/templates/review-finding.md +147 -0
- package/bin/github-app-manifest.json +0 -24
package/commands/work-on.md
CHANGED
|
@@ -747,25 +747,50 @@ if iteration == max_iterations AND not PASS:
|
|
|
747
747
|
|
|
748
748
|
### 3H: Format and verify
|
|
749
749
|
|
|
750
|
+
All tool commands are read from `forge.yaml → verification.commands`. When a key is absent, the step logs `SKIPPED — not configured in verification.commands` and continues rather than silently passing.
|
|
751
|
+
|
|
750
752
|
**Python**:
|
|
751
753
|
```bash
|
|
752
754
|
cd {WORKTREE_PATH}
|
|
753
|
-
|
|
755
|
+
|
|
756
|
+
PYTHON_FORMAT=$(awk '/^ commands:/{f=1;next} f && /^[^ \t]/{exit} f' forge.yaml 2>/dev/null | awk '/^ python:/{f=1;next} f && /^ [^ \t]/{exit} f' | grep 'format:' | head -1 | sed "s/.*format: *['\"]//;s/['\"].*//")
|
|
757
|
+
if [ -n "$PYTHON_FORMAT" ]; then
|
|
758
|
+
eval "$PYTHON_FORMAT" 2>&1
|
|
759
|
+
else
|
|
760
|
+
echo "SKIPPED — python.format not configured in verification.commands"
|
|
761
|
+
fi
|
|
762
|
+
|
|
763
|
+
# Compile check always runs (no config needed — catches syntax errors)
|
|
764
|
+
python -m py_compile {PYTHON_FILES}
|
|
754
765
|
```
|
|
755
766
|
`py_compile` failures are BLOCKING.
|
|
756
767
|
|
|
757
|
-
**TypeScript
|
|
768
|
+
**TypeScript**:
|
|
758
769
|
```bash
|
|
759
770
|
cd {WORKTREE_PATH}
|
|
760
|
-
prettier --write {TS_FILES} && tsc --noEmit
|
|
761
|
-
```
|
|
762
|
-
`tsc --noEmit` failures are BLOCKING.
|
|
763
771
|
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
772
|
+
TS_FORMAT=$(awk '/^ commands:/{f=1;next} f && /^[^ \t]/{exit} f' forge.yaml 2>/dev/null | awk '/^ typescript:/{f=1;next} f && /^ [^ \t]/{exit} f' | grep 'format:' | head -1 | sed "s/.*format: *['\"]//;s/['\"].*//")
|
|
773
|
+
TS_TYPECHECK=$(awk '/^ commands:/{f=1;next} f && /^[^ \t]/{exit} f' forge.yaml 2>/dev/null | awk '/^ typescript:/{f=1;next} f && /^ [^ \t]/{exit} f' | grep 'typecheck:' | head -1 | sed "s/.*typecheck: *['\"]//;s/['\"].*//")
|
|
774
|
+
TS_BUILD=$(awk '/^ commands:/{f=1;next} f && /^[^ \t]/{exit} f' forge.yaml 2>/dev/null | awk '/^ typescript:/{f=1;next} f && /^ [^ \t]/{exit} f' | grep 'build:' | head -1 | sed "s/.*build: *['\"]//;s/['\"].*//")
|
|
775
|
+
|
|
776
|
+
if [ -n "$TS_FORMAT" ]; then
|
|
777
|
+
eval "$TS_FORMAT" 2>&1
|
|
778
|
+
else
|
|
779
|
+
echo "SKIPPED — typescript.format not configured in verification.commands"
|
|
780
|
+
fi
|
|
781
|
+
|
|
782
|
+
if [ -n "$TS_TYPECHECK" ]; then
|
|
783
|
+
eval "$TS_TYPECHECK" 2>&1
|
|
784
|
+
TS_EXIT=$?
|
|
785
|
+
elif [ -n "$TS_BUILD" ]; then
|
|
786
|
+
eval "$TS_BUILD" 2>&1 | tail -30
|
|
787
|
+
TS_EXIT=$?
|
|
788
|
+
else
|
|
789
|
+
echo "SKIPPED — typescript.typecheck and typescript.build not configured in verification.commands"
|
|
790
|
+
TS_EXIT=0
|
|
791
|
+
fi
|
|
768
792
|
```
|
|
793
|
+
Typecheck or build failures are BLOCKING.
|
|
769
794
|
|
|
770
795
|
### 3I: Frontend proxy wiring check (MANDATORY)
|
|
771
796
|
|
|
@@ -791,27 +816,44 @@ Advisory only — does not block build. Check for lambda/callable in connect_arg
|
|
|
791
816
|
|
|
792
817
|
Skip if no new env vars introduced.
|
|
793
818
|
|
|
819
|
+
**Config variables used by this phase** (set in `forge.yaml`):
|
|
820
|
+
- `{deploy.secrets_backend}` — secrets delivery method (`sops`, `aws-sm`, `vault`, `ci-env`, `none`). When absent or not `sops`, SOPS-specific checks below are skipped with an explicit log message.
|
|
821
|
+
- `{verification.services[name].container}` — container name for post-deploy verification. Resolved by matching the service name; falls back to `{service}` (bare name) when not configured.
|
|
822
|
+
|
|
794
823
|
For each new env var, verify present in ALL required locations:
|
|
795
824
|
|
|
796
825
|
| Location | Required for |
|
|
797
826
|
|----------|-------------|
|
|
798
827
|
| `.env.example` | All new vars |
|
|
799
|
-
| `
|
|
800
|
-
| `
|
|
801
|
-
| `
|
|
802
|
-
| `docker-compose.prod.yml` | Vars needing explicit injection |
|
|
828
|
+
| Secrets backend (see `deploy.secrets_backend`) | Secret vars — skip if backend is `none` or unset |
|
|
829
|
+
| `app/env_validation.py` | API service vars (if project has one) |
|
|
830
|
+
| `docker-compose.prod.yml` | Vars needing explicit injection (if project uses Docker Compose) |
|
|
803
831
|
|
|
804
|
-
|
|
832
|
+
**Secrets backend check** *(trigger: `deploy.secrets_backend == "sops"`)*:
|
|
805
833
|
|
|
806
|
-
|
|
834
|
+
If the project uses SOPS, verify the new var is present in all SOPS chain locations:
|
|
835
|
+
- `infra/secrets/prod.enc.yaml` — SOPS-encrypted secret store
|
|
836
|
+
- `infra/decrypt-secrets.sh` ENV_MAPPING — maps SOPS key to env var name
|
|
837
|
+
- Deploy chain: SOPS → `decrypt-secrets.sh` (ENV_MAPPING) → `.env.secrets` → `merge-env-secrets.sh` → `.env.production` → docker-compose `env_file`
|
|
807
838
|
|
|
808
|
-
|
|
839
|
+
If `deploy.secrets_backend` is absent or not `sops`, skip these checks and log:
|
|
840
|
+
> `SKIP: SOPS chain check — deploy.secrets_backend is not "sops". Configure deploy.secrets_backend in forge.yaml to enable.`
|
|
841
|
+
|
|
842
|
+
**Operator-set var classification** *(trigger: new env var is NOT in the configured secrets backend)*: <!-- Added: forge#380 -->
|
|
843
|
+
|
|
844
|
+
Some env vars are operator-set (non-secret, not sourced from the secrets backend) — they must be manually added to the runtime environment on the production server. When a new env var has no entry in the secrets backend, classify it as operator-set and add a **HARD BLOCKER** item to the Testing Checklist.
|
|
845
|
+
|
|
846
|
+
Resolve the container name for the verification command:
|
|
847
|
+
1. Look up the service in `forge.yaml → verification.services[]` by name — use the `container` field if present.
|
|
848
|
+
2. If no matching entry, fall back to the bare service name: `{service}` (no suffix).
|
|
809
849
|
|
|
810
850
|
```
|
|
811
|
-
- [ ] HARD BLOCKER: Add {VAR_NAME} to
|
|
812
|
-
This var is operator-set
|
|
813
|
-
|
|
814
|
-
Verify with: docker exec {
|
|
851
|
+
- [ ] HARD BLOCKER: Add {VAR_NAME} to the runtime environment on the production server.
|
|
852
|
+
This var is operator-set — it does NOT flow through the automated secrets chain.
|
|
853
|
+
It must be added manually before or after deploy.
|
|
854
|
+
Verify with: docker exec {CONTAINER_NAME} env | grep {VAR_NAME}
|
|
855
|
+
(CONTAINER_NAME resolved from verification.services[{service}].container in forge.yaml,
|
|
856
|
+
or bare service name if not configured)
|
|
815
857
|
```
|
|
816
858
|
|
|
817
859
|
**`env_file` re-read warning** *(trigger: any new env var added to `.env.production` path)*:
|
|
@@ -822,11 +864,13 @@ Add this warning to the Testing Checklist whenever a new env var is introduced (
|
|
|
822
864
|
|
|
823
865
|
**Post-deploy in-container verification** *(trigger: any new env var)*:
|
|
824
866
|
|
|
825
|
-
Add the following to the Testing Checklist so the deployer can confirm delivery after deploy
|
|
867
|
+
Add the following to the Testing Checklist so the deployer can confirm delivery after deploy.
|
|
868
|
+
|
|
869
|
+
Resolve `{CONTAINER_NAME}` from `forge.yaml → verification.services[{service}].container`; use `{service}` (bare) if the field is absent.
|
|
826
870
|
|
|
827
871
|
```bash
|
|
828
872
|
# Verify env var reached the running container (run post-deploy)
|
|
829
|
-
docker exec {
|
|
873
|
+
docker exec {CONTAINER_NAME} env | grep {VAR_NAME}
|
|
830
874
|
# Expected: {VAR_NAME}={value}
|
|
831
875
|
# If blank: container was not recreated — run: docker compose up --no-deps --force-recreate {service}
|
|
832
876
|
```
|
|
@@ -1100,4 +1144,4 @@ gh issue comment {NUMBER} {GH_FLAG} --body "<!-- FORGE:TRAJECTORY -->
|
|
|
1100
1144
|
- PR creation fails: check if branch pushed, if PR already exists
|
|
1101
1145
|
- Merge conflicts: report to user, do NOT auto-resolve
|
|
1102
1146
|
- gh CLI fails: check `gh auth status`
|
|
1103
|
-
- Label missing: `gh label create "{name}" --color {hex} -R {GH_REPO}`
|
|
1147
|
+
- Label missing: run `npx forgedock labels setup` (from the project directory, or pass `--repo owner/repo`) to idempotently bootstrap all ForgeDock-managed labels with canonical colors and descriptions. Alternatively: `gh label create "{name}" --color {hex} --description "Managed by ForgeDock." --force -R {GH_REPO}`
|
package/docs/CONFIG.md
CHANGED
|
@@ -23,6 +23,7 @@ echo "forge.yaml" >> .gitignore # if your credentials path is sensitive
|
|
|
23
23
|
| [`project_board`](#project_board-optional) | No | GitHub Projects v2 integration |
|
|
24
24
|
| [`services`](#services-optional) | No | External service URLs and IDs |
|
|
25
25
|
| [`review`](#review-optional) | No | Context injected into review agents |
|
|
26
|
+
| [`devdocs`](#devdocs-optional) | No | Devdocs knowledge tree path |
|
|
26
27
|
| [`verification`](#verification-optional) | No | Health-check patterns |
|
|
27
28
|
| [`billing`](#billing-optional) | No | Enable financial integrity audit phase |
|
|
28
29
|
|
|
@@ -305,6 +306,39 @@ review:
|
|
|
305
306
|
|
|
306
307
|
---
|
|
307
308
|
|
|
309
|
+
## `devdocs` (OPTIONAL)
|
|
310
|
+
|
|
311
|
+
Path configuration for the devdocs knowledge tree. Pipeline agents (work-on, review-pr, etc.) read these files as **authoritative project knowledge** before acting.
|
|
312
|
+
|
|
313
|
+
Run `npx forgedock docs init` to scaffold the tree from ForgeDock's seed templates into the configured path.
|
|
314
|
+
|
|
315
|
+
```yaml
|
|
316
|
+
devdocs:
|
|
317
|
+
path: "devdocs"
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
| Field | Type | Required | Description |
|
|
321
|
+
|-------|------|----------|-------------|
|
|
322
|
+
| `path` | string (relative path) | No | Path to the devdocs tree, relative to project root. Default: `devdocs`. |
|
|
323
|
+
|
|
324
|
+
**Commands that use this section**: `docs init`, `work-on/build/context` (Phase C-1), `work-on/build/architect` (Phase A0)
|
|
325
|
+
|
|
326
|
+
### Migration from `review.context`
|
|
327
|
+
|
|
328
|
+
If you previously stored project context in `forge.yaml → review.context`, move that content into the appropriate devdocs file after running `npx forgedock docs init`:
|
|
329
|
+
|
|
330
|
+
| `review.context` content | Target devdocs file |
|
|
331
|
+
|--------------------------|---------------------|
|
|
332
|
+
| Architecture decisions | `devdocs/project/architecture.md` |
|
|
333
|
+
| Tech stack details | `devdocs/project/stack.md` |
|
|
334
|
+
| Coding conventions | `devdocs/project/conventions.md` |
|
|
335
|
+
| Project terminology | `devdocs/project/glossary.md` |
|
|
336
|
+
| ForgeDock usage notes | `devdocs/agent/using-forgedock.md` |
|
|
337
|
+
|
|
338
|
+
Agents read devdocs files as binding source-of-truth, so they receive richer context than the single `review.context` string.
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
308
342
|
## `verification` (OPTIONAL)
|
|
309
343
|
|
|
310
344
|
Service health-check patterns for the quality gate and validate commands.
|
|
@@ -382,6 +416,47 @@ billing:
|
|
|
382
416
|
|
|
383
417
|
---
|
|
384
418
|
|
|
419
|
+
## Label Bootstrap
|
|
420
|
+
|
|
421
|
+
ForgeDock manages a canonical set of GitHub labels for use across all pipeline commands. Labels cover workflow state, priority, review findings, audit findings, and category classification.
|
|
422
|
+
|
|
423
|
+
### Bootstrap command
|
|
424
|
+
|
|
425
|
+
```bash
|
|
426
|
+
# Create/update all ForgeDock-managed labels on the repo defined in forge.yaml:
|
|
427
|
+
npx forgedock labels setup
|
|
428
|
+
|
|
429
|
+
# Or target a specific repo explicitly:
|
|
430
|
+
npx forgedock labels setup --repo owner/repo
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
Running this command is idempotent — it creates labels that don't exist and updates the color/description of labels that do. Safe to re-run at any time.
|
|
434
|
+
|
|
435
|
+
**When to run it**: Once after `npx forgedock install`, or whenever a pipeline command fails with "label not found". The command bootstraps every label the pipeline relies on.
|
|
436
|
+
|
|
437
|
+
### Canonical label set
|
|
438
|
+
|
|
439
|
+
The full manifest lives in [`bin/labels.json`](../bin/labels.json) in the ForgeDock package. Each label has a fixed hex color and a description attributing it to ForgeDock.
|
|
440
|
+
|
|
441
|
+
| Family | Labels |
|
|
442
|
+
|--------|--------|
|
|
443
|
+
| Priority | `priority:P0` `priority:P1` `priority:P2` `priority:P3` |
|
|
444
|
+
| Workflow | `workflow:investigating` `workflow:ready-to-build` `workflow:building` `workflow:in-review` `workflow:merged` `workflow:decomposed` `workflow:invalid` |
|
|
445
|
+
| Pipeline | `needs-human` `review-finding` `needs-validation` `validated` `false-positive` `staging-review` `audit-finding` `orchestration-metrics` `health-report` |
|
|
446
|
+
| Category | `bug` `enhancement` `feature` `refactor` `dead-code` `improvement` `documentation` `qa` `security` `performance` |
|
|
447
|
+
|
|
448
|
+
### Colors
|
|
449
|
+
|
|
450
|
+
Colors are grouped by semantic meaning:
|
|
451
|
+
- **Critical/error** (`#B60205`): `priority:P0`, `security`
|
|
452
|
+
- **High/warning-red** (`#D93F0B`): `priority:P1`, `review-finding`, `audit-finding`
|
|
453
|
+
- **Medium/yellow** (`#FBCA04`): `priority:P2`, `needs-validation`
|
|
454
|
+
- **Low/green** (`#C2E0C6`, `#0E8A16`): `priority:P3`, `workflow:merged`, `validated`
|
|
455
|
+
- **Blue pipeline** (`#1D76DB`, `#0075CA`, `#0052CC`): active workflow states
|
|
456
|
+
- **Neutral** (`#CCCCCC`, `#E4E669`): terminal/dismissal states
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
385
460
|
## Config Reading Conventions
|
|
386
461
|
|
|
387
462
|
ForgeDock commands use two accepted patterns for reading `forge.yaml`:
|
|
@@ -393,6 +468,48 @@ Do **not** mix the two patterns for the same block of variables (e.g., `yq` with
|
|
|
393
468
|
|
|
394
469
|
---
|
|
395
470
|
|
|
471
|
+
## CLAUDE.md Integration
|
|
472
|
+
|
|
473
|
+
ForgeDock can inject a managed usage block into your project's `CLAUDE.md` so every Claude Code session opened in the repo automatically knows that ForgeDock drives development here and which commands to use.
|
|
474
|
+
|
|
475
|
+
### How It Works
|
|
476
|
+
|
|
477
|
+
Running `npx forgedock init` or `npx forgedock integrate` writes a marker-bounded block into `CLAUDE.md`:
|
|
478
|
+
|
|
479
|
+
```
|
|
480
|
+
<!-- BEGIN FORGEDOCK -->
|
|
481
|
+
## ForgeDock — Autonomous Development Pipeline
|
|
482
|
+
...command index and conventions...
|
|
483
|
+
<!-- END FORGEDOCK -->
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
The block is **idempotent** — re-running replaces only the managed section and leaves all other `CLAUDE.md` content untouched. If `CLAUDE.md` does not exist, it is created.
|
|
487
|
+
|
|
488
|
+
If `AGENTS.md` already exists in the project root, the same block is mirrored into it.
|
|
489
|
+
|
|
490
|
+
### Commands
|
|
491
|
+
|
|
492
|
+
| Command | Action |
|
|
493
|
+
|---------|--------|
|
|
494
|
+
| `npx forgedock init` | Generates `forge.yaml` **and** injects the CLAUDE.md block |
|
|
495
|
+
| `npx forgedock integrate` | Injects/refreshes the block without modifying `forge.yaml` |
|
|
496
|
+
|
|
497
|
+
### Opting Out
|
|
498
|
+
|
|
499
|
+
To prevent ForgeDock from managing the block, remove the `<!-- BEGIN FORGEDOCK -->` / `<!-- END FORGEDOCK -->` markers from `CLAUDE.md`. Without the markers, subsequent runs will append a new block rather than replacing one — so if you want to opt out permanently, delete or omit the markers **and** do not run `integrate` again.
|
|
500
|
+
|
|
501
|
+
Alternatively, keep the markers but edit the content between them freely — ForgeDock will replace that section on the next run, so any manual edits inside the markers will be overwritten.
|
|
502
|
+
|
|
503
|
+
### Re-generating
|
|
504
|
+
|
|
505
|
+
The command index inside the block is auto-generated from the `description:` frontmatter in each `commands/*.md` file. To refresh it after a ForgeDock update:
|
|
506
|
+
|
|
507
|
+
```bash
|
|
508
|
+
npx forgedock integrate
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
396
513
|
## Complete Example
|
|
397
514
|
|
|
398
515
|
See [`forge.yaml.example`](../forge.yaml.example) at the repository root for a fully annotated example covering all sections.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "forgedock",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "GitHub as a knowledge graph for AI agents. Autonomous dev pipeline for Claude Code.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"forgedock": "bin/forgedock.mjs"
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"commands/",
|
|
37
37
|
"docs/",
|
|
38
38
|
"scripts/",
|
|
39
|
+
"templates/",
|
|
39
40
|
"LICENSE",
|
|
40
41
|
"README.md"
|
|
41
42
|
],
|
|
@@ -5,6 +5,18 @@
|
|
|
5
5
|
# changed_files_file: path to a file listing changed files (one per line)
|
|
6
6
|
# repo_root: path to the repository root
|
|
7
7
|
#
|
|
8
|
+
# Layout path overrides (env vars — override defaults for non-AlterLab layouts):
|
|
9
|
+
# FORGE_PAGES_ROOT Root of Next.js App Router pages dir (default: web/src/app)
|
|
10
|
+
# FORGE_API_ROUTERS_DIR Dir containing FastAPI router .py files (default: services/api/app/routers)
|
|
11
|
+
# FORGE_API_MAIN Path to API app entrypoint, relative to repo root (default: services/api/app/main.py)
|
|
12
|
+
# FORGE_API_MIDDLEWARE_DIR Dir containing API middleware .py files (default: services/api/app/middleware)
|
|
13
|
+
# FORGE_API_SERVICES_DIR Root of the backend API service dir (default: services/api)
|
|
14
|
+
# FORGE_WORKER_DIR Root of the background worker service dir (default: services/worker)
|
|
15
|
+
# FORGE_COMPONENTS_DIR Root of shared frontend component library (default: web/src/components)
|
|
16
|
+
#
|
|
17
|
+
# Set these from forge.yaml review.layout fields before invoking, e.g.:
|
|
18
|
+
# export FORGE_PAGES_ROOT=$(yq '.review.layout.pages // "web/src/app"' forge.yaml)
|
|
19
|
+
#
|
|
8
20
|
# Output: Structured findings (one per line, prefixed with severity)
|
|
9
21
|
# BLOCKING: <message> — must fix before merge
|
|
10
22
|
# WARNING: <message> — likely issue, verify manually
|
|
@@ -23,12 +35,21 @@ else
|
|
|
23
35
|
FILES=$(cat "$CHANGED_FILES")
|
|
24
36
|
fi
|
|
25
37
|
|
|
38
|
+
# Layout path configuration — read from env vars, fall back to AlterLab defaults
|
|
39
|
+
FORGE_PAGES_ROOT="${FORGE_PAGES_ROOT:-web/src/app}"
|
|
40
|
+
FORGE_API_ROUTERS_DIR="${FORGE_API_ROUTERS_DIR:-services/api/app/routers}"
|
|
41
|
+
FORGE_API_MAIN="${FORGE_API_MAIN:-services/api/app/main.py}"
|
|
42
|
+
FORGE_API_MIDDLEWARE_DIR="${FORGE_API_MIDDLEWARE_DIR:-services/api/app/middleware}"
|
|
43
|
+
FORGE_API_SERVICES_DIR="${FORGE_API_SERVICES_DIR:-services/api}"
|
|
44
|
+
FORGE_WORKER_DIR="${FORGE_WORKER_DIR:-services/worker}"
|
|
45
|
+
FORGE_COMPONENTS_DIR="${FORGE_COMPONENTS_DIR:-web/src/components}"
|
|
46
|
+
|
|
26
47
|
BLOCKING=0
|
|
27
48
|
WARNINGS=0
|
|
28
49
|
|
|
29
50
|
# --- Next.js Route Handler registration check ---
|
|
30
51
|
while read -r f; do
|
|
31
|
-
URL_PATH=$(echo "$f" | sed
|
|
52
|
+
URL_PATH=$(echo "$f" | sed "s|^${FORGE_PAGES_ROOT}||; s|/route\\.ts\$||; s|\\[.*\\]|*|g")
|
|
32
53
|
ROUTE_SEGMENT=$(echo "$URL_PATH" | sed 's|/api/v1/||; s|/.*||')
|
|
33
54
|
|
|
34
55
|
# Check if next.config.js has a rewrite that might shadow this route
|
|
@@ -48,50 +69,50 @@ while read -r f; do
|
|
|
48
69
|
WARNINGS=$((WARNINGS + 1))
|
|
49
70
|
fi
|
|
50
71
|
fi
|
|
51
|
-
done < <(echo "$FILES" | grep -E "
|
|
72
|
+
done < <(echo "$FILES" | grep -E "^${FORGE_PAGES_ROOT}/api/.*route\\.ts$") || true
|
|
52
73
|
|
|
53
74
|
# --- Python API Router registration check ---
|
|
54
75
|
while read -r f; do
|
|
55
76
|
ROUTER_NAME=$(basename "$f" .py)
|
|
56
|
-
MAIN_PY="$REPO_ROOT
|
|
77
|
+
MAIN_PY="$REPO_ROOT/${FORGE_API_MAIN}"
|
|
57
78
|
|
|
58
79
|
if [ -f "$MAIN_PY" ]; then
|
|
59
80
|
if grep -q "$ROUTER_NAME" "$MAIN_PY" 2>/dev/null; then
|
|
60
|
-
echo "OK: API Router '$ROUTER_NAME' ($f) — registered in
|
|
81
|
+
echo "OK: API Router '$ROUTER_NAME' ($f) — registered in $(basename "$MAIN_PY")"
|
|
61
82
|
else
|
|
62
|
-
echo "BLOCKING: API Router '$ROUTER_NAME' ($f) — NOT found in
|
|
83
|
+
echo "BLOCKING: API Router '$ROUTER_NAME' ($f) — NOT found in $(basename "$MAIN_PY"). Router will not be reachable."
|
|
63
84
|
BLOCKING=$((BLOCKING + 1))
|
|
64
85
|
fi
|
|
65
86
|
else
|
|
66
|
-
echo "WARNING: Cannot verify router registration — main
|
|
87
|
+
echo "WARNING: Cannot verify router registration — API main not found at $MAIN_PY"
|
|
67
88
|
WARNINGS=$((WARNINGS + 1))
|
|
68
89
|
fi
|
|
69
|
-
done < <(echo "$FILES" | grep -E "
|
|
90
|
+
done < <(echo "$FILES" | grep -E "^${FORGE_API_ROUTERS_DIR}/.*\\.py$") || true
|
|
70
91
|
|
|
71
92
|
# --- Python Middleware registration check ---
|
|
72
93
|
while read -r f; do
|
|
73
94
|
MIDDLEWARE_NAME=$(basename "$f" .py)
|
|
74
|
-
MAIN_PY="$REPO_ROOT
|
|
95
|
+
MAIN_PY="$REPO_ROOT/${FORGE_API_MAIN}"
|
|
75
96
|
|
|
76
97
|
if [ -f "$MAIN_PY" ]; then
|
|
77
98
|
if grep -q "$MIDDLEWARE_NAME" "$MAIN_PY" 2>/dev/null; then
|
|
78
|
-
echo "OK: Middleware '$MIDDLEWARE_NAME' ($f) — registered in
|
|
99
|
+
echo "OK: Middleware '$MIDDLEWARE_NAME' ($f) — registered in $(basename "$MAIN_PY")"
|
|
79
100
|
else
|
|
80
|
-
echo "WARNING: Middleware '$MIDDLEWARE_NAME' ($f) — not found in
|
|
101
|
+
echo "WARNING: Middleware '$MIDDLEWARE_NAME' ($f) — not found in $(basename "$MAIN_PY"). May not be active."
|
|
81
102
|
WARNINGS=$((WARNINGS + 1))
|
|
82
103
|
fi
|
|
83
104
|
fi
|
|
84
|
-
done < <(echo "$FILES" | grep -E "
|
|
105
|
+
done < <(echo "$FILES" | grep -E "^${FORGE_API_MIDDLEWARE_DIR}/.*\\.py$") || true
|
|
85
106
|
|
|
86
107
|
# --- Shared module import check ---
|
|
87
108
|
while read -r f; do
|
|
88
109
|
MODULE_NAME=$(basename "$f" .py)
|
|
89
110
|
|
|
90
|
-
IMPORTERS=$(grep -rl "$MODULE_NAME" "$REPO_ROOT/
|
|
111
|
+
IMPORTERS=$(grep -rl "$MODULE_NAME" "$REPO_ROOT/${FORGE_API_SERVICES_DIR}/" "$REPO_ROOT/${FORGE_WORKER_DIR}/" 2>/dev/null | head -5)
|
|
91
112
|
if [ -n "$IMPORTERS" ]; then
|
|
92
113
|
echo "OK: Shared module '$MODULE_NAME' ($f) — imported by services"
|
|
93
114
|
else
|
|
94
|
-
echo "WARNING: Shared module '$MODULE_NAME' ($f) — no imports found in
|
|
115
|
+
echo "WARNING: Shared module '$MODULE_NAME' ($f) — no imports found in ${FORGE_API_SERVICES_DIR}/ or ${FORGE_WORKER_DIR}/"
|
|
95
116
|
WARNINGS=$((WARNINGS + 1))
|
|
96
117
|
fi
|
|
97
118
|
done < <(echo "$FILES" | grep -E "^shared/.*\.py$") || true
|
|
@@ -100,14 +121,14 @@ done < <(echo "$FILES" | grep -E "^shared/.*\.py$") || true
|
|
|
100
121
|
while read -r f; do
|
|
101
122
|
COMPONENT_NAME=$(basename "$f" .tsx)
|
|
102
123
|
|
|
103
|
-
IMPORTERS=$(grep -rl "$COMPONENT_NAME" "$REPO_ROOT/
|
|
124
|
+
IMPORTERS=$(grep -rl "$COMPONENT_NAME" "$REPO_ROOT/${FORGE_PAGES_ROOT}/" "$REPO_ROOT/${FORGE_COMPONENTS_DIR}/" 2>/dev/null | grep -v "$f" | head -3)
|
|
104
125
|
if [ -n "$IMPORTERS" ]; then
|
|
105
126
|
echo "OK: Component '$COMPONENT_NAME' ($f) — imported by other files"
|
|
106
127
|
else
|
|
107
128
|
echo "WARNING: Component '$COMPONENT_NAME' ($f) — no imports found. May be unused or new."
|
|
108
129
|
WARNINGS=$((WARNINGS + 1))
|
|
109
130
|
fi
|
|
110
|
-
done < <(echo "$FILES" | grep -E "
|
|
131
|
+
done < <(echo "$FILES" | grep -E "^${FORGE_COMPONENTS_DIR}/.*\\.tsx$") || true
|
|
111
132
|
|
|
112
133
|
# --- Exit code ---
|
|
113
134
|
if [ "$BLOCKING" -gt 0 ]; then
|
|
@@ -24,6 +24,24 @@ DIFF_INPUT="${1:--}"
|
|
|
24
24
|
CHANGED_FILES_INPUT="${2:--}"
|
|
25
25
|
REPO_ROOT="${3:-.}"
|
|
26
26
|
|
|
27
|
+
# --- Secrets backend guard ---
|
|
28
|
+
# This script only applies when the project uses SOPS as its secrets backend.
|
|
29
|
+
# Read the configured backend from the FORGE_SECRETS_BACKEND env var (set by the
|
|
30
|
+
# calling pipeline) or fall back to parsing forge.yaml in the repo root.
|
|
31
|
+
#
|
|
32
|
+
# If the backend is not "sops" (or is unset), exit 0 with a skip message.
|
|
33
|
+
# This is a clean no-op — not a false-pass — so callers can distinguish
|
|
34
|
+
# "SOPS configured and passed" from "SOPS not in use on this project".
|
|
35
|
+
_SECRETS_BACKEND="${FORGE_SECRETS_BACKEND:-}"
|
|
36
|
+
if [ -z "$_SECRETS_BACKEND" ] && [ -f "$REPO_ROOT/forge.yaml" ]; then
|
|
37
|
+
_SECRETS_BACKEND=$(grep -E '^\s*secrets_backend:' "$REPO_ROOT/forge.yaml" \
|
|
38
|
+
| head -1 | sed 's/.*secrets_backend:[[:space:]]*//' | tr -d '"' | tr -d "'" | xargs)
|
|
39
|
+
fi
|
|
40
|
+
if [ "$_SECRETS_BACKEND" != "sops" ]; then
|
|
41
|
+
echo "SKIP: verify-sops-chain — secrets_backend is '${_SECRETS_BACKEND:-none}' (not sops). Configure deploy.secrets_backend: sops in forge.yaml to enable SOPS chain verification."
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
44
|
+
|
|
27
45
|
if [ "$DIFF_INPUT" = "-" ]; then
|
|
28
46
|
DIFF_CONTENT=$(cat)
|
|
29
47
|
else
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
---
|
|
2
|
+
authority: required
|
|
3
|
+
scope: project
|
|
4
|
+
applies_to: [work-on, review-pr, issue, orchestrate, quality-gate]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# DevDocs — Authoritative Knowledge Base
|
|
8
|
+
|
|
9
|
+
This directory contains the authoritative knowledge base for your project. Pipeline agents (ForgeDock commands) read these files as **binding source-of-truth** before acting — not as suggestions.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Purpose
|
|
14
|
+
|
|
15
|
+
DevDocs bridge the gap between what agents know by default and what your project requires. They answer:
|
|
16
|
+
|
|
17
|
+
- How do we use ForgeDock in this project? (`agent/using-forgedock.md`)
|
|
18
|
+
- How do we use GitHub in this project? (`agent/using-github.md`)
|
|
19
|
+
- What templates do we use? (`templates/`)
|
|
20
|
+
- What is this project's tech stack, architecture, and conventions? (`project/`)
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Directory Structure
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
devdocs/
|
|
28
|
+
README.md ← you are here
|
|
29
|
+
agent/
|
|
30
|
+
using-forgedock.md ← ForgeDock pipeline how-to (all phases, lanes, commands)
|
|
31
|
+
using-github.md ← GitHub CLI, branch naming, labels, commit discipline
|
|
32
|
+
templates/
|
|
33
|
+
issue.md ← reusable issue body template
|
|
34
|
+
pull-request.md ← reusable PR body template
|
|
35
|
+
commit-convention.md ← conventional commit reference
|
|
36
|
+
review-finding.md ← review-finding issue template
|
|
37
|
+
project/
|
|
38
|
+
custom-instructions.md ← user binding directives (HIGHEST precedence)
|
|
39
|
+
stack.md ← tech stack description
|
|
40
|
+
architecture.md ← system and domain overview
|
|
41
|
+
conventions.md ← coding standards and patterns
|
|
42
|
+
glossary.md ← domain terms and definitions
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Precedence Rules
|
|
48
|
+
|
|
49
|
+
When a conflict arises between different knowledge sources, agents follow this priority order:
|
|
50
|
+
|
|
51
|
+
| Priority | Source | Description |
|
|
52
|
+
|----------|--------|-------------|
|
|
53
|
+
| 1 (highest) | `project/custom-instructions.md` | Explicit user-authored directives. Always wins. |
|
|
54
|
+
| 2 | Other `project/*.md` files | Authoritative project context (stack, architecture, conventions) |
|
|
55
|
+
| 3 | `agent/*.md` files | Authoritative ForgeDock/GitHub usage instructions |
|
|
56
|
+
| 4 | `templates/*.md` files | Standard templates (lower authority than instructions) |
|
|
57
|
+
| 5 | Agent memory | Recalled knowledge from past sessions |
|
|
58
|
+
| 6 (lowest) | Agent defaults | Built-in behaviors when no other source applies |
|
|
59
|
+
|
|
60
|
+
**Rule**: When `custom-instructions.md` says X, agents do X — even if their training or memory says otherwise.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Authority Levels
|
|
65
|
+
|
|
66
|
+
Each file declares an `authority` field in its frontmatter:
|
|
67
|
+
|
|
68
|
+
| Authority | Meaning |
|
|
69
|
+
|-----------|---------|
|
|
70
|
+
| `required` | Agent MUST read this file before acting in its domain |
|
|
71
|
+
| `recommended` | Agent SHOULD read this file; improves output quality |
|
|
72
|
+
| `reference` | Agent MAY consult this file; informational only |
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## How Agents Use DevDocs
|
|
77
|
+
|
|
78
|
+
1. **Before investigating**: Read `agent/using-forgedock.md` and `project/custom-instructions.md`
|
|
79
|
+
2. **Before building**: Read `agent/using-github.md`, relevant `project/*.md`, applicable `templates/*.md`
|
|
80
|
+
3. **Before reviewing**: Read `project/conventions.md`, `project/stack.md`
|
|
81
|
+
4. **Always**: Treat `project/custom-instructions.md` as the final authority
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Regeneration
|
|
86
|
+
|
|
87
|
+
If this directory was scaffolded by `npx forgedock docs init`, re-running that command will add any new template files introduced in newer ForgeDock versions. It will **not** overwrite files you have edited (idempotent).
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Maintenance Notes
|
|
92
|
+
|
|
93
|
+
- Edit `project/*.md` files to reflect your project's actual stack, architecture, and conventions
|
|
94
|
+
- Edit `project/custom-instructions.md` to add binding directives for your project
|
|
95
|
+
- Do NOT edit `agent/*.md` unless you want to override ForgeDock's default behavior for this project
|
|
96
|
+
- `templates/*.md` files can be customized; changes affect what pipeline agents use as templates
|