name: pm-iterator description: Manage named reusable value lists (iterators). Like C macros — define once, reference everywhere. Used in features, requirements, and tests. argument-hint: [product create NAME "desc" val1,val2|list|show NAME|add NAME val|remove NAME val]
PM Iterator — Reusable Named Lists
Manage named value lists that other skills reference instead of hardcoding. Like a C macro or enum — define once, reference by name everywhere.
Invocation
/pm-iterator myriplay create SOFTWARE_ARCHS "Target build architectures" x86,amd64,arm64,mips
/pm-iterator myriplay list
/pm-iterator myriplay show SOFTWARE_ARCHS
/pm-iterator myriplay add SOFTWARE_ARCHS riscv64
/pm-iterator myriplay remove SOFTWARE_ARCHS mips
/pm-iterator myriplay rename SOFTWARE_ARCHS BUILD_TARGETS
/pm-iterator myriplay delete SOFTWARE_ARCHS
Database
Path: .claude/db/marketing.sqlite | PRAGMA foreign_keys=ON;
Uses iterators and iterator_values tables.
UUID generation:
SELECT lower(hex(randomblob(4)) || '-' || hex(randomblob(2)) || '-4' ||
substr(hex(randomblob(2)),2) || '-' ||
substr('89ab',abs(random()) % 4 + 1, 1) ||
substr(hex(randomblob(2)),2) || '-' || hex(randomblob(6)));
Create
- Validate name is UPPER_SNAKE_CASE
- Check for uniqueness within the product
- INSERT into
iterators - INSERT each value into
iterator_valueswith sequential positions - Show:
Created iterator: SOFTWARE_ARCHS (x86, amd64, arm64, mips)
List
SELECT i.name, i.description, GROUP_CONCAT(iv.value, ', ' ORDER BY iv.position) AS vals
FROM iterators i
JOIN our_products op ON op.id = i.product_id
LEFT JOIN iterator_values iv ON iv.iterator_id = i.id
WHERE op.code = :product_code
GROUP BY i.id ORDER BY i.name;
Show
Display iterator detail with all values and where it's referenced:
-- Iterator values
SELECT iv.value, iv.position FROM iterator_values iv
JOIN iterators i ON i.id = iv.iterator_id
WHERE i.name = :name AND i.product_id = :pid
ORDER BY iv.position;
To find references, search text fields in epics, features, requirements, and tests for the iterator name.
Add Value
- Get max position:
SELECT MAX(position) FROM iterator_values WHERE iterator_id = :id - INSERT new value at position + 1
- Show updated list
Remove Value
- DELETE from
iterator_valuesWHERE iterator_id = :id AND value = :val - Reorder remaining positions sequentially
- Show updated list
Rename
- UPDATE
iteratorsSET name = :new_name WHERE id = :id - Warn: "Text references to the old name in existing entities will NOT auto-update. Search and replace manually if needed."
Why Iterators Matter
- Single source of truth. Change once, every reference updates.
- Explicit exclusions. If
armv9is NOT inSOFTWARE_ARCHS, that's deliberate. - Test completeness. "Test against each SOFTWARE_ARCHS" — defined, not implied.
- Requirement precision. "Support each SUPPORTED_PROTOCOLS" — list grows, coverage follows.
Display Rules
- Iterator names stored as-is in text fields: "test against each SOFTWARE_ARCHS"
- NEVER auto-expand inline — the reader sees the exact name
- Glossary at top of any output lists referenced iterators with current values
Rules
- Names must be UPPER_SNAKE_CASE.
- Names are unique per product.
- Never expand iterators in entity text. Always reference by name.
- Warn on rename that text references need manual update.