forgedock 1.0.21 → 1.0.22

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.
Files changed (44) hide show
  1. package/README.md +134 -80
  2. package/bin/demo.mjs +386 -0
  3. package/bin/forgedock.mjs +357 -30
  4. package/bin/init-detect.mjs +95 -0
  5. package/bin/runner.mjs +780 -0
  6. package/commands/cleanup.md +85 -39
  7. package/commands/deploy-info.md +6 -2
  8. package/commands/forge-stats.md +1 -1
  9. package/commands/optimize.md +1 -1
  10. package/commands/orchestrate.md +320 -26
  11. package/commands/quality-gate.md +91 -49
  12. package/commands/review-pr-agents.md +62 -38
  13. package/commands/review-pr.md +33 -2
  14. package/commands/scope.md +11 -3
  15. package/commands/security-audit.md +24 -16
  16. package/commands/sync-ecosystem.md +2 -2
  17. package/commands/work-on/build/architect.md +47 -3
  18. package/commands/work-on/build/context.md +36 -5
  19. package/commands/work-on/build/validate.md +16 -7
  20. package/commands/work-on/close.md +129 -1
  21. package/commands/work-on/investigate.md +24 -1
  22. package/commands/work-on.md +226 -8
  23. package/docs/site/annotations-explained.md +55 -0
  24. package/docs/site/command-learning-path.md +104 -0
  25. package/docs/site/command-reference.md +3 -0
  26. package/docs/site/getting-started.md +36 -14
  27. package/docs/site/troubleshooting.md +208 -0
  28. package/docs/spec/forge-protocol-v1.md +768 -0
  29. package/examples/forgedock-demo/README.md +113 -0
  30. package/examples/forgedock-demo/bootstrap.sh +125 -0
  31. package/examples/forgedock-demo/issues/01-bug-delete-missing-auth.md +37 -0
  32. package/examples/forgedock-demo/issues/02-feature-filter-notes.md +37 -0
  33. package/examples/forgedock-demo/issues/03-refactor-router-table.md +33 -0
  34. package/examples/forgedock-demo/issues/04-perf-index-lookup.md +35 -0
  35. package/examples/forgedock-demo/issues/05-docs-api-reference.md +39 -0
  36. package/examples/forgedock-demo/labels.json +21 -0
  37. package/examples/forgedock-demo/package.json +16 -0
  38. package/examples/forgedock-demo/scripts/smoke.js +61 -0
  39. package/examples/forgedock-demo/src/auth.js +28 -0
  40. package/examples/forgedock-demo/src/db.js +66 -0
  41. package/examples/forgedock-demo/src/routes/notes.js +64 -0
  42. package/examples/forgedock-demo/src/server.js +79 -0
  43. package/package.json +5 -1
  44. package/templates/forge.yaml.minimal +44 -0
