@gaffa-dev/skills 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/README.md +88 -0
- package/package.json +23 -0
- package/skills/gaffa-authoring/SKILL.md +177 -0
- package/skills/gaffa-authoring/references/actions.md +235 -0
- package/skills/gaffa-authoring/templates/async-poll.md +58 -0
- package/skills/gaffa-authoring/templates/schema-extraction.md +72 -0
- package/skills/gaffa-authoring/templates/sync.md +31 -0
- package/skills/gaffa-debug/SKILL.md +161 -0
- package/skills/gaffa-debug/references/failure-classification.md +29 -0
- package/skills/gaffa-debug/templates/rerun-with-capture.md +31 -0
- package/skills/gaffa-find/SKILL.md +159 -0
- package/skills/gaffa-find/templates/loop.md +105 -0
- package/skills/gaffa-support/SKILL.md +145 -0
- package/skills/gaffa-support/agents/openai.yaml +2 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gaffa-support
|
|
3
|
+
description: Use when the user is stuck using the gaffa skills or wants to report a problem. First attempts to resolve it from the current context and the live docs, then, if still unresolved, packages a redacted local report the developer can email to support.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# gaffa support
|
|
8
|
+
|
|
9
|
+
When a developer is stuck, first try to resolve the problem in-session, and only if that fails, package a redacted local report they can email to support.
|
|
10
|
+
The report is the project's feedback signal on how the skills perform in real use.
|
|
11
|
+
The skill runs entirely on the developer's machine: it reads the gaffa docs but never calls the gaffa API, spends no credits, and sends nothing on its own.
|
|
12
|
+
|
|
13
|
+
## Support contact
|
|
14
|
+
|
|
15
|
+
- `SUPPORT_EMAIL` is `support@gaffa.dev`.
|
|
16
|
+
The address the developer emails the report to.
|
|
17
|
+
To change it, edit this value.
|
|
18
|
+
|
|
19
|
+
## Critical gaffa facts (grounding)
|
|
20
|
+
|
|
21
|
+
1. Auth header is `X-API-Key: <key>`.
|
|
22
|
+
Read from `GAFFA_API_KEY` env var.
|
|
23
|
+
Never hard-code.
|
|
24
|
+
2. `POST /v1/browser/requests` is async by default.
|
|
25
|
+
Returns an id.
|
|
26
|
+
Poll `GET /v1/browser/requests/{id}`.
|
|
27
|
+
Opt into sync with `"async": false`.
|
|
28
|
+
3. Max runtime is plan-tiered (1 / 2 / 5 min) for both sync and async.
|
|
29
|
+
Always set `settings.time_limit` explicitly.
|
|
30
|
+
4. `parse_json` is token-priced, so its cost scales with the content parsed rather than being a flat per-call charge.
|
|
31
|
+
Stored `/v1/schemas` extractions run the same `parse_json` action and are priced the same way.
|
|
32
|
+
Check the live docs for the current model and token rates.
|
|
33
|
+
Other actions are deterministically priced.
|
|
34
|
+
5. Request recordings (`settings.record_request: true`) are strongly recommended for `/gaffa-debug`.
|
|
35
|
+
Without one, the skill can only suggest re-running the failing request with recording enabled.
|
|
36
|
+
Plan-tiered retention applies (7 days / 30 days / 3 months).
|
|
37
|
+
|
|
38
|
+
The API base URL is `https://api.gaffa.dev`.
|
|
39
|
+
Every `/v1/...` endpoint is called on that host.
|
|
40
|
+
The documentation and the docs MCP live on `https://gaffa.dev`.
|
|
41
|
+
API responses are wrapped in a top-level `data` object, so read fields as `data.id`, `data.state`, `data.credit_usage`, and `data.actions`.
|
|
42
|
+
A finished request has `data.state` equal to `completed`.
|
|
43
|
+
Each action result is a URL in `data.actions[].output`.
|
|
44
|
+
The gaffa edge rejects some default HTTP-client User-Agents (for example Python `urllib`) with a 403, so emitted code should set an explicit `User-Agent` header.
|
|
45
|
+
curl works with its default User-Agent.
|
|
46
|
+
In the request body, `actions`, `time_limit`, and `record_request` go under `settings`, while `url`, `async`, `max_cache_age`, and `proxy_location` are root-level.
|
|
47
|
+
`time_limit` is in milliseconds.
|
|
48
|
+
The `parse_json` action uses a structured `data_schema` of the form `{name, description, fields: [{type, name, description}]}`, never a flat object and never a `schema` or `prompt` field.
|
|
49
|
+
An optional `instruction` parameter sits beside `data_schema` (not inside it) for extra parsing guidance.
|
|
50
|
+
`/v1/schemas` is an endpoint for reusable stored schemas, not an action type.
|
|
51
|
+
LLM-backed extraction runs through the `parse_json` action, with an inline `data_schema` or a stored `data_schema_id`, and there is no separate schema action type.
|
|
52
|
+
On a large content-rich page, `parse_json` over the full DOM can fail with `action_failed` (verified on Wikipedia), so narrow the input with a `selector` for the region that holds the data, or set `input_token_cap`.
|
|
53
|
+
|
|
54
|
+
## Credential hygiene
|
|
55
|
+
|
|
56
|
+
1. Read `GAFFA_API_KEY` from env only.
|
|
57
|
+
Never hard-code in emitted code.
|
|
58
|
+
Reference it as `${GAFFA_API_KEY}`.
|
|
59
|
+
2. Never echo, log, narrate, or persist the value of `GAFFA_API_KEY`.
|
|
60
|
+
Never put it in a URL or query string.
|
|
61
|
+
3. Before showing a gaffa recording, error trace, or request body to the user, to an LLM judge, or to disk, strip the values of any fields whose names match (case-insensitive, including vendor-prefixed variants like `gaffa_api_key`): `Authorization`, `X-API-Key`, `api_key` (and `apiKey`, `api-key`), `cookie`, `set-cookie`.
|
|
62
|
+
Replace the value with `<REDACTED>`.
|
|
63
|
+
4. If the runtime value of `GAFFA_API_KEY` appears as a substring anywhere in a payload you are about to show or persist, replace it with `<REDACTED>`.
|
|
64
|
+
Only enable this substring scrub when the env value is at least 16 characters long and contains both a digit and a letter.
|
|
65
|
+
Otherwise skip and warn the developer on first invocation that the entropy floor was not met (field-name and prose rules still apply).
|
|
66
|
+
5. Persisted writes (the `/gaffa-find` reasoning log `./.gaffa-find-<timestamp>.log`, and any other on-disk artifact) go through redaction first, then to a tempfile, then atomic-rename to the final path.
|
|
67
|
+
A crash mid-write must not leave a plaintext-secrets file on disk.
|
|
68
|
+
6. If unsure whether a string is a secret, redact it.
|
|
69
|
+
|
|
70
|
+
## Doc-fetching strategy
|
|
71
|
+
|
|
72
|
+
Resolve documentation queries in two tiers, in order.
|
|
73
|
+
|
|
74
|
+
1. Preferred: gaffa docs MCP server at `https://gaffa.dev/docs/~gitbook/mcp`.
|
|
75
|
+
`searchDocumentation` (param `query`) for "how do I do X".
|
|
76
|
+
`getPage` (param `url`) to fetch one page by URL.
|
|
77
|
+
2. Fallback: live HTTP fetch.
|
|
78
|
+
`?ask=` against the docs for narrow lookups, `https://gaffa.dev/docs/llms.txt` for breadth.
|
|
79
|
+
Per-call timeout of 5 seconds.
|
|
80
|
+
|
|
81
|
+
MCP availability probe, once per session, cached, total budget 10 seconds: JSON-RPC `initialize`, then the mandatory `notifications/initialized` notification, then `tools/list` confirming `searchDocumentation` and `getPage` (or at least one).
|
|
82
|
+
Per-call MCP timeout is 5 seconds.
|
|
83
|
+
Two consecutive timeouts demote to live HTTP for the rest of the session, announced once.
|
|
84
|
+
|
|
85
|
+
If both tiers fail, skip the in-session resolution attempt, say the docs are unavailable, and continue to the report so the developer is not left empty-handed.
|
|
86
|
+
Both tiers read from `gaffa.dev`, so note the likely cause: `gaffa.dev` blocked by the environment's egress or proxy policy, separate from `api.gaffa.dev`, which the setup section in the skills README covers.
|
|
87
|
+
|
|
88
|
+
## Phase 1: resolve
|
|
89
|
+
|
|
90
|
+
1. State up front that the skill runs entirely on the machine: it reads only the gaffa docs over the network, makes no gaffa API call, spends no credits, and sends nothing on its own.
|
|
91
|
+
2. If the developer gave no problem statement, ask for one short sentence describing what they were trying to do and what went wrong.
|
|
92
|
+
3. Make one bounded attempt to unstick them: re-read the relevant context already in the conversation, consult the docs via the doc-fetching strategy above, and offer a concrete likely cause and a next step.
|
|
93
|
+
4. If that resolves it, stop.
|
|
94
|
+
Otherwise, or if the developer wants a report regardless, continue to Phase 2.
|
|
95
|
+
|
|
96
|
+
## Phase 2: package a report
|
|
97
|
+
|
|
98
|
+
Gather:
|
|
99
|
+
|
|
100
|
+
- The developer's problem statement.
|
|
101
|
+
- Working-directory artifacts the other skills produce.
|
|
102
|
+
List the working directory first, then read and include every file that matches: the `/gaffa-find` reasoning log `./.gaffa-find-<timestamp>.log`, and any generated gaffa script the developer points to or that the conversation produced.
|
|
103
|
+
Also include any `brq_*` request ids the developer mentions.
|
|
104
|
+
Do not skip an artifact that is present.
|
|
105
|
+
List what you found, and let the developer drop any item before the report is written.
|
|
106
|
+
- A drafted problem description composed from the current context: what was attempted, where it broke, the relevant request ids and environment.
|
|
107
|
+
This is best-effort.
|
|
108
|
+
You can only summarize what is still in the conversation, and after auto-compaction the original turns may be gone, so the on-disk artifacts are the reliable part of the report.
|
|
109
|
+
|
|
110
|
+
Then:
|
|
111
|
+
|
|
112
|
+
- Get one timestamp from the system clock with `date -u +%Y%m%dT%H%M%SZ`.
|
|
113
|
+
Do not invent it.
|
|
114
|
+
Use that value for both the filename and the report's `Generated` line.
|
|
115
|
+
- Redact everything through the credential-hygiene rules above before writing.
|
|
116
|
+
Redaction is best-effort, not a guaranteed scrub: it can miss secrets it does not recognize, such as a key hard-coded as a string literal in a generated script, a token inside a URL, or personal data scraped from a target site.
|
|
117
|
+
Say this plainly so the developer reviews the file before sending it.
|
|
118
|
+
- Write the redacted report to `./gaffa-support-<timestamp>.md` in the working directory through the redaction-then-tempfile-then-atomic-rename path: write to a tempfile in the same directory, then rename it over the final path.
|
|
119
|
+
- Show the report contents inline so the developer can review without opening the file.
|
|
120
|
+
- End with the next action.
|
|
121
|
+
The developer emails the file to `SUPPORT_EMAIL` (`support@gaffa.dev`).
|
|
122
|
+
Give a one-line summary of what the file contains, for example the number of artifacts and the request ids.
|
|
123
|
+
Sending is the developer's manual step.
|
|
124
|
+
Remind them the report sits in their working directory, so they should delete it after sending or add `gaffa-support-*.md` to their `.gitignore`, since it can hold redacted data and scraped content.
|
|
125
|
+
|
|
126
|
+
## Report shape
|
|
127
|
+
|
|
128
|
+
```markdown
|
|
129
|
+
# gaffa skills support report
|
|
130
|
+
|
|
131
|
+
Generated: <timestamp from `date -u +%Y%m%dT%H%M%SZ`>
|
|
132
|
+
|
|
133
|
+
## Problem
|
|
134
|
+
<the developer's problem statement, plus the drafted description>
|
|
135
|
+
|
|
136
|
+
## Environment
|
|
137
|
+
- Skill involved: <gaffa-authoring | gaffa-find | gaffa-debug | unknown>
|
|
138
|
+
- Request ids: <brq_... or none>
|
|
139
|
+
|
|
140
|
+
## What was already tried
|
|
141
|
+
<the Phase 1 resolution attempt and its outcome>
|
|
142
|
+
|
|
143
|
+
## Artifacts
|
|
144
|
+
<for each gathered artifact: its filename, then its redacted contents in a fenced block>
|
|
145
|
+
```
|