← back to Cli Printing Press
docs(skills): document hierarchical resource_type in store-query skeleton (#1484)
f354bc7a651085d8632ea10ee2b43b6ef6b2f330 · 2026-05-15 13:45:45 -0700 · Trevin Chow
* docs(skills): document hierarchical resource_type in store-query skeleton
The store-query RunE skeleton in skills/printing-press/SKILL.md used
SELECT id, data FROM <table> WHERE ... with no guidance on the
resources-table column model. Agents who followed the skeleton against
hierarchical resources synced from /<parents>/{id}/<children> filtered
by the bare child name (resource_type='tasks') and got zero rows
because the press stores those as resource_type='<parent>_<child>'
(projects_tasks for Asana, repos_issues for GitHub, etc).
Replace the placeholder query with a SELECT FROM resources filtered
via IN ('<resource>', '<parent>_<resource>'), and add a paragraph
above the code block explaining the convention so the next agent
doesn't have to debug a zero-rows result. Mention the typed FTS/upsert
tables as the fast path for flat-only resources, and point at
`printing-press dogfood --json` for confirming the actual resource_type
distribution.
Closes #1395
* docs(skills): use <resource> consistently in store-query intro
Greptile noted the intro paragraph used <child> as the placeholder
name while the query directly below used <resource> for the same
substitution target, which could confuse an agent following the
skeleton. Normalize both to <resource>.
Refs #1395
Files touched
M skills/printing-press/SKILL.md
Diff
commit f354bc7a651085d8632ea10ee2b43b6ef6b2f330
Author: Trevin Chow <trevin@trevinchow.com>
Date: Fri May 15 13:45:45 2026 -0700
docs(skills): document hierarchical resource_type in store-query skeleton (#1484)
* docs(skills): document hierarchical resource_type in store-query skeleton
The store-query RunE skeleton in skills/printing-press/SKILL.md used
SELECT id, data FROM <table> WHERE ... with no guidance on the
resources-table column model. Agents who followed the skeleton against
hierarchical resources synced from /<parents>/{id}/<children> filtered
by the bare child name (resource_type='tasks') and got zero rows
because the press stores those as resource_type='<parent>_<child>'
(projects_tasks for Asana, repos_issues for GitHub, etc).
Replace the placeholder query with a SELECT FROM resources filtered
via IN ('<resource>', '<parent>_<resource>'), and add a paragraph
above the code block explaining the convention so the next agent
doesn't have to debug a zero-rows result. Mention the typed FTS/upsert
tables as the fast path for flat-only resources, and point at
`printing-press dogfood --json` for confirming the actual resource_type
distribution.
Closes #1395
* docs(skills): use <resource> consistently in store-query intro
Greptile noted the intro paragraph used <child> as the placeholder
name while the query directly below used <resource> for the same
substitution target, which could confuse an agent following the
skeleton. Normalize both to <resource>.
Refs #1395
---
skills/printing-press/SKILL.md | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/skills/printing-press/SKILL.md b/skills/printing-press/SKILL.md
index df9006a5..089bcc02 100644
--- a/skills/printing-press/SKILL.md
+++ b/skills/printing-press/SKILL.md
@@ -2511,6 +2511,8 @@ RunE: func(cmd *cobra.Command, args []string) error {
**RunE skeleton — store-query shape** (offline data via the local SQLite):
+The generic `resources` table is keyed by `resource_type`. Flat resources synced from `/<resource>` land as `resource_type='<resource>'`. **Hierarchical resources** synced from `/<parents>/{id}/<resource>` land as `resource_type='<parent>_<resource>'` — e.g., `projects_tasks` (Asana), `repos_issues` / `repos_pulls` (GitHub) — *not* the bare `<resource>` name. A novel feature that filters by the bare name returns zero rows against a real DB. Use `IN (...)` to catch both shapes so the same code works whether the API exposes the resource flat or only parent-scoped.
+
```go
// Declare these alongside the cmd literal, before return cmd:
// var dbPath string
@@ -2525,11 +2527,16 @@ RunE: func(cmd *cobra.Command, args []string) error {
return fmt.Errorf("opening database: %w", err)
}
defer db.Close()
- // Replace the query with your aggregation. The store schema mirrors
- // the synced resources; `printing-press dogfood --json` shows the
- // table list. SQL must be SELECT-only; the search/sql gates reject
- // mutating statements.
- rows, err := db.DB().QueryContext(cmd.Context(), `SELECT id, data FROM <table> WHERE ...`)
+ // Filter resources by both the flat and hierarchical naming so the
+ // query catches rows synced via /<resource> AND rows synced via
+ // /<parents>/{id}/<children>. Drop the parent-scoped entry if the
+ // API only exposes the resource flat; add a <resource_singular>
+ // entry for APIs that toggle plural/singular casing. SQL must be
+ // SELECT-only; the search/sql gates reject mutating statements.
+ rows, err := db.DB().QueryContext(cmd.Context(), `
+ SELECT id, data FROM resources
+ WHERE resource_type IN ('<resource>', '<parent>_<resource>')
+ AND ...`)
if err != nil {
return fmt.Errorf("query: %w", err)
}
@@ -2545,6 +2552,8 @@ RunE: func(cmd *cobra.Command, args []string) error {
},
```
+For flat-only resources, the typed FTS/upsert tables the generator emits (e.g., `tasks_fts`, `projects`) work too — `SELECT id, data FROM <typed-table>` is the fast path. The `IN (...)` pattern above is the safe default whenever the resource may be hierarchical; `printing-press dogfood --json` shows the actual `resource_type` distribution so you can confirm without running raw SQL.
+
For features that combine both (cache an API response in the store, or fall through to live when the local store is stale), nest one skeleton inside the other and use the `--data-source auto/local/live` flag pattern from the generated `sync` command.
**Shared helpers available to novel code:** The generator emits `internal/cliutil/` in every CLI. When authoring novel commands, prefer `cliutil.FanoutRun` for any aggregation command (any `--site`/`--source`/`--region` CSV fan-out) and `cliutil.CleanText` for any text extracted from HTML or schema.org JSON-LD. Re-implementing these inline is how recipe-goat's trending silent-drop and `'` entity bugs shipped.
← 77b91be6 docs(cli): canonicalize README install block + cross-repo sw
·
back to Cli Printing Press
·
fix(cli): honor explicit "mcp:read-only": "false" in tools-a ede5c350 →