@bendyline/gilde 0.1.16 → 0.1.18
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 +5 -1
- package/authoring/gstack/LICENSE.gstack +21 -0
- package/authoring/gstack/README.md +50 -0
- package/authoring/gstack/evals/cso.json +152 -0
- package/authoring/gstack/evals/design-consultation.json +201 -0
- package/authoring/gstack/evals/document-generate.json +174 -0
- package/authoring/gstack/evals/investigate.json +153 -0
- package/authoring/gstack/evals/office-hours.json +141 -0
- package/authoring/gstack/evals/plan-ceo-review.json +135 -0
- package/authoring/gstack/evals/qa-only.json +376 -0
- package/authoring/gstack/evals/retro.json +191 -0
- package/authoring/gstack/evals/spec.json +162 -0
- package/authoring/gstack/overlays/cso.json +132 -0
- package/authoring/gstack/overlays/design-consultation.json +153 -0
- package/authoring/gstack/overlays/document-generate.json +124 -0
- package/authoring/gstack/overlays/investigate.json +128 -0
- package/authoring/gstack/overlays/office-hours.json +119 -0
- package/authoring/gstack/overlays/plan-ceo-review.json +128 -0
- package/authoring/gstack/overlays/qa-only.json +145 -0
- package/authoring/gstack/overlays/retro.json +132 -0
- package/authoring/gstack/overlays/spec.json +140 -0
- package/authoring/gstack/persona-drafts/cso.about.md +9 -0
- package/authoring/gstack/persona-drafts/design-consultation.about.md +9 -0
- package/authoring/gstack/persona-drafts/office-hours.about.md +9 -0
- package/authoring/gstack/persona-drafts/qa-only.about.md +5 -0
- package/authoring/gstack/persona-drafts/spec.about.md +26 -0
- package/authoring/gstack/snapshots/cso/SKILL.md +1285 -0
- package/authoring/gstack/snapshots/design-consultation/SKILL.md +1230 -0
- package/authoring/gstack/snapshots/document-generate/SKILL.md +1252 -0
- package/authoring/gstack/snapshots/investigate/SKILL.md +1074 -0
- package/authoring/gstack/snapshots/office-hours/SKILL.md +1697 -0
- package/authoring/gstack/snapshots/plan-ceo-review/SKILL.md +1476 -0
- package/authoring/gstack/snapshots/qa-only/SKILL.md +1256 -0
- package/authoring/gstack/snapshots/retro/SKILL.md +1812 -0
- package/authoring/gstack/snapshots/spec/SKILL.md +2359 -0
- package/authoring/gstack/wave.json +103 -0
- package/data/connector-types/gi/github-releases/manifest.json +17 -0
- package/data/connector-types/gi/github-releases/versions/1.0.0/manifest.json +71 -0
- package/data/connector-types/index.json +1 -1
- package/data/craftbook-templates/br/branding-website/versions/1.1.0/craftbook.json +190 -0
- package/data/craftbook-templates/br/branding-website/versions/1.1.0/test.json +164 -0
- package/data/craftbook-templates/br/browser-qa-audit/versions/2.0.0/craftbook.json +358 -0
- package/data/craftbook-templates/br/browser-qa-audit/versions/2.0.0/test.json +376 -0
- package/data/craftbook-templates/ca/careful-mode/versions/1.1.0/craftbook.json +43 -0
- package/data/craftbook-templates/ca/careful-mode/versions/1.1.0/test.json +110 -0
- package/data/craftbook-templates/ca/careful-mode/versions/1.2.0/craftbook.json +43 -0
- package/data/craftbook-templates/ca/careful-mode/versions/1.2.0/test.json +110 -0
- package/data/craftbook-templates/co/content-deck/versions/1.1.0/craftbook.json +185 -0
- package/data/craftbook-templates/co/content-deck/versions/1.1.0/test.json +166 -0
- package/data/craftbook-templates/co/content-deck/versions/1.2.0/craftbook.json +185 -0
- package/data/craftbook-templates/co/content-deck/versions/1.2.0/test.json +169 -0
- package/data/craftbook-templates/co/corpus-email-digest/versions/1.1.0/craftbook.json +189 -0
- package/data/craftbook-templates/co/corpus-email-digest/versions/1.1.0/test.json +182 -0
- package/data/craftbook-templates/co/corpus-email-digest/versions/1.2.0/craftbook.json +189 -0
- package/data/craftbook-templates/co/corpus-email-digest/versions/1.2.0/test.json +187 -0
- package/data/craftbook-templates/de/design-system-consultation/versions/2.0.0/craftbook.json +385 -0
- package/data/craftbook-templates/de/design-system-consultation/versions/2.0.0/test.json +201 -0
- package/data/craftbook-templates/en/engineering-retrospective/versions/2.0.0/craftbook.json +353 -0
- package/data/craftbook-templates/en/engineering-retrospective/versions/2.0.0/test.json +191 -0
- package/data/craftbook-templates/ex/executive-level-review/versions/2.0.0/craftbook.json +347 -0
- package/data/craftbook-templates/ex/executive-level-review/versions/2.0.0/test.json +135 -0
- package/data/craftbook-templates/fr/freeze-scope/versions/1.2.0/craftbook.json +50 -0
- package/data/craftbook-templates/fr/freeze-scope/versions/1.2.0/test.json +131 -0
- package/data/craftbook-templates/fr/freeze-scope/versions/1.3.0/craftbook.json +50 -0
- package/data/craftbook-templates/fr/freeze-scope/versions/1.3.0/test.json +131 -0
- package/data/craftbook-templates/ht/html-arcade-game/versions/1.1.0/craftbook.json +197 -0
- package/data/craftbook-templates/ht/html-arcade-game/versions/1.1.0/test.json +173 -0
- package/data/craftbook-templates/ht/html-arcade-game/versions/1.2.0/craftbook.json +197 -0
- package/data/craftbook-templates/ht/html-arcade-game/versions/1.2.0/test.json +176 -0
- package/data/craftbook-templates/id/idea-office-hours/versions/2.0.0/craftbook.json +333 -0
- package/data/craftbook-templates/id/idea-office-hours/versions/2.0.0/test.json +141 -0
- package/data/craftbook-templates/im/image-set-index/versions/1.1.0/craftbook.json +163 -0
- package/data/craftbook-templates/im/image-set-index/versions/1.1.0/test.json +177 -0
- package/data/craftbook-templates/im/image-set-index/versions/1.2.0/craftbook.json +163 -0
- package/data/craftbook-templates/im/image-set-index/versions/1.2.0/test.json +180 -0
- package/data/craftbook-templates/index.json +1 -1
- package/data/craftbook-templates/po/powerpoint-deck/versions/1.6.0/craftbook.json +257 -0
- package/data/craftbook-templates/po/powerpoint-deck/versions/1.6.0/test.json +225 -0
- package/data/craftbook-templates/re/release-artifact-sanity-check/art.json +13 -0
- package/data/craftbook-templates/re/release-artifact-sanity-check/logo.webp +0 -0
- package/data/craftbook-templates/re/release-artifact-sanity-check/manifest.json +24 -0
- package/data/craftbook-templates/re/release-artifact-sanity-check/versions/1.0.0/craftbook.json +202 -0
- package/data/craftbook-templates/re/release-artifact-sanity-check/versions/1.0.0/test.json +138 -0
- package/data/craftbook-templates/ro/root-cause-investigation/versions/2.0.0/craftbook.json +348 -0
- package/data/craftbook-templates/ro/root-cause-investigation/versions/2.0.0/test.json +153 -0
- package/data/craftbook-templates/se/security-architecture-review/versions/2.0.0/craftbook.json +353 -0
- package/data/craftbook-templates/se/security-architecture-review/versions/2.0.0/test.json +152 -0
- package/data/craftbook-templates/sp/spec-authoring/versions/2.0.0/craftbook.json +391 -0
- package/data/craftbook-templates/sp/spec-authoring/versions/2.0.0/test.json +162 -0
- package/data/craftbook-templates/te/technical-documentation/versions/2.0.0/craftbook.json +343 -0
- package/data/craftbook-templates/te/technical-documentation/versions/2.0.0/test.json +174 -0
- package/data/craftbook-templates/tr/translate-content/versions/1.1.0/craftbook.json +84 -0
- package/data/craftbook-templates/tr/translate-content/versions/1.1.0/test.json +141 -0
- package/package.json +8 -4
- package/schemas/craftbook-test.schema.json +232 -3
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"releasedAt": "2026-08-09T00:00:00Z",
|
|
5
|
+
"sourceRevision": "a3259400a366593e0c909dd9ac3e59752efd2488",
|
|
6
|
+
"basedOn": {
|
|
7
|
+
"name": "gstack",
|
|
8
|
+
"url": "https://github.com/garrytan/gstack"
|
|
9
|
+
},
|
|
10
|
+
"books": [
|
|
11
|
+
{
|
|
12
|
+
"source": "office-hours",
|
|
13
|
+
"id": "idea-office-hours",
|
|
14
|
+
"name": "Idea Office Hours",
|
|
15
|
+
"description": "Pressure-test a product idea with forcing questions before jumping to solutions, then capture the decision in a short design doc — a structured 'office hours' diagnostic.",
|
|
16
|
+
"tags": [
|
|
17
|
+
"product",
|
|
18
|
+
"ideation",
|
|
19
|
+
"planning"
|
|
20
|
+
]
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"source": "investigate",
|
|
24
|
+
"id": "root-cause-investigation",
|
|
25
|
+
"name": "Root-Cause Investigation",
|
|
26
|
+
"description": "Debug systematically: reproduce the failure and find the true root cause before changing any code, then fix and verify. Enforces a no-fix-without-diagnosis discipline.",
|
|
27
|
+
"tags": [
|
|
28
|
+
"debugging",
|
|
29
|
+
"engineering"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"source": "document-generate",
|
|
34
|
+
"id": "technical-documentation",
|
|
35
|
+
"name": "Technical Documentation",
|
|
36
|
+
"description": "Generate a coherent documentation set from a codebase, organized by the Diataxis model (tutorials, how-to guides, reference, explanation), with cross-links and a coverage pass.",
|
|
37
|
+
"tags": [
|
|
38
|
+
"documentation",
|
|
39
|
+
"writing"
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"source": "plan-ceo-review",
|
|
44
|
+
"id": "executive-level-review",
|
|
45
|
+
"name": "Executive-Level Review",
|
|
46
|
+
"description": "A strategic, executive-level review of a plan or scope: challenge the premise, weigh alternatives, and score each dimension before committing — the 'should we even build this' pass.",
|
|
47
|
+
"tags": [
|
|
48
|
+
"review",
|
|
49
|
+
"planning",
|
|
50
|
+
"strategy"
|
|
51
|
+
]
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"source": "spec",
|
|
55
|
+
"id": "spec-authoring",
|
|
56
|
+
"name": "Spec Authoring",
|
|
57
|
+
"description": "Turn a rough intent into a backlog-ready spec: interrogate scope and requirements against the real code, then file a well-formed, unambiguous issue.",
|
|
58
|
+
"tags": [
|
|
59
|
+
"planning",
|
|
60
|
+
"spec"
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"source": "cso",
|
|
65
|
+
"id": "security-architecture-review",
|
|
66
|
+
"name": "Security Architecture Review",
|
|
67
|
+
"description": "A structured security architecture review: walk the stack for secrets, dependencies, auth, and common vulnerability classes, then report findings ranked by severity and confidence.",
|
|
68
|
+
"tags": [
|
|
69
|
+
"security",
|
|
70
|
+
"review"
|
|
71
|
+
]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"source": "design-consultation",
|
|
75
|
+
"id": "design-system-consultation",
|
|
76
|
+
"name": "Design System Consultation",
|
|
77
|
+
"description": "Interview for product context and taste, then propose a full design system — type, color, layout, motion — and capture it as a DESIGN.md with live preview pages.",
|
|
78
|
+
"tags": [
|
|
79
|
+
"design"
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"source": "qa-only",
|
|
84
|
+
"id": "browser-qa-audit",
|
|
85
|
+
"name": "Browser QA Audit",
|
|
86
|
+
"description": "Exercise a running app in a real browser, triage what breaks, and produce a report-only QA findings list with a health score — no code changes.",
|
|
87
|
+
"tags": [
|
|
88
|
+
"qa",
|
|
89
|
+
"testing"
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"source": "retro",
|
|
94
|
+
"id": "engineering-retrospective",
|
|
95
|
+
"name": "Engineering Retrospective",
|
|
96
|
+
"description": "Build a data-grounded engineering retrospective from git history: activity, hotspots, review patterns, and per-person growth notes for a given window.",
|
|
97
|
+
"tags": [
|
|
98
|
+
"retrospective",
|
|
99
|
+
"engineering"
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
]
|
|
103
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"kind": "connector-type",
|
|
4
|
+
"id": "github-releases",
|
|
5
|
+
"name": "GitHub Releases",
|
|
6
|
+
"description": "Mirror GitHub release notes and uploaded release assets into local project files. Public repositories work anonymously; Gezel's GitHub sign-in or an optional token also enables private repositories and draft releases.",
|
|
7
|
+
"tags": [
|
|
8
|
+
"github",
|
|
9
|
+
"releases",
|
|
10
|
+
"artifacts",
|
|
11
|
+
"binaries",
|
|
12
|
+
"native"
|
|
13
|
+
],
|
|
14
|
+
"maintainer": {
|
|
15
|
+
"name": "Gezel"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"releasedAt": "2026-08-09T00:00:00Z",
|
|
5
|
+
"driver": "native",
|
|
6
|
+
"source": {
|
|
7
|
+
"adapterId": "github-releases"
|
|
8
|
+
},
|
|
9
|
+
"configSchema": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"properties": {
|
|
12
|
+
"owner": {
|
|
13
|
+
"type": "string",
|
|
14
|
+
"title": "Repository owner"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "string",
|
|
18
|
+
"title": "Repository name"
|
|
19
|
+
},
|
|
20
|
+
"maxReleases": {
|
|
21
|
+
"type": "integer",
|
|
22
|
+
"title": "Latest releases (blank = all)",
|
|
23
|
+
"minimum": 1,
|
|
24
|
+
"maximum": 10000
|
|
25
|
+
},
|
|
26
|
+
"includeDrafts": {
|
|
27
|
+
"type": "boolean",
|
|
28
|
+
"title": "Include draft releases when signed in",
|
|
29
|
+
"default": true
|
|
30
|
+
},
|
|
31
|
+
"includePrereleases": {
|
|
32
|
+
"type": "boolean",
|
|
33
|
+
"title": "Include prereleases",
|
|
34
|
+
"default": true
|
|
35
|
+
},
|
|
36
|
+
"downloadAssets": {
|
|
37
|
+
"type": "boolean",
|
|
38
|
+
"title": "Download uploaded release assets",
|
|
39
|
+
"default": true
|
|
40
|
+
},
|
|
41
|
+
"assetNamePattern": {
|
|
42
|
+
"type": "string",
|
|
43
|
+
"title": "Asset filename globs (optional, comma-separated)"
|
|
44
|
+
},
|
|
45
|
+
"maxAssetSizeMb": {
|
|
46
|
+
"type": "number",
|
|
47
|
+
"title": "Maximum asset size in MB (blank = unlimited)",
|
|
48
|
+
"exclusiveMinimum": 0
|
|
49
|
+
},
|
|
50
|
+
"apiBaseUrl": {
|
|
51
|
+
"type": "string",
|
|
52
|
+
"title": "GitHub Enterprise API base URL (optional)"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"required": [
|
|
56
|
+
"owner",
|
|
57
|
+
"repository"
|
|
58
|
+
]
|
|
59
|
+
},
|
|
60
|
+
"secretShape": {
|
|
61
|
+
"kind": "apikey",
|
|
62
|
+
"field": "token",
|
|
63
|
+
"label": "GitHub token (optional; uses your GitHub sign-in)",
|
|
64
|
+
"required": false
|
|
65
|
+
},
|
|
66
|
+
"normalize": {
|
|
67
|
+
"kind": "native"
|
|
68
|
+
},
|
|
69
|
+
"completeness": "mirror",
|
|
70
|
+
"notes": "Lists releases through GitHub's REST API and stores one release-notes record per release. Uploaded assets are streamed to disk, checked against GitHub's size and sha256 digest when supplied, and published as file-backed connector attachments without buffering the entire asset in memory. Public repositories work anonymously. For github.com, a per-binding token wins, then Gezel's stored GitHub sign-in, GH_TOKEN/GITHUB_TOKEN, or a signed-in GitHub CLI. Users with push access receive draft releases from GitHub's list-releases endpoint. Optional filters bound the newest release count, prerelease/draft inclusion, asset filename globs, and per-asset size. GitHub-generated source archives are not release assets and are not downloaded."
|
|
71
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"schemaVersion":1,"kind":"connector-type","count":9,"entries":[{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"airtable-records","name":"Airtable Records","description":"Mirror an Airtable table into a searchable corpus — one file per record — via the Airtable API, hosted off-platform through a vendored Prismatic component. Captures the table's current rows each sync.","tags":["airtable","records","spectral"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-08T00:00:00Z","driver":"spectral","configSchema":{"type":"object","properties":{"baseId":{"type":"string","title":"Base ID"},"tableName":{"type":"string","title":"Table name"},"view":{"type":"string","title":"View (optional)"},"filterByFormula":{"type":"string","title":"Filter by formula (optional)"}},"required":["baseId","tableName"]},"secretShape":{"kind":"apikey","field":"apiKey"},"source":{"component":"airtable","action":"listRecords","connectionKey":"personalAccessToken","connectionInput":"airtableConnection","inputs":{"baseId":"$config.baseId","tableName":"$config.tableName","view":"$config.view","filterByFormula":"$config.filterByFormula"},"itemsPath":"$.data"},"normalize":{"kind":"mapping","map":{"id":"$.id","title":"$.fields.Name","timestamp":"$.createdTime","body":"$.fields","frontmatter":{"recordId":"$.id","createdTime":"$.createdTime"}}},"actions":[],"completeness":"mirror","notes":"Personal Access Token connection. Each sync re-fetches every row in the table (no incremental cursor); the writer is content-hash idempotent, so re-syncs are cheap and only changed rows rewrite. Deleted Airtable rows are not pruned from the corpus. `title` maps to the `Name` field (Airtable's usual primary column) and falls back to the record id when absent.","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"mail-imap","name":"Email (IMAP)","description":"Mirror an IMAP mailbox into a normalized, searchable corpus of messages.","tags":["email","native"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-08T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"address":{"type":"string","title":"Email address"},"provider":{"type":"string","const":"imap"},"syncFolders":{"type":"array","title":"Folders to sync","items":{"type":"string"}},"allowedRecipients":{"type":"array","title":"Allowed send recipients","items":{"type":"string"}},"allowedDomains":{"type":"array","title":"Allowed send domains","items":{"type":"string"}}},"required":["address"]},"secretShape":{"kind":"imap"},"source":{"adapterId":"mail-imap"},"normalize":{"kind":"native"},"actions":[{"name":"send","consentScope":"recipient-allowlist"}],"completeness":"mirror","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"github-issues","name":"GitHub Issues","description":"Mirror recent issues from one GitHub repository into searchable project files. Public repositories work without sign-in; add a token for private repositories or higher rate limits.","tags":["github","issues","script"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-13T00:00:00Z","driver":"script","configSchema":{"type":"object","properties":{"owner":{"type":"string","title":"Repository owner"},"repository":{"type":"string","title":"Repository name"},"apiBaseUrl":{"type":"string","title":"API base URL (GitHub Enterprise only)"}},"required":["owner","repository"]},"secretShape":{"kind":"apikey","field":"token","label":"GitHub personal access token","required":false},"source":{"inlineFetch":"import { defineScript, gezel } from '@bendyline/gezel-sdk';\n\nexport const meta = defineScript({\n name: 'github-issues-fetch',\n description: 'Fetches a bounded, incremental window of GitHub repository issues.',\n inputs: {\n cursor: { type: 'json', description: 'Last successfully synced GitHub updated_at value.' },\n config: { type: 'json', description: 'Repository owner, name, and optional API base URL.', required: true },\n },\n outputs: {\n records: { type: 'array', description: 'GitHub issues ready for connector normalization.', itemType: 'object' },\n cursor: { type: 'string', description: 'Newest updated_at value processed.', nullable: true },\n },\n requires: ['network', 'credential:$credential'],\n} as const);\n\ntype Config = { owner?: unknown; repository?: unknown; apiBaseUrl?: unknown };\ntype Issue = Record<string, unknown> & { updated_at?: unknown; pull_request?: unknown };\nconst input = gezel.input as { cursor?: unknown; config?: Config };\nconst config = input.config ?? {};\nconst owner = typeof config.owner === 'string' ? config.owner.trim() : '';\nconst repository = typeof config.repository === 'string' ? config.repository.trim() : '';\nif (!owner || !repository) throw new Error('GitHub owner and repository are required.');\n\nconst apiBaseUrl =\n typeof config.apiBaseUrl === 'string' && config.apiBaseUrl.trim()\n ? config.apiBaseUrl.trim().replace(/\\/+$/, '')\n : 'https://api.github.com';\nlet apiOrigin: string;\ntry {\n const parsed = new URL(apiBaseUrl);\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') throw new Error('bad protocol');\n apiOrigin = parsed.origin;\n} catch {\n throw new Error('GitHub API base URL must be an absolute HTTP or HTTPS URL.');\n}\n\nconst params = new URLSearchParams({\n state: 'all',\n sort: 'updated',\n direction: typeof input.cursor === 'string' ? 'asc' : 'desc',\n per_page: '100',\n});\nif (typeof input.cursor === 'string' && input.cursor) params.set('since', input.cursor);\nlet nextUrl =\n apiBaseUrl + '/repos/' + encodeURIComponent(owner) + '/' + encodeURIComponent(repository) + '/issues?' + params;\nlet nextCursor = typeof input.cursor === 'string' ? input.cursor : null;\nconst records: Issue[] = [];\n\nfunction nextPage(link: string | undefined): string | null {\n if (!link) return null;\n for (const part of link.split(',')) {\n const match = part.match(/<([^>]+)>;\\s*rel=\"next\"/);\n if (match?.[1]) return match[1];\n }\n return null;\n}\n\nfor (let page = 0; page < 5 && nextUrl; page++) {\n const target = new URL(nextUrl);\n if (target.origin !== apiOrigin) throw new Error('GitHub pagination changed origin; refusing to forward the token.');\n const headers = {\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'User-Agent': 'Gezel-GitHub-Issues-Connector',\n };\n let response;\n try {\n response = await gezel.http.authed(target.toString(), {\n credential: '$credential',\n headers,\n });\n } catch (error) {\n if ((error as { code?: string }).code !== 'CREDENTIAL_MISSING') throw error;\n response = await gezel.http.request(target.toString(), { headers });\n }\n if (!response.ok) {\n throw new Error('GitHub issues request failed (' + response.status + '): ' + response.body.slice(0, 240));\n }\n const pageItems = JSON.parse(response.body) as unknown;\n if (!Array.isArray(pageItems)) throw new Error('GitHub returned a non-array issues response.');\n for (const raw of pageItems) {\n if (!raw || typeof raw !== 'object') continue;\n const issue = raw as Issue;\n const updatedAt = typeof issue.updated_at === 'string' ? issue.updated_at : '';\n if (updatedAt && (!nextCursor || updatedAt > nextCursor)) nextCursor = updatedAt;\n if (issue.pull_request) continue;\n const labels = Array.isArray(issue.labels)\n ? issue.labels\n .map((label) =>\n typeof label === 'string'\n ? label\n : label && typeof label === 'object'\n ? String((label as Record<string, unknown>).name ?? '')\n : '',\n )\n .filter(Boolean)\n : [];\n const assignees = Array.isArray(issue.assignees)\n ? issue.assignees\n .map((person) =>\n person && typeof person === 'object'\n ? String((person as Record<string, unknown>).login ?? '')\n : '',\n )\n .filter(Boolean)\n : [];\n records.push({\n ...issue,\n gezel_repository: owner + '/' + repository,\n gezel_labels: labels,\n gezel_assignees: assignees,\n });\n }\n const candidate = nextPage(response.headers.link);\n nextUrl = candidate && new URL(candidate).origin === apiOrigin ? candidate : '';\n}\n\ngezel.output({ records, cursor: nextCursor });\n","idPath":"$.id"},"normalize":{"kind":"mapping","map":{"id":"$.id","title":"$.title","group":"$.gezel_repository","timestamp":"$.updated_at","body":"$.body","frontmatter":{"number":"$.number","state":"$.state","stateReason":"$.state_reason","author":"$.user.login","assignees":"$.gezel_assignees","labels":"$.gezel_labels","milestone":"$.milestone.title","comments":"$.comments","url":"$.html_url","createdAt":"$.created_at","closedAt":"$.closed_at","locked":"$.locked"}}},"actions":[],"completeness":"window","notes":"Uses GitHub's REST list-repository-issues endpoint anonymously for public repositories, or with an optional personal access token for private repositories and higher rate limits. Pull requests are excluded because GitHub's Issues API returns both. The first sync captures up to 500 recently updated issues; later syncs resume from updated_at in oldest-first order so busy repositories catch up over multiple passes. Issue comments are represented by their count but comment bodies are not mirrored in this version.","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"github-wiki","name":"GitHub Wiki","description":"Mirror a repository's wiki pages into searchable project files. Public wikis work anonymously; add a token for private repositories.","tags":["github","wiki","documentation","native"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-13T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"owner":{"type":"string","title":"Repository owner"},"repository":{"type":"string","title":"Repository name"},"host":{"type":"string","title":"GitHub Enterprise host (optional)"}},"required":["owner","repository"]},"secretShape":{"kind":"apikey","field":"token","label":"GitHub personal access token","required":false},"source":{"adapterId":"github-wiki"},"normalize":{"kind":"native"},"actions":[],"completeness":"mirror","notes":"Uses GitHub's separate .wiki.git repository as a read-only transport. Public wikis clone anonymously. An optional personal access token enables private repository wikis. Supported textual wiki markup is mirrored and scanned as untrusted external content; binary files and Git history are not exposed. Changed pages are stored as immutable revisions. Deletions are not currently pruned from the local corpus.","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"mail-gmail","name":"Gmail","description":"Mirror a Gmail mailbox into a normalized, searchable corpus of messages (OAuth).","tags":["email","native","oauth"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-08T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"address":{"type":"string","title":"Email address"},"provider":{"type":"string","const":"gmail"},"syncFolders":{"type":"array","title":"Labels to sync","items":{"type":"string"}},"allowedRecipients":{"type":"array","title":"Allowed send recipients","items":{"type":"string"}},"allowedDomains":{"type":"array","title":"Allowed send domains","items":{"type":"string"}}},"required":["address"]},"secretShape":{"kind":"oauth2","authorizeUrl":"https://accounts.google.com/o/oauth2/v2/auth","tokenUrl":"https://oauth2.googleapis.com/token","scopes":"https://mail.google.com/","clientIdEnv":"GEZEL_GOOGLE_CLIENT_ID","clientSecretEnv":"GEZEL_GOOGLE_CLIENT_SECRET","authParams":{"access_type":"offline","prompt":"consent"}},"source":{"adapterId":"mail-gmail"},"normalize":{"kind":"native"},"actions":[{"name":"send","consentScope":"recipient-allowlist"}],"completeness":"mirror","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"calendar-google","name":"Google Calendar","description":"Mirror Google Calendar events into a normalized, searchable corpus (OAuth). Pairs with Gmail for cross-corpus reports.","tags":["calendar","native","oauth"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-08T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"calendars":{"type":"array","title":"Calendar IDs (blank = all)","items":{"type":"string"}}}},"secretShape":{"kind":"oauth2","authorizeUrl":"https://accounts.google.com/o/oauth2/v2/auth","tokenUrl":"https://oauth2.googleapis.com/token","scopes":"https://www.googleapis.com/auth/calendar.readonly","clientIdEnv":"GEZEL_GOOGLE_CLIENT_ID","clientSecretEnv":"GEZEL_GOOGLE_CLIENT_SECRET","authParams":{"access_type":"offline","prompt":"consent"}},"source":{"adapterId":"calendar-google"},"normalize":{"kind":"native"},"actions":[],"completeness":"mirror","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"linear-issues","name":"Linear Issues","description":"Mirror recent Linear issues into a searchable corpus via Linear's MCP server. A rolling window of recent activity, not full history.","tags":["issues","mcp"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-08T00:00:00Z","driver":"mcp","configSchema":{"type":"object","properties":{}},"secretShape":{"kind":"apikey","field":"Authorization"},"source":{"server":{"kind":"http","transport":"streamable-http","url":"https://mcp.linear.app/mcp","headersFromSecret":{"Authorization":"Bearer $secret"}},"list":{"tool":"list_issues","cursorArg":"updatedAfter","itemsPath":"$.issues","idPath":"$.id","tsPath":"$.updatedAt"},"fetch":{"tool":"get_issue","idArg":"id"}},"normalize":{"kind":"mapping","map":{"id":"$.id","title":"$.title","group":"$.team.name","timestamp":"$.updatedAt","body":"$.description","frontmatter":{"identifier":"$.identifier","state":"$.state.name","assignee":"$.assignee.name","url":"$.url"}}},"actions":[],"completeness":"window","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"mail-microsoft365","name":"Microsoft 365 Mail","description":"Mirror a Microsoft 365 (work/school) mailbox into a normalized, searchable corpus of messages (OAuth).","tags":["email","native","oauth"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-08-09T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"address":{"type":"string","title":"Email address"},"provider":{"type":"string","const":"microsoft365"},"tenant":{"type":"string","const":"organizations"},"syncFolders":{"type":"array","title":"Folders to sync","items":{"type":"string"}},"allowedRecipients":{"type":"array","title":"Allowed send recipients","items":{"type":"string"}},"allowedDomains":{"type":"array","title":"Allowed send domains","items":{"type":"string"}}},"required":["address"]},"secretShape":{"kind":"oauth2","authorizeUrl":"https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize","tokenUrl":"https://login.microsoftonline.com/organizations/oauth2/v2.0/token","scopes":"offline_access https://graph.microsoft.com/Mail.Read https://graph.microsoft.com/Mail.Send","clientIdEnv":"GEZEL_MICROSOFT_CLIENT_ID"},"source":{"adapterId":"mail-microsoft365"},"normalize":{"kind":"native"},"actions":[{"name":"send","consentScope":"recipient-allowlist"}],"completeness":"mirror","notes":"Work/school accounts in the 'organizations' Azure AD tenant. Sending is deny-by-default: only recipients on the binding's allowed recipients/domains lists can be sent to, and night shift defers sends to the outbox for daytime approval.","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"mail-outlook","name":"Outlook.com Mail","description":"Mirror a personal Outlook.com mailbox into a normalized, searchable corpus of messages (OAuth).","tags":["email","native","oauth"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-08-09T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"address":{"type":"string","title":"Email address"},"provider":{"type":"string","const":"outlook"},"tenant":{"type":"string","const":"consumers"},"syncFolders":{"type":"array","title":"Folders to sync","items":{"type":"string"}},"allowedRecipients":{"type":"array","title":"Allowed send recipients","items":{"type":"string"}},"allowedDomains":{"type":"array","title":"Allowed send domains","items":{"type":"string"}}},"required":["address"]},"secretShape":{"kind":"oauth2","authorizeUrl":"https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize","tokenUrl":"https://login.microsoftonline.com/consumers/oauth2/v2.0/token","scopes":"offline_access https://graph.microsoft.com/Mail.Read https://graph.microsoft.com/Mail.Send","clientIdEnv":"GEZEL_MICROSOFT_CLIENT_ID"},"source":{"adapterId":"mail-outlook"},"normalize":{"kind":"native"},"actions":[{"name":"send","consentScope":"recipient-allowlist"}],"completeness":"mirror","notes":"Personal Outlook.com accounts in the 'consumers' tenant. Sending is deny-by-default: only recipients on the binding's allowed recipients/domains lists can be sent to, and night shift defers sends to the outbox for daytime approval.","availableVersions":["1.0.0"]}}]}
|
|
1
|
+
{"schemaVersion":1,"kind":"connector-type","count":10,"entries":[{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"airtable-records","name":"Airtable Records","description":"Mirror an Airtable table into a searchable corpus — one file per record — via the Airtable API, hosted off-platform through a vendored Prismatic component. Captures the table's current rows each sync.","tags":["airtable","records","spectral"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-08T00:00:00Z","driver":"spectral","configSchema":{"type":"object","properties":{"baseId":{"type":"string","title":"Base ID"},"tableName":{"type":"string","title":"Table name"},"view":{"type":"string","title":"View (optional)"},"filterByFormula":{"type":"string","title":"Filter by formula (optional)"}},"required":["baseId","tableName"]},"secretShape":{"kind":"apikey","field":"apiKey"},"source":{"component":"airtable","action":"listRecords","connectionKey":"personalAccessToken","connectionInput":"airtableConnection","inputs":{"baseId":"$config.baseId","tableName":"$config.tableName","view":"$config.view","filterByFormula":"$config.filterByFormula"},"itemsPath":"$.data"},"normalize":{"kind":"mapping","map":{"id":"$.id","title":"$.fields.Name","timestamp":"$.createdTime","body":"$.fields","frontmatter":{"recordId":"$.id","createdTime":"$.createdTime"}}},"actions":[],"completeness":"mirror","notes":"Personal Access Token connection. Each sync re-fetches every row in the table (no incremental cursor); the writer is content-hash idempotent, so re-syncs are cheap and only changed rows rewrite. Deleted Airtable rows are not pruned from the corpus. `title` maps to the `Name` field (Airtable's usual primary column) and falls back to the record id when absent.","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"mail-imap","name":"Email (IMAP)","description":"Mirror an IMAP mailbox into a normalized, searchable corpus of messages.","tags":["email","native"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-08T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"address":{"type":"string","title":"Email address"},"provider":{"type":"string","const":"imap"},"syncFolders":{"type":"array","title":"Folders to sync","items":{"type":"string"}},"allowedRecipients":{"type":"array","title":"Allowed send recipients","items":{"type":"string"}},"allowedDomains":{"type":"array","title":"Allowed send domains","items":{"type":"string"}}},"required":["address"]},"secretShape":{"kind":"imap"},"source":{"adapterId":"mail-imap"},"normalize":{"kind":"native"},"actions":[{"name":"send","consentScope":"recipient-allowlist"}],"completeness":"mirror","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"github-issues","name":"GitHub Issues","description":"Mirror recent issues from one GitHub repository into searchable project files. Public repositories work without sign-in; add a token for private repositories or higher rate limits.","tags":["github","issues","script"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-13T00:00:00Z","driver":"script","configSchema":{"type":"object","properties":{"owner":{"type":"string","title":"Repository owner"},"repository":{"type":"string","title":"Repository name"},"apiBaseUrl":{"type":"string","title":"API base URL (GitHub Enterprise only)"}},"required":["owner","repository"]},"secretShape":{"kind":"apikey","field":"token","label":"GitHub personal access token","required":false},"source":{"inlineFetch":"import { defineScript, gezel } from '@bendyline/gezel-sdk';\n\nexport const meta = defineScript({\n name: 'github-issues-fetch',\n description: 'Fetches a bounded, incremental window of GitHub repository issues.',\n inputs: {\n cursor: { type: 'json', description: 'Last successfully synced GitHub updated_at value.' },\n config: { type: 'json', description: 'Repository owner, name, and optional API base URL.', required: true },\n },\n outputs: {\n records: { type: 'array', description: 'GitHub issues ready for connector normalization.', itemType: 'object' },\n cursor: { type: 'string', description: 'Newest updated_at value processed.', nullable: true },\n },\n requires: ['network', 'credential:$credential'],\n} as const);\n\ntype Config = { owner?: unknown; repository?: unknown; apiBaseUrl?: unknown };\ntype Issue = Record<string, unknown> & { updated_at?: unknown; pull_request?: unknown };\nconst input = gezel.input as { cursor?: unknown; config?: Config };\nconst config = input.config ?? {};\nconst owner = typeof config.owner === 'string' ? config.owner.trim() : '';\nconst repository = typeof config.repository === 'string' ? config.repository.trim() : '';\nif (!owner || !repository) throw new Error('GitHub owner and repository are required.');\n\nconst apiBaseUrl =\n typeof config.apiBaseUrl === 'string' && config.apiBaseUrl.trim()\n ? config.apiBaseUrl.trim().replace(/\\/+$/, '')\n : 'https://api.github.com';\nlet apiOrigin: string;\ntry {\n const parsed = new URL(apiBaseUrl);\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') throw new Error('bad protocol');\n apiOrigin = parsed.origin;\n} catch {\n throw new Error('GitHub API base URL must be an absolute HTTP or HTTPS URL.');\n}\n\nconst params = new URLSearchParams({\n state: 'all',\n sort: 'updated',\n direction: typeof input.cursor === 'string' ? 'asc' : 'desc',\n per_page: '100',\n});\nif (typeof input.cursor === 'string' && input.cursor) params.set('since', input.cursor);\nlet nextUrl =\n apiBaseUrl + '/repos/' + encodeURIComponent(owner) + '/' + encodeURIComponent(repository) + '/issues?' + params;\nlet nextCursor = typeof input.cursor === 'string' ? input.cursor : null;\nconst records: Issue[] = [];\n\nfunction nextPage(link: string | undefined): string | null {\n if (!link) return null;\n for (const part of link.split(',')) {\n const match = part.match(/<([^>]+)>;\\s*rel=\"next\"/);\n if (match?.[1]) return match[1];\n }\n return null;\n}\n\nfor (let page = 0; page < 5 && nextUrl; page++) {\n const target = new URL(nextUrl);\n if (target.origin !== apiOrigin) throw new Error('GitHub pagination changed origin; refusing to forward the token.');\n const headers = {\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'User-Agent': 'Gezel-GitHub-Issues-Connector',\n };\n let response;\n try {\n response = await gezel.http.authed(target.toString(), {\n credential: '$credential',\n headers,\n });\n } catch (error) {\n if ((error as { code?: string }).code !== 'CREDENTIAL_MISSING') throw error;\n response = await gezel.http.request(target.toString(), { headers });\n }\n if (!response.ok) {\n throw new Error('GitHub issues request failed (' + response.status + '): ' + response.body.slice(0, 240));\n }\n const pageItems = JSON.parse(response.body) as unknown;\n if (!Array.isArray(pageItems)) throw new Error('GitHub returned a non-array issues response.');\n for (const raw of pageItems) {\n if (!raw || typeof raw !== 'object') continue;\n const issue = raw as Issue;\n const updatedAt = typeof issue.updated_at === 'string' ? issue.updated_at : '';\n if (updatedAt && (!nextCursor || updatedAt > nextCursor)) nextCursor = updatedAt;\n if (issue.pull_request) continue;\n const labels = Array.isArray(issue.labels)\n ? issue.labels\n .map((label) =>\n typeof label === 'string'\n ? label\n : label && typeof label === 'object'\n ? String((label as Record<string, unknown>).name ?? '')\n : '',\n )\n .filter(Boolean)\n : [];\n const assignees = Array.isArray(issue.assignees)\n ? issue.assignees\n .map((person) =>\n person && typeof person === 'object'\n ? String((person as Record<string, unknown>).login ?? '')\n : '',\n )\n .filter(Boolean)\n : [];\n records.push({\n ...issue,\n gezel_repository: owner + '/' + repository,\n gezel_labels: labels,\n gezel_assignees: assignees,\n });\n }\n const candidate = nextPage(response.headers.link);\n nextUrl = candidate && new URL(candidate).origin === apiOrigin ? candidate : '';\n}\n\ngezel.output({ records, cursor: nextCursor });\n","idPath":"$.id"},"normalize":{"kind":"mapping","map":{"id":"$.id","title":"$.title","group":"$.gezel_repository","timestamp":"$.updated_at","body":"$.body","frontmatter":{"number":"$.number","state":"$.state","stateReason":"$.state_reason","author":"$.user.login","assignees":"$.gezel_assignees","labels":"$.gezel_labels","milestone":"$.milestone.title","comments":"$.comments","url":"$.html_url","createdAt":"$.created_at","closedAt":"$.closed_at","locked":"$.locked"}}},"actions":[],"completeness":"window","notes":"Uses GitHub's REST list-repository-issues endpoint anonymously for public repositories, or with an optional personal access token for private repositories and higher rate limits. Pull requests are excluded because GitHub's Issues API returns both. The first sync captures up to 500 recently updated issues; later syncs resume from updated_at in oldest-first order so busy repositories catch up over multiple passes. Issue comments are represented by their count but comment bodies are not mirrored in this version.","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"github-releases","name":"GitHub Releases","description":"Mirror GitHub release notes and uploaded release assets into local project files. Public repositories work anonymously; Gezel's GitHub sign-in or an optional token also enables private repositories and draft releases.","tags":["github","releases","artifacts","binaries","native"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-08-09T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"owner":{"type":"string","title":"Repository owner"},"repository":{"type":"string","title":"Repository name"},"maxReleases":{"type":"integer","title":"Latest releases (blank = all)","minimum":1,"maximum":10000},"includeDrafts":{"type":"boolean","title":"Include draft releases when signed in","default":true},"includePrereleases":{"type":"boolean","title":"Include prereleases","default":true},"downloadAssets":{"type":"boolean","title":"Download uploaded release assets","default":true},"assetNamePattern":{"type":"string","title":"Asset filename globs (optional, comma-separated)"},"maxAssetSizeMb":{"type":"number","title":"Maximum asset size in MB (blank = unlimited)","exclusiveMinimum":0},"apiBaseUrl":{"type":"string","title":"GitHub Enterprise API base URL (optional)"}},"required":["owner","repository"]},"secretShape":{"kind":"apikey","field":"token","label":"GitHub token (optional; uses your GitHub sign-in)","required":false},"source":{"adapterId":"github-releases"},"normalize":{"kind":"native"},"actions":[],"completeness":"mirror","notes":"Lists releases through GitHub's REST API and stores one release-notes record per release. Uploaded assets are streamed to disk, checked against GitHub's size and sha256 digest when supplied, and published as file-backed connector attachments without buffering the entire asset in memory. Public repositories work anonymously. For github.com, a per-binding token wins, then Gezel's stored GitHub sign-in, GH_TOKEN/GITHUB_TOKEN, or a signed-in GitHub CLI. Users with push access receive draft releases from GitHub's list-releases endpoint. Optional filters bound the newest release count, prerelease/draft inclusion, asset filename globs, and per-asset size. GitHub-generated source archives are not release assets and are not downloaded.","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"github-wiki","name":"GitHub Wiki","description":"Mirror a repository's wiki pages into searchable project files. Public wikis work anonymously; add a token for private repositories.","tags":["github","wiki","documentation","native"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-13T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"owner":{"type":"string","title":"Repository owner"},"repository":{"type":"string","title":"Repository name"},"host":{"type":"string","title":"GitHub Enterprise host (optional)"}},"required":["owner","repository"]},"secretShape":{"kind":"apikey","field":"token","label":"GitHub personal access token","required":false},"source":{"adapterId":"github-wiki"},"normalize":{"kind":"native"},"actions":[],"completeness":"mirror","notes":"Uses GitHub's separate .wiki.git repository as a read-only transport. Public wikis clone anonymously. An optional personal access token enables private repository wikis. Supported textual wiki markup is mirrored and scanned as untrusted external content; binary files and Git history are not exposed. Changed pages are stored as immutable revisions. Deletions are not currently pruned from the local corpus.","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"mail-gmail","name":"Gmail","description":"Mirror a Gmail mailbox into a normalized, searchable corpus of messages (OAuth).","tags":["email","native","oauth"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-08T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"address":{"type":"string","title":"Email address"},"provider":{"type":"string","const":"gmail"},"syncFolders":{"type":"array","title":"Labels to sync","items":{"type":"string"}},"allowedRecipients":{"type":"array","title":"Allowed send recipients","items":{"type":"string"}},"allowedDomains":{"type":"array","title":"Allowed send domains","items":{"type":"string"}}},"required":["address"]},"secretShape":{"kind":"oauth2","authorizeUrl":"https://accounts.google.com/o/oauth2/v2/auth","tokenUrl":"https://oauth2.googleapis.com/token","scopes":"https://mail.google.com/","clientIdEnv":"GEZEL_GOOGLE_CLIENT_ID","clientSecretEnv":"GEZEL_GOOGLE_CLIENT_SECRET","authParams":{"access_type":"offline","prompt":"consent"}},"source":{"adapterId":"mail-gmail"},"normalize":{"kind":"native"},"actions":[{"name":"send","consentScope":"recipient-allowlist"}],"completeness":"mirror","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"calendar-google","name":"Google Calendar","description":"Mirror Google Calendar events into a normalized, searchable corpus (OAuth). Pairs with Gmail for cross-corpus reports.","tags":["calendar","native","oauth"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-08T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"calendars":{"type":"array","title":"Calendar IDs (blank = all)","items":{"type":"string"}}}},"secretShape":{"kind":"oauth2","authorizeUrl":"https://accounts.google.com/o/oauth2/v2/auth","tokenUrl":"https://oauth2.googleapis.com/token","scopes":"https://www.googleapis.com/auth/calendar.readonly","clientIdEnv":"GEZEL_GOOGLE_CLIENT_ID","clientSecretEnv":"GEZEL_GOOGLE_CLIENT_SECRET","authParams":{"access_type":"offline","prompt":"consent"}},"source":{"adapterId":"calendar-google"},"normalize":{"kind":"native"},"actions":[],"completeness":"mirror","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"linear-issues","name":"Linear Issues","description":"Mirror recent Linear issues into a searchable corpus via Linear's MCP server. A rolling window of recent activity, not full history.","tags":["issues","mcp"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-07-08T00:00:00Z","driver":"mcp","configSchema":{"type":"object","properties":{}},"secretShape":{"kind":"apikey","field":"Authorization"},"source":{"server":{"kind":"http","transport":"streamable-http","url":"https://mcp.linear.app/mcp","headersFromSecret":{"Authorization":"Bearer $secret"}},"list":{"tool":"list_issues","cursorArg":"updatedAfter","itemsPath":"$.issues","idPath":"$.id","tsPath":"$.updatedAt"},"fetch":{"tool":"get_issue","idArg":"id"}},"normalize":{"kind":"mapping","map":{"id":"$.id","title":"$.title","group":"$.team.name","timestamp":"$.updatedAt","body":"$.description","frontmatter":{"identifier":"$.identifier","state":"$.state.name","assignee":"$.assignee.name","url":"$.url"}}},"actions":[],"completeness":"window","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"mail-microsoft365","name":"Microsoft 365 Mail","description":"Mirror a Microsoft 365 (work/school) mailbox into a normalized, searchable corpus of messages (OAuth).","tags":["email","native","oauth"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-08-09T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"address":{"type":"string","title":"Email address"},"provider":{"type":"string","const":"microsoft365"},"tenant":{"type":"string","const":"organizations"},"syncFolders":{"type":"array","title":"Folders to sync","items":{"type":"string"}},"allowedRecipients":{"type":"array","title":"Allowed send recipients","items":{"type":"string"}},"allowedDomains":{"type":"array","title":"Allowed send domains","items":{"type":"string"}}},"required":["address"]},"secretShape":{"kind":"oauth2","authorizeUrl":"https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize","tokenUrl":"https://login.microsoftonline.com/organizations/oauth2/v2.0/token","scopes":"offline_access https://graph.microsoft.com/Mail.Read https://graph.microsoft.com/Mail.Send","clientIdEnv":"GEZEL_MICROSOFT_CLIENT_ID"},"source":{"adapterId":"mail-microsoft365"},"normalize":{"kind":"native"},"actions":[{"name":"send","consentScope":"recipient-allowlist"}],"completeness":"mirror","notes":"Work/school accounts in the 'organizations' Azure AD tenant. Sending is deny-by-default: only recipients on the binding's allowed recipients/domains lists can be sent to, and night shift defers sends to the outbox for daytime approval.","availableVersions":["1.0.0"]}},{"manifest":{"schemaVersion":1,"kind":"connector-type","id":"mail-outlook","name":"Outlook.com Mail","description":"Mirror a personal Outlook.com mailbox into a normalized, searchable corpus of messages (OAuth).","tags":["email","native","oauth"],"maintainer":{"name":"Gezel"},"version":"1.0.0","releasedAt":"2026-08-09T00:00:00Z","driver":"native","configSchema":{"type":"object","properties":{"address":{"type":"string","title":"Email address"},"provider":{"type":"string","const":"outlook"},"tenant":{"type":"string","const":"consumers"},"syncFolders":{"type":"array","title":"Folders to sync","items":{"type":"string"}},"allowedRecipients":{"type":"array","title":"Allowed send recipients","items":{"type":"string"}},"allowedDomains":{"type":"array","title":"Allowed send domains","items":{"type":"string"}}},"required":["address"]},"secretShape":{"kind":"oauth2","authorizeUrl":"https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize","tokenUrl":"https://login.microsoftonline.com/consumers/oauth2/v2.0/token","scopes":"offline_access https://graph.microsoft.com/Mail.Read https://graph.microsoft.com/Mail.Send","clientIdEnv":"GEZEL_MICROSOFT_CLIENT_ID"},"source":{"adapterId":"mail-outlook"},"normalize":{"kind":"native"},"actions":[{"name":"send","consentScope":"recipient-allowlist"}],"completeness":"mirror","notes":"Personal Outlook.com accounts in the 'consumers' tenant. Sending is deny-by-default: only recipients on the binding's allowed recipients/domains lists can be sent to, and night shift defers sends to the outbox for daytime approval.","availableVersions":["1.0.0"]}}]}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "branding-website",
|
|
3
|
+
"name": "Branding Website",
|
|
4
|
+
"description": "Build a small brand/marketing website where the visual identity leads. Locks a visual language and mockups FIRST, then writes the copy, then builds the HTML to the locked design — the ordering that makes brand sites feel designed rather than templated.\n\nA gallery craftbook generated from an archetype spec. It runs\n`phase → (per-phase gate) → … → evaluate → (loop) → finish`. Each build\nphase that produces a checkable artifact is followed by a **runtime\ngate-checkpoint** — the runtime verifies the artifact and routes with no\nmodel turn, looping back to redo the phase on a miss. The final `evaluate`\nstep holds a static deliverable gate plus a reviewer QA pass. What it adds\nover the generic `build-loop`: a specialist role per phase, a\ndomain-correct ordering, and a concrete per-phase quality bar.\n\nDeliverables marked \"artifact\" land in the project's artifacts drawer (`write_artifact` / `read_artifact`), not the shipped workspace — review output is not product source.\n\nPhases:\n\n1. Brand & visual design (visual-designer) — visual language + mock, BEFORE any HTML → gated on artifact `design/brand-system.md` (markdown-notes)\n2. Copywriting (copywriter) — headlines + section copy to the brand voice → gated on artifact `copy/site-copy.md` (markdown-notes)\n3. Build (developer) — implement index.html to the locked design + copy → gated on `index.html` (html-marketing-site)\n\nThe gates never advance with an unmet criterion, and loop back to the\nowning phase to fix named gaps.\n",
|
|
5
|
+
"entryStepId": "brand-design",
|
|
6
|
+
"triggers": [
|
|
7
|
+
"branding website",
|
|
8
|
+
"landing page",
|
|
9
|
+
"marketing site",
|
|
10
|
+
"brand site"
|
|
11
|
+
],
|
|
12
|
+
"steps": [
|
|
13
|
+
{
|
|
14
|
+
"id": "brand-design",
|
|
15
|
+
"name": "Brand & visual design",
|
|
16
|
+
"description": "visual language + mock, BEFORE any HTML",
|
|
17
|
+
"prompt": "Lock the visual language before a line of HTML exists. Decide: palette (with exact hex values), type pairing using system-safe fonts, spacing/scale, hero treatment, and responsive section order. Produce an ASCII/markdown wireframe of each section (hero, value props, proof or fit, CTA, footer). Write an **acceptance-criteria checklist** that includes the brand rules (\"headings use <font>\", \"palette is exactly <hex list>\", \"hero matches the mock\"). Save the full system, wireframe, and checklist to artifact `design/brand-system.md` with `write_artifact`; note the path in task notes. No HTML yet.",
|
|
18
|
+
"suggestedRole": "visual-designer",
|
|
19
|
+
"advanceWhen": {
|
|
20
|
+
"file": "design/brand-system.md",
|
|
21
|
+
"minBytes": 1,
|
|
22
|
+
"sniff": "nonempty",
|
|
23
|
+
"artifact": true
|
|
24
|
+
},
|
|
25
|
+
"gate": {
|
|
26
|
+
"at": "completion",
|
|
27
|
+
"checks": [
|
|
28
|
+
{
|
|
29
|
+
"kind": "minBytes",
|
|
30
|
+
"file": "design/brand-system.md",
|
|
31
|
+
"bytes": 800,
|
|
32
|
+
"artifact": true
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"kind": "sniff",
|
|
36
|
+
"file": "design/brand-system.md",
|
|
37
|
+
"sniff": "nonempty",
|
|
38
|
+
"artifact": true
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"kind": "contains",
|
|
42
|
+
"file": "design/brand-system.md",
|
|
43
|
+
"pattern": "#[0-9a-f]{6}",
|
|
44
|
+
"flags": "i",
|
|
45
|
+
"label": "exact palette",
|
|
46
|
+
"artifact": true
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"kind": "contains",
|
|
50
|
+
"file": "design/brand-system.md",
|
|
51
|
+
"pattern": "hero[\\s\\S]*(?:value|benefit)[\\s\\S]*(?:CTA|call.to.action)[\\s\\S]*footer",
|
|
52
|
+
"flags": "i",
|
|
53
|
+
"label": "section wireframe",
|
|
54
|
+
"artifact": true
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
"onReject": "brand-design",
|
|
58
|
+
"maxAttempts": 3
|
|
59
|
+
},
|
|
60
|
+
"next": "copy"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "copy",
|
|
64
|
+
"name": "Copywriting",
|
|
65
|
+
"description": "headlines + section copy to the brand voice",
|
|
66
|
+
"prompt": "Read artifact `design/brand-system.md` with `read_artifact`. Write the approved words: headline, subhead, three value-prop blurbs, proof or fit copy, CTA label, and footer. Match the named brand voice and keep it tight — marketing copy, not paragraphs. Save the complete section-keyed copy to artifact `copy/site-copy.md` with `write_artifact`; note the path in task notes so the build phase can drop it straight in.",
|
|
67
|
+
"suggestedRole": "copywriter",
|
|
68
|
+
"advanceWhen": {
|
|
69
|
+
"file": "copy/site-copy.md",
|
|
70
|
+
"minBytes": 1,
|
|
71
|
+
"sniff": "nonempty",
|
|
72
|
+
"artifact": true
|
|
73
|
+
},
|
|
74
|
+
"gate": {
|
|
75
|
+
"at": "completion",
|
|
76
|
+
"checks": [
|
|
77
|
+
{
|
|
78
|
+
"kind": "minBytes",
|
|
79
|
+
"file": "copy/site-copy.md",
|
|
80
|
+
"bytes": 450,
|
|
81
|
+
"artifact": true
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"kind": "sniff",
|
|
85
|
+
"file": "copy/site-copy.md",
|
|
86
|
+
"sniff": "nonempty",
|
|
87
|
+
"artifact": true
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"kind": "contains",
|
|
91
|
+
"file": "copy/site-copy.md",
|
|
92
|
+
"pattern": "headline|hero",
|
|
93
|
+
"flags": "i",
|
|
94
|
+
"label": "hero copy",
|
|
95
|
+
"artifact": true
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"kind": "contains",
|
|
99
|
+
"file": "copy/site-copy.md",
|
|
100
|
+
"pattern": "CTA|call.to.action",
|
|
101
|
+
"flags": "i",
|
|
102
|
+
"label": "call to action",
|
|
103
|
+
"artifact": true
|
|
104
|
+
}
|
|
105
|
+
],
|
|
106
|
+
"onReject": "copy",
|
|
107
|
+
"maxAttempts": 3
|
|
108
|
+
},
|
|
109
|
+
"next": "build"
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
"id": "build",
|
|
113
|
+
"name": "Build",
|
|
114
|
+
"description": "implement index.html to the locked design + copy",
|
|
115
|
+
"prompt": "Read artifacts `design/brand-system.md` and `copy/site-copy.md` with `read_artifact`. Implement workspace `index.html` with `write_file` (inline CSS) to the locked visual language and approved copy — do not redesign in code. Honor the exact palette, type, and section order from the mock; include viewport metadata, semantic sections, a working primary CTA, and a footer. Make it responsive and self-contained with no external assets. On a loop-back, fix only the named gaps. `write_task_note` the workspace path and which criteria now pass.",
|
|
116
|
+
"suggestedRole": "developer",
|
|
117
|
+
"advanceWhen": {
|
|
118
|
+
"file": "index.html",
|
|
119
|
+
"minBytes": 1,
|
|
120
|
+
"sniff": "html-complete"
|
|
121
|
+
},
|
|
122
|
+
"gate": {
|
|
123
|
+
"at": "completion",
|
|
124
|
+
"checks": [
|
|
125
|
+
{
|
|
126
|
+
"kind": "minBytes",
|
|
127
|
+
"file": "index.html",
|
|
128
|
+
"bytes": 3200
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"kind": "htmlLint",
|
|
132
|
+
"file": "index.html"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"kind": "contains",
|
|
136
|
+
"file": "index.html",
|
|
137
|
+
"pattern": "<meta[^>]+name=[\"']viewport[\"']",
|
|
138
|
+
"flags": "i",
|
|
139
|
+
"label": "responsive viewport"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"kind": "contains",
|
|
143
|
+
"file": "index.html",
|
|
144
|
+
"pattern": "<footer\\b",
|
|
145
|
+
"flags": "i",
|
|
146
|
+
"label": "footer"
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
"scripts": [
|
|
150
|
+
{
|
|
151
|
+
"name": "checkHtmlComplete",
|
|
152
|
+
"scope": "standard",
|
|
153
|
+
"inputs": {
|
|
154
|
+
"file": "index.html"
|
|
155
|
+
}
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "checkCssMinBytes",
|
|
159
|
+
"scope": "standard",
|
|
160
|
+
"inputs": {
|
|
161
|
+
"file": "index.html",
|
|
162
|
+
"minBytes": 600
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
],
|
|
166
|
+
"onReject": "build",
|
|
167
|
+
"maxAttempts": 4
|
|
168
|
+
},
|
|
169
|
+
"next": "evaluate"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
"id": "evaluate",
|
|
173
|
+
"name": "Evaluate",
|
|
174
|
+
"description": "Grade the deliverable against every acceptance criterion. All pass → finish; any fail → loop back and fix the gap.",
|
|
175
|
+
"prompt": "Read workspace `index.html` with `read_file` and compare it with artifacts `design/brand-system.md` and `copy/site-copy.md` via `read_artifact`. Check the brand acceptance criteria specifically: does the palette match the locked hex list, the type match, the responsive section order match the mock, and the copy match what was approved? Render desktop and narrow layouts if you can. A site that works but ignores the locked visual language FAILS — loop back to build.\n\nThen route — this is the whole point of the loop:\n\n- **Every criterion PASSES →** call `advance_task_step({ ref, stepId: \"evaluate\", next: \"finish\" })`.\n- **Any criterion FAILS →** write the specific gaps to notes, then call `advance_task_step({ ref, stepId: \"evaluate\", next: \"build\" })` to loop back. The builder fixes exactly those gaps.\n\nNever route to `finish` while any criterion is unmet. The build phase's completion gate already blocked a grossly-incomplete deliverable; your job is the judgment an automated check cannot make (does it actually work, read well, look right). After ~3 unproductive loops, stop and report DONE_WITH_CONCERNS so the user can step in.",
|
|
176
|
+
"suggestedRole": "reviewer",
|
|
177
|
+
"next": "build"
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"id": "finish",
|
|
181
|
+
"name": "Finish",
|
|
182
|
+
"description": "All acceptance criteria met. Stamp a short summary and report DONE.",
|
|
183
|
+
"prompt": "Every acceptance criterion passed. Write a one-paragraph DONE summary to task notes via `write_task_note`: what was built, the deliverable path(s), and a one-line confirmation that each criterion is met. Then report DONE.",
|
|
184
|
+
"suggestedRole": "developer",
|
|
185
|
+
"terminal": true
|
|
186
|
+
}
|
|
187
|
+
],
|
|
188
|
+
"version": "1.1.0",
|
|
189
|
+
"releasedAt": "2026-08-09T00:00:00Z"
|
|
190
|
+
}
|