cleargate 0.8.2 → 0.11.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/CHANGELOG.md +210 -0
- package/README.md +22 -1
- package/dist/MANIFEST.json +276 -31
- package/dist/chunk-HZPJ5QX4.js +459 -0
- package/dist/chunk-HZPJ5QX4.js.map +1 -0
- package/dist/{chunk-OM4FAEA7.js → chunk-Q3BTSXCK.js} +69 -3
- package/dist/chunk-Q3BTSXCK.js.map +1 -0
- package/dist/cli.cjs +2888 -598
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +2481 -619
- package/dist/cli.js.map +1 -1
- package/dist/lib/ledger.cjs +120 -0
- package/dist/lib/ledger.cjs.map +1 -0
- package/dist/lib/ledger.d.cts +64 -0
- package/dist/lib/ledger.d.ts +64 -0
- package/dist/lib/ledger.js +96 -0
- package/dist/lib/ledger.js.map +1 -0
- package/dist/lib/lifecycle-reconcile.cjs +497 -0
- package/dist/lib/lifecycle-reconcile.cjs.map +1 -0
- package/dist/lib/lifecycle-reconcile.d.cts +136 -0
- package/dist/lib/lifecycle-reconcile.d.ts +136 -0
- package/dist/lib/lifecycle-reconcile.js +20 -0
- package/dist/lib/lifecycle-reconcile.js.map +1 -0
- package/dist/templates/cleargate-planning/.claude/agents/architect.md +65 -10
- package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-contradict.md +108 -0
- package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-ingest.md +49 -3
- package/dist/templates/cleargate-planning/.claude/agents/cleargate-wiki-lint.md +6 -1
- package/dist/templates/cleargate-planning/.claude/agents/developer.md +51 -2
- package/dist/templates/cleargate-planning/.claude/agents/devops.md +249 -0
- package/dist/templates/cleargate-planning/.claude/agents/qa.md +91 -1
- package/dist/templates/cleargate-planning/.claude/agents/reporter.md +72 -14
- package/dist/templates/cleargate-planning/.claude/hooks/pre-commit-surface-gate.sh +21 -0
- package/dist/templates/cleargate-planning/.claude/hooks/pre-tool-use-task.sh +148 -0
- package/dist/templates/cleargate-planning/.claude/hooks/session-start.sh +6 -0
- package/dist/templates/cleargate-planning/.claude/hooks/stamp-and-gate.sh +12 -1
- package/dist/templates/cleargate-planning/.claude/hooks/token-ledger.sh +334 -96
- package/dist/templates/cleargate-planning/.claude/settings.json +4 -0
- package/dist/templates/cleargate-planning/.claude/skills/sprint-execution/SKILL.md +644 -0
- package/dist/templates/cleargate-planning/.cleargate/config.example.yml +19 -0
- package/dist/templates/cleargate-planning/.cleargate/knowledge/cleargate-enforcement.md +542 -0
- package/dist/templates/cleargate-planning/.cleargate/knowledge/cleargate-protocol.md +102 -428
- package/dist/templates/cleargate-planning/.cleargate/knowledge/mid-sprint-triage-rubric.md +160 -0
- package/dist/templates/cleargate-planning/.cleargate/knowledge/readiness-gates.md +72 -9
- package/dist/templates/cleargate-planning/.cleargate/knowledge/sprint-closeout-checklist.md +71 -0
- package/dist/templates/cleargate-planning/.cleargate/scripts/assert_story_files.mjs +24 -2
- package/dist/templates/cleargate-planning/.cleargate/scripts/close_sprint.mjs +471 -29
- package/dist/templates/cleargate-planning/.cleargate/scripts/dedupe_frontmatter.mjs +219 -0
- package/dist/templates/cleargate-planning/.cleargate/scripts/gate-checks.json +3 -3
- package/dist/templates/cleargate-planning/.cleargate/scripts/init_sprint.mjs +86 -10
- package/dist/templates/cleargate-planning/.cleargate/scripts/lib/report-filename.mjs +54 -0
- package/dist/templates/cleargate-planning/.cleargate/scripts/prep_doc_refresh.mjs +378 -0
- package/dist/templates/cleargate-planning/.cleargate/scripts/prep_qa_context.mjs +888 -0
- package/dist/templates/cleargate-planning/.cleargate/scripts/run_script.sh +173 -87
- package/dist/templates/cleargate-planning/.cleargate/scripts/sprint_trends.mjs +71 -0
- package/dist/templates/cleargate-planning/.cleargate/scripts/suggest_improvements.mjs +483 -13
- package/dist/templates/cleargate-planning/.cleargate/scripts/test/test_prep_qa_context.sh +482 -0
- package/dist/templates/cleargate-planning/.cleargate/scripts/validate_state.mjs +32 -8
- package/dist/templates/cleargate-planning/.cleargate/scripts/write_dispatch.sh +136 -0
- package/dist/templates/cleargate-planning/.cleargate/templates/Bug.md +27 -1
- package/dist/templates/cleargate-planning/.cleargate/templates/CR.md +35 -1
- package/dist/templates/cleargate-planning/.cleargate/templates/Sprint Plan Template.md +48 -14
- package/dist/templates/cleargate-planning/.cleargate/templates/epic.md +40 -3
- package/dist/templates/cleargate-planning/.cleargate/templates/hotfix.md +53 -0
- package/dist/templates/cleargate-planning/.cleargate/templates/initiative.md +98 -29
- package/dist/templates/cleargate-planning/.cleargate/templates/proposal.md +17 -4
- package/dist/templates/cleargate-planning/.cleargate/templates/sprint_context.md +8 -0
- package/dist/templates/cleargate-planning/.cleargate/templates/sprint_report.md +23 -4
- package/dist/templates/cleargate-planning/.cleargate/templates/story.md +58 -3
- package/dist/templates/cleargate-planning/CLAUDE.md +30 -10
- package/dist/templates/cleargate-planning/MANIFEST.json +276 -31
- package/dist/{whoami-CX7CXJD5.js → whoami-W4U6DPVG.js} +17 -17
- package/dist/whoami-W4U6DPVG.js.map +1 -0
- package/package.json +20 -6
- package/templates/cleargate-planning/.claude/agents/architect.md +65 -10
- package/templates/cleargate-planning/.claude/agents/cleargate-wiki-contradict.md +108 -0
- package/templates/cleargate-planning/.claude/agents/cleargate-wiki-ingest.md +49 -3
- package/templates/cleargate-planning/.claude/agents/cleargate-wiki-lint.md +6 -1
- package/templates/cleargate-planning/.claude/agents/developer.md +51 -2
- package/templates/cleargate-planning/.claude/agents/devops.md +249 -0
- package/templates/cleargate-planning/.claude/agents/qa.md +91 -1
- package/templates/cleargate-planning/.claude/agents/reporter.md +72 -14
- package/templates/cleargate-planning/.claude/hooks/pre-commit-surface-gate.sh +21 -0
- package/templates/cleargate-planning/.claude/hooks/pre-tool-use-task.sh +148 -0
- package/templates/cleargate-planning/.claude/hooks/session-start.sh +6 -0
- package/templates/cleargate-planning/.claude/hooks/stamp-and-gate.sh +12 -1
- package/templates/cleargate-planning/.claude/hooks/token-ledger.sh +334 -96
- package/templates/cleargate-planning/.claude/settings.json +4 -0
- package/templates/cleargate-planning/.claude/skills/sprint-execution/SKILL.md +644 -0
- package/templates/cleargate-planning/.cleargate/config.example.yml +19 -0
- package/templates/cleargate-planning/.cleargate/knowledge/cleargate-enforcement.md +542 -0
- package/templates/cleargate-planning/.cleargate/knowledge/cleargate-protocol.md +102 -428
- package/templates/cleargate-planning/.cleargate/knowledge/mid-sprint-triage-rubric.md +160 -0
- package/templates/cleargate-planning/.cleargate/knowledge/readiness-gates.md +72 -9
- package/templates/cleargate-planning/.cleargate/knowledge/sprint-closeout-checklist.md +71 -0
- package/templates/cleargate-planning/.cleargate/scripts/assert_story_files.mjs +24 -2
- package/templates/cleargate-planning/.cleargate/scripts/close_sprint.mjs +471 -29
- package/templates/cleargate-planning/.cleargate/scripts/dedupe_frontmatter.mjs +219 -0
- package/templates/cleargate-planning/.cleargate/scripts/gate-checks.json +3 -3
- package/templates/cleargate-planning/.cleargate/scripts/init_sprint.mjs +86 -10
- package/templates/cleargate-planning/.cleargate/scripts/lib/report-filename.mjs +54 -0
- package/templates/cleargate-planning/.cleargate/scripts/prep_doc_refresh.mjs +378 -0
- package/templates/cleargate-planning/.cleargate/scripts/prep_qa_context.mjs +888 -0
- package/templates/cleargate-planning/.cleargate/scripts/run_script.sh +173 -87
- package/templates/cleargate-planning/.cleargate/scripts/sprint_trends.mjs +71 -0
- package/templates/cleargate-planning/.cleargate/scripts/suggest_improvements.mjs +483 -13
- package/templates/cleargate-planning/.cleargate/scripts/test/test_prep_qa_context.sh +482 -0
- package/templates/cleargate-planning/.cleargate/scripts/validate_state.mjs +32 -8
- package/templates/cleargate-planning/.cleargate/scripts/write_dispatch.sh +136 -0
- package/templates/cleargate-planning/.cleargate/templates/Bug.md +27 -1
- package/templates/cleargate-planning/.cleargate/templates/CR.md +35 -1
- package/templates/cleargate-planning/.cleargate/templates/Sprint Plan Template.md +48 -14
- package/templates/cleargate-planning/.cleargate/templates/epic.md +40 -3
- package/templates/cleargate-planning/.cleargate/templates/hotfix.md +53 -0
- package/templates/cleargate-planning/.cleargate/templates/initiative.md +98 -29
- package/templates/cleargate-planning/.cleargate/templates/sprint_context.md +8 -0
- package/templates/cleargate-planning/.cleargate/templates/sprint_report.md +23 -4
- package/templates/cleargate-planning/.cleargate/templates/story.md +58 -3
- package/templates/cleargate-planning/CLAUDE.md +30 -10
- package/templates/cleargate-planning/MANIFEST.json +276 -31
- package/dist/chunk-OM4FAEA7.js.map +0 -1
- package/dist/whoami-CX7CXJD5.js.map +0 -1
- package/templates/cleargate-planning/.cleargate/templates/proposal.md +0 -61
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/auth/acquire.ts"],"sourcesContent":["import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { z } from 'zod';\n\nexport const ConfigSchema = z\n .object({\n mcpUrl: z.string().url().optional(),\n profile: z.string().min(1).default('default'),\n logLevel: z.enum(['debug', 'info', 'warn', 'error']).default('info'),\n })\n .strict();\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\n/** Partial raw config used for each layer before merge */\ntype RawConfig = Partial<{\n mcpUrl: string | undefined;\n profile: string | undefined;\n logLevel: string | undefined;\n}>;\n\nexport interface LoadConfigOptions {\n flags?: RawConfig;\n env?: NodeJS.ProcessEnv;\n configPath?: string;\n}\n\n/**\n * Synchronously loads and merges config from all layers:\n * flags > env > config file > zod defaults\n */\nexport function loadConfig(opts: LoadConfigOptions = {}): Config {\n const {\n flags = {},\n env = process.env,\n configPath,\n } = opts;\n\n // Resolve config file path\n const resolvedConfigPath =\n configPath ??\n (() => {\n const home = os.homedir();\n if (!home) return null;\n return path.join(home, '.cleargate', 'config.json');\n })();\n\n // Layer: file\n let fileLayer: RawConfig = {};\n if (resolvedConfigPath) {\n try {\n const raw = fs.readFileSync(resolvedConfigPath, 'utf8');\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new Error(\n `Failed to parse config file at ${resolvedConfigPath}: invalid JSON`,\n );\n }\n // Validate file contents strictly (unknown keys will throw here)\n const fileResult = ConfigSchema.safeParse(parsed);\n if (!fileResult.success) {\n throw new Error(\n `Invalid config file at ${resolvedConfigPath}: ${fileResult.error.message}`,\n );\n }\n fileLayer = fileResult.data;\n } catch (err) {\n // Re-throw parse/validation errors; silently skip only ENOENT\n if (\n err instanceof Error &&\n 'code' in err &&\n (err as NodeJS.ErrnoException).code === 'ENOENT'\n ) {\n // file doesn't exist — skip silently\n } else {\n throw err;\n }\n }\n }\n\n // Layer: env\n const envLayer: RawConfig = {};\n if (env['CLEARGATE_MCP_URL']) {\n envLayer.mcpUrl = env['CLEARGATE_MCP_URL'];\n }\n if (env['CLEARGATE_PROFILE']) {\n envLayer.profile = env['CLEARGATE_PROFILE'];\n }\n if (env['CLEARGATE_LOG_LEVEL']) {\n envLayer.logLevel = env['CLEARGATE_LOG_LEVEL'];\n }\n\n // Merge: flags > env > file (start from {} so zod defaults fill in missing fields)\n const merged: Record<string, unknown> = {\n ...fileLayer,\n ...envLayer,\n ...(flags.mcpUrl !== undefined ? { mcpUrl: flags.mcpUrl } : {}),\n ...(flags.profile !== undefined ? { profile: flags.profile } : {}),\n ...(flags.logLevel !== undefined ? { logLevel: flags.logLevel } : {}),\n };\n\n // Remove undefined values so zod defaults apply properly\n for (const key of Object.keys(merged)) {\n if (merged[key] === undefined) {\n delete merged[key];\n }\n }\n\n const result = ConfigSchema.safeParse(merged);\n if (!result.success) {\n throw new Error(`Config validation failed: ${result.error.message}`);\n }\n\n return result.data;\n}\n\n/**\n * Asserts mcpUrl is present, throws a user-friendly error if not.\n */\nexport function requireMcpUrl(cfg: Config): string {\n if (cfg.mcpUrl === undefined) {\n throw new Error(\n 'mcpUrl not configured. Run `cleargate join <invite-url>` first.',\n );\n }\n return cfg.mcpUrl;\n}\n","/**\n * acquireAccessToken — resolve a short-lived MCP access-token JWT.\n *\n * Resolution order (first success wins):\n * 1. CLEARGATE_MCP_TOKEN env var — CI / dev short-circuit (assumed JWT, not verified locally).\n * 2. In-memory single-flight cache (keyed by `${profile}::${mcpUrl}`) — returns cached token\n * if still valid (expires 60s before access token's `exp` claim).\n * 3. Stored refresh token (keychain/file) + POST /auth/refresh → rotates refresh token, returns access token.\n *\n * Errors surface to caller with a clear message so command handlers can exit cleanly.\n *\n * Lives here (not in mcp-client.ts) because the refresh flow needs TokenStore + mcpUrl and\n * mcp-client.ts is kept thin (just: host, bearer, JSON-RPC).\n */\nimport { createTokenStore } from './factory.js';\nimport type { TokenStore } from './token-store.js';\n\n// ── Single-flight in-memory cache ─────────────────────────────────────────────\n// Process-local; naturally cleared when the Node CLI exits.\n// Key: `${profile}::${mcpUrl}` — R1 mitigation: two profiles in same process never collide.\n// Env-token path (CLEARGATE_MCP_TOKEN) bypasses this cache entirely.\n\nconst CACHE = new Map<string, { accessToken: string; expiresAtMs: number }>();\n\n/** Test seam: clear the acquire cache between tests. */\nexport function __resetAcquireCache(): void {\n CACHE.clear();\n}\n\n/** Decode a JWT payload without verifying the signature (CLI-side only). */\nfunction decodeJwtPayload(token: string): Record<string, unknown> | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) return null;\n const padded = parts[1].replace(/-/g, '+').replace(/_/g, '/');\n const json = Buffer.from(padded, 'base64').toString('utf8');\n return JSON.parse(json) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nexport interface AcquireOptions {\n mcpUrl: string;\n profile: string;\n /** Force a fresh /auth/refresh even if the cache has a valid entry. */\n forceRefresh?: boolean;\n /** Test seam: overrides globalThis.fetch */\n fetch?: typeof globalThis.fetch;\n /** Test seam: overrides createTokenStore */\n createStore?: () => Promise<TokenStore>;\n /** Test seam: overrides process.env lookup */\n env?: NodeJS.ProcessEnv;\n /** Test seam: overrides Date.now() for expiry calculations. */\n now?: () => number;\n}\n\nexport class AcquireError extends Error {\n constructor(\n message: string,\n public readonly code:\n | 'env_token'\n | 'no_stored_token'\n | 'invalid_token'\n | 'token_revoked'\n | 'transport'\n | 'unexpected_status'\n | 'bad_response',\n ) {\n super(message);\n this.name = 'AcquireError';\n }\n}\n\n/**\n * Returns a bearer string suitable for Authorization headers against /mcp and\n * /admin-api. Rotates the stored refresh token on success.\n */\nexport async function acquireAccessToken(opts: AcquireOptions): Promise<string> {\n const env = opts.env ?? process.env;\n const nowFn = opts.now ?? Date.now;\n\n // 1. Env short-circuit — CI / dev / manual paste. Assumed to be a valid JWT.\n // Env tokens are NOT cached — they have no known exp without decoding + the\n // env is set per-invocation in CI anyway.\n const envToken = env['CLEARGATE_MCP_TOKEN'];\n if (envToken && envToken.length > 0) {\n return envToken;\n }\n\n // 2. Single-flight cache check (skip when forceRefresh is set).\n const cacheKey = `${opts.profile}::${opts.mcpUrl}`;\n if (!opts.forceRefresh) {\n const cached = CACHE.get(cacheKey);\n if (cached && nowFn() < cached.expiresAtMs) {\n return cached.accessToken;\n }\n }\n\n // 3. Stored refresh token → POST /auth/refresh.\n const store = await (opts.createStore ?? createTokenStore)();\n const stored = await store.load(opts.profile);\n if (!stored) {\n throw new AcquireError(\n `No stored credentials for profile '${opts.profile}'. Run \\`cleargate join <invite-url>\\` first, or export CLEARGATE_MCP_TOKEN.`,\n 'no_stored_token',\n );\n }\n\n const fetchFn = opts.fetch ?? globalThis.fetch;\n\n let response: Response;\n try {\n response = await fetchFn(`${opts.mcpUrl}/auth/refresh`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ refresh_token: stored }),\n });\n } catch (err) {\n throw new AcquireError(\n `cannot reach ${opts.mcpUrl} (${err instanceof Error ? err.message : String(err)})`,\n 'transport',\n );\n }\n\n if (response.status === 401) {\n const body = (await response.json().catch(() => ({}))) as { error?: string };\n if (body.error === 'token_revoked') {\n throw new AcquireError(\n 'refresh token was revoked. Run `cleargate join <invite-url>` to re-authenticate.',\n 'token_revoked',\n );\n }\n throw new AcquireError(\n 'refresh token is invalid or expired. Run `cleargate join <invite-url>` to re-authenticate.',\n 'invalid_token',\n );\n }\n\n if (!response.ok) {\n throw new AcquireError(`unexpected status ${response.status} from /auth/refresh`, 'unexpected_status');\n }\n\n const body = (await response.json().catch(() => null)) as\n | { access_token?: unknown; refresh_token?: unknown }\n | null;\n if (\n !body ||\n typeof body.access_token !== 'string' ||\n typeof body.refresh_token !== 'string' ||\n body.access_token.length === 0 ||\n body.refresh_token.length === 0\n ) {\n throw new AcquireError('server returned unexpected /auth/refresh response shape', 'bad_response');\n }\n\n // Rotate — store the new refresh token so the next call uses a fresh jti.\n await store.save(opts.profile, body.refresh_token);\n\n const accessToken = body.access_token;\n\n // 4. Cache the new access token (expire 60s before the JWT exp claim).\n const payload = decodeJwtPayload(accessToken);\n const exp = payload?.exp;\n if (typeof exp === 'number' && Number.isFinite(exp)) {\n const expiresAtMs = (exp - 60) * 1000;\n CACHE.set(cacheKey, { accessToken, expiresAtMs });\n }\n // If exp is missing or non-numeric, do NOT cache — next call will re-refresh.\n\n return accessToken;\n}\n"],"mappings":"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","names":["body"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/commands/whoami.ts"],"sourcesContent":["/**\n * cleargate whoami — smoke-test command that proves the stored refresh token\n * can be exchanged for a short-lived MCP access token, decodes the JWT payload\n * (no verification — just introspection), and prints identity fields.\n *\n * This is the first command to exercise the acquireAccessToken flow end-to-end;\n * sync/pull/push will be wired in follow-up stories.\n */\nimport { Buffer } from 'node:buffer';\nimport { loadConfig, requireMcpUrl } from '../config.js';\nimport { acquireAccessToken, AcquireError } from '../auth/acquire.js';\n\nexport interface WhoamiOptions {\n profile: string;\n mcpUrlFlag?: string;\n /** Test seam: replaces globalThis.fetch */\n fetch?: typeof globalThis.fetch;\n stdout?: (s: string) => void;\n stderr?: (s: string) => void;\n exit?: (code: number) => never;\n}\n\nfunction decodeJwtPayload(jwt: string): Record<string, unknown> | null {\n const parts = jwt.split('.');\n if (parts.length !== 3) return null;\n try {\n const json = Buffer.from(parts[1]!, 'base64url').toString('utf8');\n return JSON.parse(json);\n } catch {\n return null;\n }\n}\n\nexport async function whoamiHandler(opts: WhoamiOptions): Promise<void> {\n const stdout = opts.stdout ?? ((s) => process.stdout.write(s));\n const stderr = opts.stderr ?? ((s) => process.stderr.write(s));\n const exit = opts.exit ?? ((c: number): never => process.exit(c));\n\n const cfg = loadConfig({ flags: { profile: opts.profile, mcpUrl: opts.mcpUrlFlag } });\n let mcpUrl: string;\n try {\n mcpUrl = requireMcpUrl(cfg);\n } catch (err) {\n stderr(`cleargate: ${err instanceof Error ? err.message : String(err)}\\n`);\n exit(5);\n return;\n }\n\n let accessToken: string;\n try {\n accessToken = await acquireAccessToken({\n mcpUrl,\n profile: opts.profile,\n fetch: opts.fetch,\n });\n } catch (err) {\n if (err instanceof AcquireError) {\n stderr(`cleargate: ${err.message}\\n`);\n exit(err.code === 'transport' ? 2 : 5);\n return;\n }\n stderr(`cleargate: internal error: ${err instanceof Error ? err.message : String(err)}\\n`);\n exit(99);\n return;\n }\n\n const claims = decodeJwtPayload(accessToken);\n if (!claims) {\n stderr('cleargate: access token received but could not decode payload.\\n');\n exit(7);\n return;\n }\n\n stdout(\n [\n `mcp_url: ${mcpUrl}`,\n `profile: ${opts.profile}`,\n `member_id: ${claims.sub ?? '?'}`,\n `project_id: ${claims.project_id ?? '?'}`,\n `role: ${claims.role ?? '?'}`,\n `expires_at: ${typeof claims.exp === 'number' ? new Date(claims.exp * 1000).toISOString() : '?'}`,\n '',\n ].join('\\n'),\n );\n}\n"],"mappings":";;;;;;;;;;AAQA,SAAS,cAAc;AAcvB,SAAS,iBAAiB,KAA6C;AACrE,QAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,MAAI;AACF,UAAM,OAAO,OAAO,KAAK,MAAM,CAAC,GAAI,WAAW,EAAE,SAAS,MAAM;AAChE,WAAO,KAAK,MAAM,IAAI;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,cAAc,MAAoC;AACtE,QAAM,SAAS,KAAK,WAAW,CAAC,MAAM,QAAQ,OAAO,MAAM,CAAC;AAC5D,QAAM,SAAS,KAAK,WAAW,CAAC,MAAM,QAAQ,OAAO,MAAM,CAAC;AAC5D,QAAM,OAAO,KAAK,SAAS,CAAC,MAAqB,QAAQ,KAAK,CAAC;AAE/D,QAAM,MAAM,WAAW,EAAE,OAAO,EAAE,SAAS,KAAK,SAAS,QAAQ,KAAK,WAAW,EAAE,CAAC;AACpF,MAAI;AACJ,MAAI;AACF,aAAS,cAAc,GAAG;AAAA,EAC5B,SAAS,KAAK;AACZ,WAAO,cAAc,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,CAAI;AACzE,SAAK,CAAC;AACN;AAAA,EACF;AAEA,MAAI;AACJ,MAAI;AACF,kBAAc,MAAM,mBAAmB;AAAA,MACrC;AAAA,MACA,SAAS,KAAK;AAAA,MACd,OAAO,KAAK;AAAA,IACd,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,QAAI,eAAe,cAAc;AAC/B,aAAO,cAAc,IAAI,OAAO;AAAA,CAAI;AACpC,WAAK,IAAI,SAAS,cAAc,IAAI,CAAC;AACrC;AAAA,IACF;AACA,WAAO,8BAA8B,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,CAAI;AACzF,SAAK,EAAE;AACP;AAAA,EACF;AAEA,QAAM,SAAS,iBAAiB,WAAW;AAC3C,MAAI,CAAC,QAAQ;AACX,WAAO,kEAAkE;AACzE,SAAK,CAAC;AACN;AAAA,EACF;AAEA;AAAA,IACE;AAAA,MACE,eAAe,MAAM;AAAA,MACrB,eAAe,KAAK,OAAO;AAAA,MAC3B,eAAe,OAAO,OAAO,GAAG;AAAA,MAChC,eAAe,OAAO,cAAc,GAAG;AAAA,MACvC,eAAe,OAAO,QAAQ,GAAG;AAAA,MACjC,eAAe,OAAO,OAAO,QAAQ,WAAW,IAAI,KAAK,OAAO,MAAM,GAAI,EAAE,YAAY,IAAI,GAAG;AAAA,MAC/F;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AACF;","names":[]}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
<instructions> FOLLOW THIS EXACT STRUCTURE. Output sections in order 1-4.
|
|
2
|
-
YAML Frontmatter: Proposal ID, Status, Author, and the crucial approved boolean.
|
|
3
|
-
§1 Initiative & Context: The "Why" and "What".
|
|
4
|
-
§2 Technical Architecture & Constraints: Architecture constraints, data flow, dependencies.
|
|
5
|
-
§3 Touched Files: Real files that will need modification.
|
|
6
|
-
Output location: .cleargate/delivery/pending-sync/PROPOSAL-{Name}.md
|
|
7
|
-
|
|
8
|
-
Document Hierarchy Position: LEVEL 0 (Proposal → Epic → Story)
|
|
9
|
-
|
|
10
|
-
CRITICAL PHASE GATE: Do NOT generate Epics or Stories, and do NOT invoke cleargate_push_item, until the Human has reviewed this document and manually changed approved: false to approved: true in the frontmatter.
|
|
11
|
-
|
|
12
|
-
Do NOT output these instructions. </instructions>
|
|
13
|
-
|
|
14
|
-
proposal_id: "PROP-{ID}" status: "Draft / In Review / Approved" author: "{AI Agent / Vibe Coder}" approved: false
|
|
15
|
-
created_at: "2026-04-17T00:00:00Z"
|
|
16
|
-
updated_at: "2026-04-17T00:00:00Z"
|
|
17
|
-
created_at_version: "strategy-phase-pre-init"
|
|
18
|
-
updated_at_version: "strategy-phase-pre-init"
|
|
19
|
-
server_pushed_at_version: null
|
|
20
|
-
draft_tokens:
|
|
21
|
-
input: null
|
|
22
|
-
output: null
|
|
23
|
-
cache_read: null
|
|
24
|
-
cache_creation: null
|
|
25
|
-
model: null
|
|
26
|
-
sessions: []
|
|
27
|
-
cached_gate_result:
|
|
28
|
-
pass: null
|
|
29
|
-
failing_criteria: []
|
|
30
|
-
last_gate_check: null
|
|
31
|
-
# Sync attribution. Optional; stamped by `cleargate push` / `cleargate pull`.
|
|
32
|
-
pushed_by: null # set by push: which user pushed
|
|
33
|
-
pushed_at: null # set by push: ISO-8601 timestamp
|
|
34
|
-
last_pulled_by: null # set by pull: which user pulled
|
|
35
|
-
last_pulled_at: null # set by pull: ISO-8601 timestamp
|
|
36
|
-
last_remote_update: null # set by pull: server's last-modified timestamp
|
|
37
|
-
source: "local-authored" # flips to "remote-authored" on intake
|
|
38
|
-
last_synced_status: null # required for conflict-detector; status at last sync
|
|
39
|
-
last_synced_body_sha: null # sha256 of body at last sync
|
|
40
|
-
PROPOSAL-{ID}: {Initiative Name}
|
|
41
|
-
1. Initiative & Context
|
|
42
|
-
1.1 Objective
|
|
43
|
-
{1-2 sentences explaining the high-level goal and business value.}
|
|
44
|
-
|
|
45
|
-
1.2 The "Why"
|
|
46
|
-
{Reason 1}
|
|
47
|
-
{Reason 2}
|
|
48
|
-
2. Technical Architecture & Constraints
|
|
49
|
-
2.1 Dependencies
|
|
50
|
-
{List required external APIs, packages, or systems}
|
|
51
|
-
2.2 System Constraints
|
|
52
|
-
Constraint Details
|
|
53
|
-
Architectural Rules {e.g., Must use purely functional components, etc.}
|
|
54
|
-
Security {e.g., Data must be encrypted at rest.}
|
|
55
|
-
3. Scope Impact (Touched Files & Data)
|
|
56
|
-
3.1 Known Files
|
|
57
|
-
path/to/existing/file.ext - {Explanation of expected change}
|
|
58
|
-
3.2 Expected New Entities
|
|
59
|
-
path/to/new/file.ext - {Explanation of purpose}
|
|
60
|
-
🔒 Approval Gate
|
|
61
|
-
(Vibe Coder: Review this proposal. If the architecture and context are correct, change approved: false to approved: true in the YAML frontmatter. Only then is the AI authorized to proceed with Epic/Story decomposition.)
|