@@ -0,0 +1,64 @@
1
+ // Route handlers for the demo Notes API.
2
+ //
3
+ // Each handler takes (req, res, params) and returns a plain object that the
4
+ // server serializes to JSON. Handlers throw errors with a `statusCode` to
5
+ // signal HTTP error responses.
6
+
7
+ const db = require('../db');
8
+ const { requireToken } = require('../auth');
9
+
10
+ // GET /notes
11
+ // Lists notes. Supports an optional ?where= filter that is passed straight
12
+ // into db.query().
13
+ //
14
+ // >>> DEMO NOTE: forwarding the raw ?where= string into db.query() is the
15
+ // >>> injection surface (see db.js). Issue #2 asks to make this safe.
16
+ function listNotes(req, res, params) {
17
+ const where = params.query.where;
18
+ if (where) {
19
+ return { notes: db.query(where) };
20
+ }
21
+ return { notes: db.all() };
22
+ }
23
+
24
+ // GET /notes/:id
25
+ function getNote(req, res, params) {
26
+ const note = db.findById(params.id);
27
+ if (!note) {
28
+ const err = new Error('Note not found');
29
+ err.statusCode = 404;
30
+ throw err;
31
+ }
32
+ return { note };
33
+ }
34
+
35
+ // POST /notes (protected)
36
+ function createNote(req, res, params) {
37
+ requireToken(req);
38
+ const { title, body, owner } = params.body || {};
39
+ if (!title) {
40
+ const err = new Error('title is required');
41
+ err.statusCode = 400;
42
+ throw err;
43
+ }
44
+ const note = db.insert({ title, body: body || '', owner: owner || 'anonymous' });
45
+ res.statusCode = 201;
46
+ return { note };
47
+ }
48
+
49
+ // DELETE /notes/:id
50
+ //
51
+ // >>> DEMO NOTE: this mutating route is MISSING a requireToken(req) call, so
52
+ // >>> anyone can delete any note. That missing authorization check is the
53
+ // >>> INTENTIONAL flaw that Issue #1 (bug fix) asks you to close.
54
+ function deleteNote(req, res, params) {
55
+ const ok = db.remove(params.id);
56
+ if (!ok) {
57
+ const err = new Error('Note not found');
58
+ err.statusCode = 404;
59
+ throw err;
60
+ }
61
+ return { deleted: Number(params.id) };
62
+ }
63
+
64
+ module.exports = { listNotes, getNote, createNote, deleteNote };
@@ -0,0 +1,79 @@
1
+ // Entry point for the demo Notes API.
2
+ //
3
+ // Uses only Node's built-in `http` module — no Express, no npm install. Run it
4
+ // with `node src/server.js` (or `npm start`). The router below is intentionally
5
+ // small and hand-rolled so the whole codebase stays readable in a few minutes.
6
+
7
+ const http = require('http');
8
+ const { URL } = require('url');
9
+ const routes = require('./routes/notes');
10
+
11
+ const PORT = process.env.PORT || 3000;
12
+
13
+ // Route table: [method, pathRegex, handler]. A `:id` segment is captured.
14
+ const TABLE = [
15
+ ['GET', /^\/notes$/, routes.listNotes],
16
+ ['POST', /^\/notes$/, routes.createNote],
17
+ ['GET', /^\/notes\/(?<id>\d+)$/, routes.getNote],
18
+ ['DELETE', /^\/notes\/(?<id>\d+)$/, routes.deleteNote],
19
+ ];
20
+
21
+ function readBody(req) {
22
+ return new Promise((resolve) => {
23
+ let raw = '';
24
+ req.on('data', (chunk) => {
25
+ raw += chunk;
26
+ });
27
+ req.on('end', () => {
28
+ if (!raw) return resolve({});
29
+ try {
30
+ resolve(JSON.parse(raw));
31
+ } catch {
32
+ resolve({});
33
+ }
34
+ });
35
+ });
36
+ }
37
+
38
+ const server = http.createServer(async (req, res) => {
39
+ res.setHeader('Content-Type', 'application/json');
40
+
41
+ // Health check.
42
+ if (req.method === 'GET' && req.url === '/health') {
43
+ res.statusCode = 200;
44
+ return res.end(JSON.stringify({ status: 'ok' }));
45
+ }
46
+
47
+ const url = new URL(req.url, `http://localhost:${PORT}`);
48
+ const query = Object.fromEntries(url.searchParams.entries());
49
+
50
+ const match = TABLE.find(
51
+ ([method, pattern]) => method === req.method && pattern.test(url.pathname)
52
+ );
53
+
54
+ if (!match) {
55
+ res.statusCode = 404;
56
+ return res.end(JSON.stringify({ error: 'Not found' }));
57
+ }
58
+
59
+ const [, pattern, handler] = match;
60
+ const groups = url.pathname.match(pattern).groups || {};
61
+ const body = req.method === 'POST' ? await readBody(req) : {};
62
+
63
+ try {
64
+ const result = handler(req, res, { ...groups, query, body });
65
+ return res.end(JSON.stringify(result));
66
+ } catch (err) {
67
+ res.statusCode = err.statusCode || 500;
68
+ return res.end(JSON.stringify({ error: err.message }));
69
+ }
70
+ });
71
+
72
+ if (require.main === module) {
73
+ server.listen(PORT, () => {
74
+ // eslint-disable-next-line no-console
75
+ console.log(`Notes API listening on http://localhost:${PORT}`);
76
+ });
77
+ }
78
+
79
+ module.exports = { server };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forgedock",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
4
4
  "description": "Autonomous dev pipeline for Claude Code. GitHub as institutional memory — every issue, PR, and annotation survives context resets and makes the next agent smarter.",
5
5
  "bin": {
6
6
  "forgedock": "bin/forgedock.mjs"
@@ -36,6 +36,7 @@
36
36
  "!bin/tests/",
37
37
  "commands/",
38
38
  "docs/",
39
+ "examples/",
39
40
  "scripts/",
40
41
  "templates/",
41
42
  "LICENSE",
@@ -47,6 +48,9 @@
47
48
  "engines": {
48
49
  "node": ">=18"
49
50
  },
51
+ "optionalDependencies": {
52
+ "@anthropic-ai/sdk": ">=0.30.0"
53
+ },
50
54
  "peerDependencies": {
51
55
  "@anthropic-ai/claude-code": ">=2.0.0"
52
56
  },
@@ -0,0 +1,44 @@
1
+ # forge.yaml — ForgeDock Configuration (minimal)
2
+ #
3
+ # The smallest config that runs the full pipeline. Copy it to your project root:
4
+ #
5
+ # cp forge.yaml.minimal forge.yaml
6
+ #
7
+ # ...or generate one with detected values automatically:
8
+ #
9
+ # npx forgedock init --minimal
10
+ #
11
+ # Only project, paths, and branches are required — everything else is optional
12
+ # and falls back to sensible defaults. Start here and add sections as you need
13
+ # them. See forge.yaml.example and docs/CONFIG.md for the full reference.
14
+ #
15
+ # This mirrors ForgeDock's own real-world config: a handful of lines is enough.
16
+
17
+ # =============================================================================
18
+ # PROJECT (REQUIRED)
19
+ # =============================================================================
20
+
21
+ project:
22
+ name: "My Project"
23
+ owner: "my-github-org"
24
+ repo: "my-repo"
25
+
26
+ # =============================================================================
27
+ # PATHS (REQUIRED)
28
+ # Local paths used for git worktrees. worktree_base defaults to
29
+ # {root}/.claude/worktrees.
30
+ # =============================================================================
31
+
32
+ paths:
33
+ root: "/path/to/my-repo"
34
+ worktree_base: "/path/to/my-repo/.claude/worktrees"
35
+
36
+ # =============================================================================
37
+ # BRANCHES (REQUIRED)
38
+ # Set staging to your default branch if you have no separate staging branch.
39
+ # =============================================================================
40
+
41
+ branches:
42
+ default: "main"
43
+ staging: "staging"
44
+ feature_pattern: "milestone/{slug}"