bigpowers 2.5.0 → 2.7.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/.pi/package.json +1 -1
- package/.pi/prompts/align-grid.md +2 -0
- package/.pi/prompts/run-planning.md +59 -6
- package/.pi/prompts/scope-work.md +36 -6
- package/.pi/prompts/search-skills.md +54 -6
- package/.pi/prompts/slice-tasks.md +37 -5
- package/.pi/skills/align-grid/SKILL.md +2 -0
- package/.pi/skills/run-planning/SKILL.md +59 -6
- package/.pi/skills/scope-work/SKILL.md +36 -6
- package/.pi/skills/search-skills/SKILL.md +54 -6
- package/.pi/skills/slice-tasks/SKILL.md +37 -5
- package/CHANGELOG.md +14 -0
- package/SKILL-INDEX.md +97 -103
- package/align-grid/SKILL.md +2 -0
- package/package.json +1 -1
- package/run-planning/SKILL.md +59 -6
- package/scope-work/SKILL.md +36 -6
- package/scripts/generate-skill-index.sh +218 -0
- package/scripts/regenerate-lockfile.sh +41 -0
- package/scripts/sync-skills.sh +12 -0
- package/search-skills/SKILL.md +54 -6
- package/skills-lock.json +234 -76
- package/slice-tasks/SKILL.md +37 -5
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# generate-skill-index.sh — Auto-generate SKILL-INDEX.md from skills-lock.json + SKILL.md frontmatter
|
|
3
|
+
# This file is called by sync-skills.sh. Output is SKILL-INDEX.md at repo root.
|
|
4
|
+
# DO NOT edit SKILL-INDEX.md manually — it is auto-generated.
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
8
|
+
LOCKFILE="$REPO_ROOT/skills-lock.json"
|
|
9
|
+
INDEX_FILE="$REPO_ROOT/SKILL-INDEX.md"
|
|
10
|
+
|
|
11
|
+
if [[ ! -f "$LOCKFILE" ]]; then
|
|
12
|
+
echo "generate-skill-index: ERROR — skills-lock.json not found. Run regenerate-lockfile.sh first." >&2
|
|
13
|
+
exit 1
|
|
14
|
+
fi
|
|
15
|
+
|
|
16
|
+
# Phase categorization — maps each skill to a lifecycle phase
|
|
17
|
+
declare -A PHASE_MAP
|
|
18
|
+
PHASE_MAP=(
|
|
19
|
+
# Discover
|
|
20
|
+
[survey-context]="Discover"
|
|
21
|
+
[research-first]="Discover"
|
|
22
|
+
[search-skills]="Discover"
|
|
23
|
+
[using-bigpowers]="Discover"
|
|
24
|
+
[map-codebase]="Discover"
|
|
25
|
+
[elaborate-spec]="Discover"
|
|
26
|
+
# Elaborate / Design
|
|
27
|
+
[model-domain]="Design"
|
|
28
|
+
[define-language]="Design"
|
|
29
|
+
[grill-me]="Design"
|
|
30
|
+
[grill-with-docs]="Design"
|
|
31
|
+
[deepen-architecture]="Design"
|
|
32
|
+
[design-interface]="Design"
|
|
33
|
+
[define-success]="Design"
|
|
34
|
+
# Plan
|
|
35
|
+
[scope-work]="Plan"
|
|
36
|
+
[slice-tasks]="Plan"
|
|
37
|
+
[plan-work]="Plan"
|
|
38
|
+
[plan-release]="Plan"
|
|
39
|
+
[plan-refactor]="Plan"
|
|
40
|
+
[assess-impact]="Plan"
|
|
41
|
+
[change-request]="Plan"
|
|
42
|
+
[run-planning]="Plan"
|
|
43
|
+
[seed-conventions]="Plan"
|
|
44
|
+
# Build
|
|
45
|
+
[develop-tdd]="Build"
|
|
46
|
+
[kickoff-branch]="Build"
|
|
47
|
+
[execute-plan]="Build"
|
|
48
|
+
[build-epic]="Build"
|
|
49
|
+
[spike-prototype]="Build"
|
|
50
|
+
[craft-skill]="Build"
|
|
51
|
+
[setup-environment]="Build"
|
|
52
|
+
[wire-observability]="Build"
|
|
53
|
+
[align-grid]="Build"
|
|
54
|
+
[orchestrate-project]="Build"
|
|
55
|
+
[guard-git]="Build"
|
|
56
|
+
[hook-commits]="Build"
|
|
57
|
+
# Verify
|
|
58
|
+
[verify-work]="Verify"
|
|
59
|
+
[validate-fix]="Verify"
|
|
60
|
+
[audit-code]="Verify"
|
|
61
|
+
[enforce-first]="Verify"
|
|
62
|
+
[run-evals]="Verify"
|
|
63
|
+
[investigate-bug]="Verify"
|
|
64
|
+
[diagnose-root]="Verify"
|
|
65
|
+
[fix-bug]="Verify"
|
|
66
|
+
[inspect-quality]="Verify"
|
|
67
|
+
[request-review]="Verify"
|
|
68
|
+
[respond-review]="Verify"
|
|
69
|
+
[trace-requirement]="Verify"
|
|
70
|
+
# Release
|
|
71
|
+
[release-branch]="Release"
|
|
72
|
+
[commit-message]="Release"
|
|
73
|
+
# Sustain
|
|
74
|
+
[session-state]="Sustain"
|
|
75
|
+
[edit-document]="Sustain"
|
|
76
|
+
[write-document]="Sustain"
|
|
77
|
+
[organize-workspace]="Sustain"
|
|
78
|
+
[reset-baseline]="Sustain"
|
|
79
|
+
[stocktake-skills]="Sustain"
|
|
80
|
+
[evolve-skill]="Sustain"
|
|
81
|
+
[terse-mode]="Sustain"
|
|
82
|
+
[delegate-task]="Sustain"
|
|
83
|
+
[dispatch-agents]="Sustain"
|
|
84
|
+
[simulate-agents]="Sustain"
|
|
85
|
+
[compose-workflow]="Sustain"
|
|
86
|
+
[migrate-spec]="Sustain"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Phase order for display
|
|
90
|
+
PHASE_ORDER=("Discover" "Design" "Plan" "Build" "Verify" "Release" "Sustain")
|
|
91
|
+
|
|
92
|
+
# Column widths
|
|
93
|
+
SKILL_COL_WIDTH=28
|
|
94
|
+
DESC_COL_WIDTH=56
|
|
95
|
+
|
|
96
|
+
# Build the index file
|
|
97
|
+
{
|
|
98
|
+
echo "# Skill Index — Single Source of Truth"
|
|
99
|
+
echo ""
|
|
100
|
+
echo "> **DO NOT EDIT** — This file is auto-generated by \`scripts/generate-skill-index.sh\`."
|
|
101
|
+
echo "> Edit \`SKILL.md\` source files or \`skills-lock.json\` instead. Run \`bash scripts/sync-skills.sh\` to regenerate."
|
|
102
|
+
echo ""
|
|
103
|
+
echo "**Generated:** $(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
104
|
+
echo "**Skills:** $(jq '.skills | length' "$LOCKFILE")"
|
|
105
|
+
echo ""
|
|
106
|
+
|
|
107
|
+
# Summary by phase
|
|
108
|
+
echo "---"
|
|
109
|
+
echo ""
|
|
110
|
+
echo "## Quick Navigation by Phase"
|
|
111
|
+
echo ""
|
|
112
|
+
echo "| Phase | Count | Skills |"
|
|
113
|
+
echo "|---|---|---|"
|
|
114
|
+
total=0
|
|
115
|
+
for phase in "${PHASE_ORDER[@]}"; do
|
|
116
|
+
phase_skills=()
|
|
117
|
+
for name in $(jq -r '.skills | keys[]' "$LOCKFILE" | sort); do
|
|
118
|
+
[[ "${PHASE_MAP[$name]:-}" == "$phase" ]] && phase_skills+=("$name")
|
|
119
|
+
done
|
|
120
|
+
count=${#phase_skills[@]}
|
|
121
|
+
total=$((total + count))
|
|
122
|
+
skill_list=$(IFS=,; echo "${phase_skills[*]}" | sed 's/,/, /g')
|
|
123
|
+
echo "| $phase | $count | \`$skill_list\` |"
|
|
124
|
+
done
|
|
125
|
+
echo "| **TOTAL** | **$total** | |"
|
|
126
|
+
echo ""
|
|
127
|
+
|
|
128
|
+
# Full reference table
|
|
129
|
+
echo "---"
|
|
130
|
+
echo ""
|
|
131
|
+
echo "## Full Reference Table"
|
|
132
|
+
echo ""
|
|
133
|
+
echo "| # | Phase | Skill | Description | Status |"
|
|
134
|
+
echo "|---|---|---|---|---|"
|
|
135
|
+
|
|
136
|
+
row=0
|
|
137
|
+
for phase in "${PHASE_ORDER[@]}"; do
|
|
138
|
+
for name in $(jq -r '.skills | keys[]' "$LOCKFILE" | sort); do
|
|
139
|
+
[[ "${PHASE_MAP[$name]:-}" != "$phase" ]] && continue
|
|
140
|
+
row=$((row + 1))
|
|
141
|
+
desc=$(jq -r --arg n "$name" '.skills[$n].description // ""' "$LOCKFILE" | head -c 80)
|
|
142
|
+
echo "| $row | $phase | \`$name\` | $desc | ✅ Active |"
|
|
143
|
+
done
|
|
144
|
+
done
|
|
145
|
+
|
|
146
|
+
echo ""
|
|
147
|
+
echo "**Total: $total active skills.**"
|
|
148
|
+
echo ""
|
|
149
|
+
|
|
150
|
+
# Lifecycle arc
|
|
151
|
+
echo "---"
|
|
152
|
+
echo ""
|
|
153
|
+
echo "## Lifecycle Arc"
|
|
154
|
+
echo ""
|
|
155
|
+
echo '```'
|
|
156
|
+
echo '[First time]'
|
|
157
|
+
echo 'using-bigpowers → orchestrate-project'
|
|
158
|
+
echo ' ↓'
|
|
159
|
+
echo 'survey-context → research-first → elaborate-spec → map-codebase'
|
|
160
|
+
echo ' ↓'
|
|
161
|
+
echo ' model-domain / define-language / grill-me / grill-with-docs'
|
|
162
|
+
echo ' design-interface / deepen-architecture / define-success'
|
|
163
|
+
echo ' ↓'
|
|
164
|
+
echo ' scope-work → assess-impact → change-request → slice-tasks'
|
|
165
|
+
echo ' → plan-work / plan-refactor / plan-release / seed-conventions'
|
|
166
|
+
echo ' ↓'
|
|
167
|
+
echo ' kickoff-branch → guard-git / hook-commits / setup-environment'
|
|
168
|
+
echo ' ↓'
|
|
169
|
+
echo ' [Unknown domain?] spike-prototype → (learnings)'
|
|
170
|
+
echo ' ↓'
|
|
171
|
+
echo ' develop-tdd (+ enforce-first) ←→ delegate-task / dispatch-agents'
|
|
172
|
+
echo ' execute-plan / build-epic / craft-skill / align-grid'
|
|
173
|
+
echo ' ↓'
|
|
174
|
+
echo ' ★ VERIFY ★ verify-work → run-evals → audit-code'
|
|
175
|
+
echo ' ↓'
|
|
176
|
+
echo ' fix-bug → investigate-bug → diagnose-root → validate-fix'
|
|
177
|
+
echo ' ↓'
|
|
178
|
+
echo ' request-review → respond-review → trace-requirement'
|
|
179
|
+
echo ' ↓'
|
|
180
|
+
echo ' commit-message → release-branch'
|
|
181
|
+
echo ' ↓'
|
|
182
|
+
echo ' inspect-quality → organize-workspace → stocktake-skills'
|
|
183
|
+
echo ' → evolve-skill → edit-document / write-document / migrate-spec'
|
|
184
|
+
echo ''
|
|
185
|
+
echo 'Transversal utilities (any phase):'
|
|
186
|
+
echo ' terse-mode, session-state, visual-dashboard, reset-baseline,'
|
|
187
|
+
echo ' search-skills, compose-workflow, simulate-agents, wire-observability'
|
|
188
|
+
echo '```'
|
|
189
|
+
echo ""
|
|
190
|
+
echo "---"
|
|
191
|
+
echo ""
|
|
192
|
+
echo "## Status Legend"
|
|
193
|
+
echo ""
|
|
194
|
+
echo "| Icon | Meaning |"
|
|
195
|
+
echo "|---|---|"
|
|
196
|
+
echo "| ✅ Active | SKILL.md exists and is usable |"
|
|
197
|
+
echo "| 📋 Planned | Designed but not yet implemented |"
|
|
198
|
+
echo "| 🔄 Refactoring | Active but under revision |"
|
|
199
|
+
echo "| ⚠️ Deprecated | Will be removed in a future release |"
|
|
200
|
+
echo ""
|
|
201
|
+
echo "## Naming Convention Notes"
|
|
202
|
+
echo ""
|
|
203
|
+
echo "All skills follow \`verb-noun\` kebab-case (ADR-0001). Documented exceptions:"
|
|
204
|
+
echo "- \`terse-mode\` — adjective-noun; retained for clarity"
|
|
205
|
+
echo "- \`visual-dashboard\` — adjective-noun; retained for clarity"
|
|
206
|
+
echo ""
|
|
207
|
+
echo "## How to Update"
|
|
208
|
+
echo ""
|
|
209
|
+
echo "1. Run \`bash scripts/sync-skills.sh\` to regenerate this file and all artifacts."
|
|
210
|
+
echo "2. Or run \`bash scripts/generate-skill-index.sh\` to only regenerate this index."
|
|
211
|
+
echo ""
|
|
212
|
+
echo "→ verify: \`find . -maxdepth 2 -name \"SKILL.md\" | grep -v \".git\\|.cursor\\|.gemini\" | wc -l\`"
|
|
213
|
+
echo ""
|
|
214
|
+
|
|
215
|
+
} > "$INDEX_FILE"
|
|
216
|
+
|
|
217
|
+
count=$(jq '.skills | length' "$LOCKFILE")
|
|
218
|
+
echo "generate-skill-index: wrote SKILL-INDEX.md ($count skills)"
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# regenerate-lockfile.sh — Scan all SKILL.md files and regenerate skills-lock.json
|
|
3
|
+
# Output: Canonical catalog with name, description, sha256, path for every skill.
|
|
4
|
+
# Run this after adding, removing, or updating any skill.
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
8
|
+
LOCKFILE="$REPO_ROOT/skills-lock.json"
|
|
9
|
+
|
|
10
|
+
# Build JSON using jq from individual skill records
|
|
11
|
+
# We pipe each skill as a JSON object, then jq -s merges them into an object keyed by name
|
|
12
|
+
records=()
|
|
13
|
+
for skill_dir in "$REPO_ROOT"/*/; do
|
|
14
|
+
skill_md="$skill_dir/SKILL.md"
|
|
15
|
+
[[ -f "$skill_md" ]] || continue
|
|
16
|
+
|
|
17
|
+
name=$(basename "$skill_dir")
|
|
18
|
+
# Extract description from YAML frontmatter (between first --- and second ---)
|
|
19
|
+
description=$(awk '/^---/{f++; next} f==1 && /^description:/{p=1; sub(/^description:[[:space:]]*/,""); print; next} f==1 && p && /^[a-z]+:/{exit} f==1 && p{print}' "$skill_md" \
|
|
20
|
+
| tr -d '\n' | sed -E 's/[[:space:]]+/ /g')
|
|
21
|
+
|
|
22
|
+
# Compute SHA-256 of full SKILL.md content (first 16 hex chars for compact uniqueness)
|
|
23
|
+
sha256=$(sha256sum "$skill_md" | cut -c1-16)
|
|
24
|
+
|
|
25
|
+
# Relative path from repo root
|
|
26
|
+
relpath="${skill_dir#$REPO_ROOT/}SKILL.md"
|
|
27
|
+
|
|
28
|
+
# Emit JSON record for this skill
|
|
29
|
+
records+=("$(jq -n --arg name "$name" \
|
|
30
|
+
--arg desc "$description" \
|
|
31
|
+
--arg sha "$sha256" \
|
|
32
|
+
--arg path "$relpath" \
|
|
33
|
+
'{($name): {description: $desc, sha256: $sha, path: $path}}')")
|
|
34
|
+
done
|
|
35
|
+
|
|
36
|
+
# Merge all records into a single "skills" object with version
|
|
37
|
+
jq -n --argjson skills "$(printf '%s\n' "${records[@]}" | jq -s 'add')" \
|
|
38
|
+
'{version: 1, skills: $skills}' > "$LOCKFILE"
|
|
39
|
+
|
|
40
|
+
count=$(jq '.skills | length' "$LOCKFILE")
|
|
41
|
+
echo "regenerate-lockfile: $count skills written to skills-lock.json"
|
package/scripts/sync-skills.sh
CHANGED
|
@@ -174,6 +174,16 @@ if [[ -n "$OPN_TARGET" ]] && [[ -d "$OPN_TARGET" ]]; then
|
|
|
174
174
|
echo " → $opencode_count skills copied to $OPN_SKILLS/"
|
|
175
175
|
fi
|
|
176
176
|
|
|
177
|
+
# Regenerate skills-lock.json catalog
|
|
178
|
+
if [[ -x "$REPO_ROOT/scripts/regenerate-lockfile.sh" ]]; then
|
|
179
|
+
bash "$REPO_ROOT/scripts/regenerate-lockfile.sh" || { echo "sync-skills: FAIL — lockfile regeneration failed" >&2; exit 1; }
|
|
180
|
+
fi
|
|
181
|
+
|
|
182
|
+
# Regenerate SKILL-INDEX.md from lockfile + frontmatter
|
|
183
|
+
if [[ -x "$REPO_ROOT/scripts/generate-skill-index.sh" ]]; then
|
|
184
|
+
bash "$REPO_ROOT/scripts/generate-skill-index.sh" || { echo "sync-skills: FAIL — SKILL-INDEX.md generation failed" >&2; exit 1; }
|
|
185
|
+
fi
|
|
186
|
+
|
|
177
187
|
# Regenerate lexical skill index for search-skills
|
|
178
188
|
if [[ -x "$REPO_ROOT/scripts/build-skill-index.sh" ]]; then
|
|
179
189
|
bash "$REPO_ROOT/scripts/build-skill-index.sh" || true
|
|
@@ -187,6 +197,8 @@ echo " → .gemini/extensions/bigpowers/gemini-extension.json"
|
|
|
187
197
|
echo " → .pi/skills/ ($skill_count skill dirs — pi Agent Skills)"
|
|
188
198
|
echo " → .pi/prompts/ ($skill_count prompt templates — pi slash commands)"
|
|
189
199
|
echo " → .pi/package.json (pi package manifest)"
|
|
200
|
+
echo " → skills-lock.json (catalog with SHA-256 hashes)"
|
|
201
|
+
echo " → SKILL-INDEX.md (auto-generated skill reference)"
|
|
190
202
|
echo " → opencode.json (CLAUDE.md + CONVENTIONS.md instructions)"
|
|
191
203
|
[[ -n "$OPN_TARGET" ]] && echo " → bigpowers-opencode: $opencode_count skills"
|
|
192
204
|
|
package/search-skills/SKILL.md
CHANGED
|
@@ -5,17 +5,65 @@ model: haiku
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Search Skills
|
|
8
|
-
> **HARD GATE** — **HARD GATE** — Search results must be ranked by relevance. Do NOT return all matches without prioritization. Use skill metadata (phase, purpose, frequency) to rank.
|
|
9
8
|
|
|
9
|
+
> **HARD GATE** — Search results must be ranked by relevance. Do NOT return all matches without prioritization. Use skill metadata (phase, purpose, frequency) to rank.
|
|
10
|
+
>
|
|
11
|
+
> **HARD GATE** — Do NOT use external embedding APIs or AI-based semantic search. This is a lexical-only index (ADR: zero external dependency).
|
|
10
12
|
|
|
11
|
-
Lexical search only — no embedding service (ADR: zero external dependency).
|
|
13
|
+
Lexical search only — no embedding service (ADR: zero external dependency). The index is a flat markdown file (`specs/SKILL-SEARCH-INDEX.md`) built from every SKILL.md's YAML frontmatter — name, description, and key phrases. No vector DB, no API calls, no network dependency.
|
|
14
|
+
|
|
15
|
+
## When to use
|
|
16
|
+
|
|
17
|
+
- You're unsure which skill to invoke for a user's request
|
|
18
|
+
- At the start of `research-first` to find pre-existing skills that might solve the problem
|
|
19
|
+
- When a user asks "is there a skill for X?"
|
|
20
|
+
- Before calling a skill by name, to confirm it's the right one
|
|
21
|
+
|
|
22
|
+
## Pre-flight
|
|
23
|
+
|
|
24
|
+
- [ ] Does `specs/SKILL-SEARCH-INDEX.md` exist? If not, run `bash scripts/build-skill-index.sh`.
|
|
25
|
+
- [ ] Is the index fresh? Check its timestamp — if > 24 hours old or after any SKILL.md change, regenerate.
|
|
12
26
|
|
|
13
27
|
## Process
|
|
14
28
|
|
|
15
|
-
1. Run `bash scripts/build-skill-index.sh` if `specs/SKILL-SEARCH-INDEX.md`
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
29
|
+
1. **Refresh index if stale** — Run `bash scripts/build-skill-index.sh` if `specs/SKILL-SEARCH-INDEX.md` doesn't exist or was modified before the last SKILL.md change.
|
|
30
|
+
|
|
31
|
+
2. **Search the index** — Use ripgrep on the lexical index:
|
|
32
|
+
```
|
|
33
|
+
rg -i "<keywords>" specs/SKILL-SEARCH-INDEX.md
|
|
34
|
+
```
|
|
35
|
+
The index contains each skill's name, description, phase, and key use-case phrases, so natural language queries work well even without embeddings.
|
|
36
|
+
|
|
37
|
+
3. **Rank results** — Read the top 3 matches. Evaluate by:
|
|
38
|
+
- **Exactness** — Does the description literally match the user's intent?
|
|
39
|
+
- **Phase fit** — Is the skill designed for the current lifecycle phase?
|
|
40
|
+
- **Trigger phrases** — Does the skill's "Use when" section match the situation?
|
|
41
|
+
|
|
42
|
+
4. **Recommend one skill** — Select the single best-matching skill. Provide:
|
|
43
|
+
- The skill name
|
|
44
|
+
- Why it's the best match (citing the description or trigger phrase)
|
|
45
|
+
- What it produces (artifact, dialogue, or state change)
|
|
46
|
+
|
|
47
|
+
5. **Invoke** — Call the skill directly or through the orchestrator. If no match found, suggest the closest phase-appropriate skill or `using-bigpowers` as a general entry point.
|
|
48
|
+
|
|
49
|
+
## Index Format
|
|
50
|
+
|
|
51
|
+
`specs/SKILL-SEARCH-INDEX.md` contains one section per skill:
|
|
52
|
+
```markdown
|
|
53
|
+
## <skill-name>
|
|
54
|
+
- **Description:** <from frontmatter>
|
|
55
|
+
- **Phase:** <lifecycle phase>
|
|
56
|
+
- **Triggers:** <key phrases from description>
|
|
57
|
+
- **Keywords:** <extracted terms>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Why Not Semantic Search?
|
|
61
|
+
|
|
62
|
+
- Zero network dependency — works fully offline
|
|
63
|
+
- Zero cost — no API keys, no usage limits
|
|
64
|
+
- Instant — ripgrep on a local file is sub-second
|
|
65
|
+
- Deterministic — same query always returns same results
|
|
66
|
+
- Auditable — you can read the full index
|
|
19
67
|
|
|
20
68
|
## Verify
|
|
21
69
|
|