@stevenvincentone/intidev-agentloops 0.1.0

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/docs/config.md ADDED
@@ -0,0 +1,88 @@
1
+ # Configuration
2
+
3
+ `agentloop.config.json` controls the project vocabulary.
4
+
5
+ ```json
6
+ {
7
+ "projectName": "IntiDev AgentLoops",
8
+ "description": "Feedback loops for agentic workflows",
9
+ "defaultKind": "bug",
10
+ "ticketKinds": [
11
+ { "kind": "bug", "defaultSeverity": "high", "requiredFields": ["summary"] },
12
+ { "kind": "feature", "defaultSeverity": "medium", "requiredFields": ["summary"] }
13
+ ],
14
+ "queues": [
15
+ { "prefix": "USER", "kinds": ["user_feedback"], "sources": ["user_report"] },
16
+ { "prefix": "DEV", "kinds": ["feature", "task", "investigation", "tech_debt"] },
17
+ { "prefix": "ISSUE", "kinds": ["bug", "incident"], "default": true }
18
+ ],
19
+ "sources": ["user_report", "manual_admin", "agent", "smoke", "ci", "ingestion"]
20
+ }
21
+ ```
22
+
23
+ ### Ticket kinds
24
+
25
+ Each kind can define:
26
+
27
+ - `defaultSeverity`: used when `--severity` is omitted
28
+ - `requiredFields`: enforcement when creating tickets
29
+
30
+ ### Queues and aliases
31
+
32
+ Canonical ids are always stored as `ISSUE-000123`. Each ticket also gets one
33
+ user-facing **queue alias** derived from its `kind` and `source`:
34
+
35
+ - `queues` are evaluated in order; the first whose `sources` includes the
36
+ ticket's source, or whose `kinds` includes its kind, wins.
37
+ - a `sources` match takes that queue's precedence, so a `user_report`-sourced
38
+ bug routes to `USER-000123` even though `bug` is otherwise an `ISSUE` kind.
39
+ - the queue marked `"default": true` is the fallback when nothing matches.
40
+
41
+ With the default config that yields:
42
+
43
+ - `USER-000123` for product/support feedback (kind `user_feedback` or source `user_report`)
44
+ - `DEV-000123` for development work (`feature`, `task`, `investigation`, `tech_debt`)
45
+ - `ISSUE-000123` for defects (`bug`, `incident`) and anything unrouted
46
+
47
+ The canonical `ISSUE-` key keeps downstream systems stable while the alias gives
48
+ each operational queue a recognizable prefix. Aliases and canonical ids share the
49
+ same number, and any of them resolves back to the same ticket on lookup.
50
+
51
+ ### Prior-art scoring (optional)
52
+
53
+ `agentloop related <id>` (and the `agentloop_related` MCP tool) rank related
54
+ tickets from deterministic signals: shared family, shared pattern, shared tags,
55
+ same kind, and title/summary token overlap. Core ships fixed default weights; a
56
+ project can override any of them, or raise the default match threshold:
57
+
58
+ ```json
59
+ {
60
+ "priorArt": {
61
+ "weights": { "family": 3, "pattern": 3, "tag": 2, "kind": 1, "textOverlap": 4 },
62
+ "minScore": 1
63
+ }
64
+ }
65
+ ```
66
+
67
+ Omit `priorArt` entirely to use the core defaults.
68
+
69
+ ### Redaction (optional)
70
+
71
+ By default ticket text is stored unchanged. Add regex rules under
72
+ `redaction.patterns` to scrub sensitive content (PII, secrets) on every write —
73
+ titles, summaries, notes, resolutions, and guard summaries, via both the CLI and
74
+ the MCP write tools:
75
+
76
+ ```json
77
+ {
78
+ "redaction": {
79
+ "patterns": [
80
+ { "name": "email", "pattern": "[\\w.]+@[\\w.]+\\.[a-z]+", "replacement": "[email]" }
81
+ ]
82
+ }
83
+ }
84
+ ```
85
+
86
+ Each rule takes a `pattern` (regex source), optional `flags` (default `g`), and
87
+ optional `replacement` (default `[redacted]`). Library users can instead inject a
88
+ `TicketRedactor` directly: `new AgentLoopStore(cwd, config, { redactor })`.
package/docs/mcp.md ADDED
@@ -0,0 +1,88 @@
1
+ # MCP server
2
+
3
+ AgentLoops exposes a [Model Context Protocol](https://modelcontextprotocol.io)
4
+ server so coding agents can use the ticket ledger directly. Writes are **opt-in**:
5
+ the server is read-only by default and only registers the write tools (create /
6
+ note / workflow / resolve / guard) when started with `--write`.
7
+
8
+ ## Running
9
+
10
+ ```bash
11
+ agentloop mcp # read-only
12
+ agentloop mcp --write # also expose the write tools (alias: --allow-writes)
13
+ ```
14
+
15
+ - Communicates over **stdio** using JSON-RPC. `stdout` carries only the protocol
16
+ stream; human-readable status (including the read-only/read-write mode) is
17
+ written to `stderr`.
18
+ - Reads/writes `.agentloops/state.json` from the **current working directory**, so
19
+ start it from the project root where you ran `agentloop init`.
20
+ - Implemented over the same `AgentLoopStore` as the CLI, so the CLI and MCP
21
+ surfaces always agree.
22
+
23
+ ## Read-only tools
24
+
25
+ Always available; annotated `readOnlyHint: true`.
26
+
27
+ | Tool | Input | Returns |
28
+ | --- | --- | --- |
29
+ | `agentloop_summary` | none | `{ schemaVersion, generatedAt, summary }` — ticket/pattern counts |
30
+ | `agentloop_list` | `status?`, `kind?` | `{ ..., filters, count, tickets }` |
31
+ | `agentloop_show` | `id` | `{ ..., kind: "ticket", ticket }` or `{ ..., kind: "pattern", pattern }` |
32
+ | `agentloop_handoff` | `id` | `{ ..., ticketId, aliases, prompt }` |
33
+ | `agentloop_convergence` | `family?`, `minSources?`, `includeAll?` | `{ ..., filters, summary, patterns }` — patterns whose tickets span ≥ `minSources` (default 2) distinct sources |
34
+ | `agentloop_guard_gaps` | `family?`, `includeWaived?`, `allKinds?` | `{ ..., filters, summary, gaps }` — resolved tickets (ISSUE/USER queues by default) lacking an active regression guard |
35
+ | `agentloop_search_knowledge` | `family?`, `kind?`, `source?`, `tag?`, `query?`, `limit?` | `{ ..., filters, summary, entries }` — how prior resolved tickets were fixed (searchable corpus) |
36
+ | `agentloop_knowledge_gaps` | `family?`, `severity?`, `source?` | `{ ..., filters, summary, gaps }` — resolved tickets whose knowledge is incomplete (missing resolution or verification) |
37
+ | `agentloop_related` | `id`, `minScore?`, `limit?` | `{ ..., ticket, weights, related }` — prior-art lookup ranking tickets by shared family/pattern/tags/kind and title overlap (weights tunable via `config.priorArt`) |
38
+
39
+ ## Write tools
40
+
41
+ Only registered with `--write`. Each returns `{ schemaVersion, generatedAt,
42
+ action, ticket }`, where `ticket` carries the canonical `id` and queue `aliases`.
43
+
44
+ | Tool | Input | Notes |
45
+ | --- | --- | --- |
46
+ | `agentloop_create` | `summary` (required), `title?`, `family?`, `kind?`, `source?`, `severity?`, `confidence?`, `tags?`, `handoff?` | `kind`/`family` default from config; `source` defaults to `agent` |
47
+ | `agentloop_note` | `id`, `body` (required), `type?`, `author?` | `type` defaults to `triage`, `author` to `agent` |
48
+ | `agentloop_workflow` | `id`, `status` (`active` \| `reopened` \| `deferred`), `reason?` | resolve via `agentloop_resolve`, not here |
49
+ | `agentloop_resolve` | `id`, `summary` (required), `verification?`, `guardStatus?`, `guardSummary?` | |
50
+ | `agentloop_guard` | `id`, `guardStatus`, `guardSummary?` | |
51
+
52
+ Notes:
53
+
54
+ - `id` accepts the canonical `ISSUE-NNNNNN` id, any queue alias (`DEV-...`,
55
+ `USER-...`, etc.), or a `PATTERN-NNNNNN` id for `agentloop_show`.
56
+ - `status` (for `agentloop_list`) accepts `triaged | active | resolved | reopened | deferred | all`.
57
+ - `kind`, `severity`, `confidence`, `guardStatus`, and note `type` are validated
58
+ against the configured/known values; invalid inputs return a readable error.
59
+ - Every envelope includes `schemaVersion` (currently `1`) and `generatedAt`.
60
+ Fields are added, not removed, within a schema version.
61
+ - Unknown ids return a tool error (`isError: true`) with a readable message
62
+ rather than failing the protocol call.
63
+ - Writes pass through the configured redactor before storage (no-op by default;
64
+ see `redaction.patterns` in [config](config.md) or inject a `TicketRedactor`).
65
+
66
+ ## Client configuration
67
+
68
+ Claude Code:
69
+
70
+ ```bash
71
+ claude mcp add agentloop -- agentloop mcp
72
+ ```
73
+
74
+ Generic MCP client config:
75
+
76
+ ```json
77
+ {
78
+ "mcpServers": {
79
+ "agentloop": {
80
+ "command": "agentloop",
81
+ "args": ["mcp"]
82
+ }
83
+ }
84
+ }
85
+ ```
86
+
87
+ If you have not installed the package globally, point the client at the built CLI
88
+ instead, e.g. `"command": "node", "args": ["/path/to/dist/cli.js", "mcp"]`.
@@ -0,0 +1,84 @@
1
+ # Storage backends (filesystem & Postgres)
2
+
3
+ `AgentLoopStore` holds the whole ledger in memory and delegates persistence to a
4
+ `StateBackend`, so the same domain logic (tickets, patterns, audits, prior art)
5
+ runs over different stores:
6
+
7
+ | Backend | Use |
8
+ | --- | --- |
9
+ | `FilesystemStateBackend` (default) | JSON at `<cwd>/.agentloops/state.json` |
10
+ | `MemoryStateBackend` | ephemeral; tests and short-lived processes |
11
+ | `PostgresStateBackend` | a relational `ticket_*` schema in Postgres |
12
+
13
+ ```ts
14
+ import { AgentLoopStore, MemoryStateBackend } from "@stevenvincentone/intidev-agentloops";
15
+
16
+ const store = new AgentLoopStore(process.cwd(), config, { backend: new MemoryStateBackend() });
17
+ ```
18
+
19
+ ## Postgres
20
+
21
+ `PostgresStateBackend` brings **no `pg` dependency** — you inject a client that
22
+ matches `pg.Pool`/`pg.Client` (`{ query(text, params) => Promise<{ rows }> }`).
23
+
24
+ ```ts
25
+ import { Pool } from "pg";
26
+ import { AgentLoopStore, PostgresStateBackend } from "@stevenvincentone/intidev-agentloops";
27
+
28
+ const pool = new Pool({ connectionString: process.env.DATABASE_URL });
29
+ const backend = new PostgresStateBackend(pool);
30
+ await backend.migrate(); // optional; load()/save() also create the schema on first use
31
+
32
+ const store = new AgentLoopStore("", config, { backend });
33
+ ```
34
+
35
+ - Saves are **transactional** (whole-snapshot replace), so a failed write never
36
+ leaves a partially-updated ledger. A `pg.Pool` is used via a single dedicated
37
+ connection per operation.
38
+ - Schema is created with `CREATE TABLE IF NOT EXISTS`, so `migrate()` is safe to
39
+ run repeatedly.
40
+
41
+ ## CLI and MCP on Postgres
42
+
43
+ The `agentloop` CLI and `agentloop mcp` server run on Postgres automatically when
44
+ a connection string is configured — no flags needed:
45
+
46
+ ```bash
47
+ export DATABASE_URL=postgres://user:pass@host:5432/db
48
+ agentloop init # creates the ticket_* schema and an empty ledger
49
+ agentloop create --kind bug --summary "..." --source smoke
50
+ agentloop summary
51
+ agentloop mcp # MCP server backed by Postgres
52
+ ```
53
+
54
+ - Connection string precedence: explicit > `DATABASE_URL` env > `config.storage.databaseUrl`.
55
+ Prefer the env var so secrets stay out of committed config.
56
+ - `pg` is an **optional peer dependency** — install it in your project (`npm install pg`)
57
+ when you want the Postgres backend. Filesystem users need nothing extra; if a
58
+ Postgres URL is set but `pg` is missing, the CLI prints an actionable error.
59
+ - One-shot commands open and **close** the pool so the process exits cleanly; the
60
+ MCP server holds the pool open until its stdin closes.
61
+
62
+ ### Public schema
63
+
64
+ The canonical relational schema is exported as `TICKET_SCHEMA_SQL`:
65
+
66
+ - `loop_meta` — single row of top-level ledger state (project, sequences)
67
+ - `ticket_patterns`, `ticket_pattern_links` — patterns and their members
68
+ - `tickets`, `ticket_aliases`, `ticket_tags`, `ticket_notes`
69
+
70
+ Timestamps are stored as ISO text to keep round-trips identical to the JSON
71
+ backend. `serializeState` / `deserializeRows` are exported pure mappers between
72
+ `LoopState` and these rows.
73
+
74
+ ### Running the Postgres tests
75
+
76
+ The Postgres integration test is skipped unless `DATABASE_URL` is set:
77
+
78
+ ```bash
79
+ docker run -d --name agentloops-pg -e POSTGRES_PASSWORD=postgres \
80
+ -e POSTGRES_DB=agentloops -p 55432:5432 postgres:16
81
+ DATABASE_URL=postgres://postgres:postgres@127.0.0.1:55432/agentloops npm test
82
+ ```
83
+
84
+ CI runs it automatically against a `postgres:16` service container.
package/package.json ADDED
@@ -0,0 +1,88 @@
1
+ {
2
+ "name": "@stevenvincentone/intidev-agentloops",
3
+ "version": "0.1.0",
4
+ "description": "IntiDev AgentLoops - Feedback Loops for Agentic Workflows",
5
+ "license": "MIT",
6
+ "type": "commonjs",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./package.json": "./package.json"
15
+ },
16
+ "bin": {
17
+ "agentloop": "dist/cli.js"
18
+ },
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "cli": "tsx src/cli.ts",
22
+ "demo": "tsx scripts/demo-seed.ts",
23
+ "test": "tsx --test test/*.test.ts",
24
+ "start": "npm run cli --",
25
+ "prepare": "npm run build",
26
+ "prepublishOnly": "npm run typecheck && npm run build && npm test",
27
+ "format": "npx prettier --write \"src/**/*.ts\" \"docs/**/*.md\" \"*.md\"",
28
+ "lint": "npx tsc --noEmit",
29
+ "typecheck": "npx tsc -p tsconfig.tooling.json"
30
+ },
31
+ "keywords": [
32
+ "agentic",
33
+ "issue-tracking",
34
+ "ticketing",
35
+ "feedback-loop",
36
+ "devtool",
37
+ "observability",
38
+ "knowledge-base",
39
+ "guardrails",
40
+ "agent-tools"
41
+ ],
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/StevenVincentOne/IntiDev-AgentLoops.git"
45
+ },
46
+ "homepage": "https://github.com/StevenVincentOne/IntiDev-AgentLoops#readme",
47
+ "bugs": {
48
+ "url": "https://github.com/StevenVincentOne/IntiDev-AgentLoops/issues"
49
+ },
50
+ "author": {
51
+ "name": "Inti / Steven Vincent"
52
+ },
53
+ "engines": {
54
+ "node": ">=20"
55
+ },
56
+ "publishConfig": {
57
+ "access": "public"
58
+ },
59
+ "devDependencies": {
60
+ "@types/node": "^22.7.4",
61
+ "@types/pg": "^8.11.10",
62
+ "pg": "^8.13.1",
63
+ "prettier": "^3.3.3",
64
+ "tsx": "^4.19.1",
65
+ "typescript": "^5.6.3"
66
+ },
67
+ "files": [
68
+ "dist/**/*.js",
69
+ "dist/**/*.d.ts",
70
+ "README.md",
71
+ "LICENSE",
72
+ "CHANGELOG.md",
73
+ "docs/*.md",
74
+ "agentloop.config.json.example"
75
+ ],
76
+ "dependencies": {
77
+ "@modelcontextprotocol/sdk": "^1.29.0",
78
+ "zod": "^4.4.3"
79
+ },
80
+ "peerDependencies": {
81
+ "pg": "^8.0.0"
82
+ },
83
+ "peerDependenciesMeta": {
84
+ "pg": {
85
+ "optional": true
86
+ }
87
+ }
88
+ }