@codyswann/lisa 2.142.3 → 2.143.1

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.
Files changed (61) hide show
  1. package/package.json +1 -1
  2. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  3. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  4. package/plugins/lisa/commands/repair-intake.md +2 -2
  5. package/plugins/lisa/skills/repair-intake/SKILL.md +64 -9
  6. package/plugins/lisa-agy/commands/repair-intake.md +2 -2
  7. package/plugins/lisa-agy/plugin.json +1 -1
  8. package/plugins/lisa-agy/skills/repair-intake/SKILL.md +64 -9
  9. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  10. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  11. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  12. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  14. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  15. package/plugins/lisa-copilot/commands/repair-intake.md +2 -2
  16. package/plugins/lisa-copilot/skills/repair-intake/SKILL.md +64 -9
  17. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-cursor/commands/repair-intake.md +2 -2
  19. package/plugins/lisa-cursor/skills/repair-intake/SKILL.md +64 -9
  20. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  21. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  22. package/plugins/lisa-expo-agy/plugin.json +1 -1
  23. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  27. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  28. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  29. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  31. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  32. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  33. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  35. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  37. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  38. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  40. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  42. package/plugins/lisa-rails-agy/plugin.json +1 -1
  43. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  45. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  47. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  48. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  50. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  52. package/plugins/lisa-wiki/scripts/wiki-safety.mjs +199 -0
  53. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  54. package/plugins/lisa-wiki-agy/scripts/wiki-safety.mjs +199 -0
  55. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-wiki-copilot/scripts/wiki-safety.mjs +199 -0
  57. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-wiki-cursor/scripts/wiki-safety.mjs +199 -0
  59. package/plugins/src/base/commands/repair-intake.md +2 -2
  60. package/plugins/src/base/skills/repair-intake/SKILL.md +64 -9
  61. package/plugins/src/wiki/scripts/wiki-safety.mjs +199 -0
@@ -49,6 +49,11 @@ close-out** roles and moves work *unstuck* or *fully closed*:
49
49
  lifecycle label. repair-intake classifies it as a PRD or build ticket and adds the configured
50
50
  `ready` label (`prd-ready` for a PRD, build `status:ready` for a ticket) so normal intake can see
51
51
  it; if the later intake/implement gate finds the item incomplete, it moves the item to `blocked`.
52
+ - **Missing PRD child link drift** — a GitHub PRD in `ticketed` (or another open non-product-owned
53
+ PRD role) has a generated-work section/comment that names top-level generated work, but the PRD's
54
+ native sub-issue list is missing one or more of those top-level children. repair-intake replays the
55
+ `prd-backlink` native-linking contract and attaches the missing same-repo top-level children
56
+ idempotently, so PRD rollup can rely on the native graph again.
52
57
 
53
58
  This skill is the symmetric counterpart to `lisa:intake`. It reuses the same queue-detection,
54
59
  the same agent-team orchestration, the same "don't ask, just run" confirmation policy, and the
@@ -152,7 +157,7 @@ claim-and-advance). The essentials, inlined here so this skill is self-complete:
152
157
  | Confluence **space** URL/key | PRD (Confluence) | source=confluence | `in_review`, `blocked`, terminal/open PRDs, all-terminal generated-work rollups |
153
158
  | Confluence **parent page** URL/ID | PRD (Confluence, narrowed) | source=confluence | `in_review`, `blocked`, terminal/open PRDs, all-terminal generated-work rollups |
154
159
  | Linear **workspace** URL, **team** URL/key, or literal `linear` | PRD (Linear) | source=linear | `in_review`, `blocked`, terminal/open PRDs, all-terminal generated-work rollups |
155
- | GitHub **repo** URL / `org/repo` (PRD namespace) | PRD (GitHub) | source=github | `in_review`, `blocked`, terminal/open PRDs, all-terminal generated-work rollups |
160
+ | GitHub **repo** URL / `org/repo` (PRD namespace) | PRD (GitHub) | source=github | `in_review`, `blocked`, terminal/open PRDs, missing PRD child links, all-terminal generated-work rollups |
156
161
  | GitHub **repo** URL / `org/repo` with `tracker = github` (build namespace) | Build (GitHub) | tracker=github | `claimed`, `blocked`, terminal/open issues, parent rollups (intermediate-env + all-terminal), stale-`ready` containers |
157
162
  | GitHub **repo** URL / `org/repo` with an open issue missing configured lifecycle labels | GitHub label normalization | per classified lifecycle | add configured `prd.ready` or build `ready` |
158
163
  | Literal `github` | GitHub; route by `intake_mode` (`prd` / `build` / `both`) | per lifecycle | per lifecycle above, plus GitHub ready-label normalization |
@@ -550,6 +555,47 @@ work is fully terminal:
550
555
  5. If generated work is missing, ambiguous, or partially incomplete, leave the PRD open and report
551
556
  the incomplete child set. Never close a PRD on partial completion.
552
557
 
558
+ ### GitHub PRD missing child links → native sub-issue repair
559
+
560
+ For each open GitHub PRD in `ticketed` or another non-product-owned PRD role, compare the durable
561
+ generated-work fallback against the PRD's native sub-issue graph and repair missing native links.
562
+ This is the recovery counterpart to `lisa:prd-backlink`'s GitHub native parent-linking section:
563
+ PRD intake/backlink should attach generated top-level work as native PRD children when possible,
564
+ but repair-intake must heal the graph when that write was skipped, failed, or later drifted.
565
+
566
+ 1. Read the generated work exactly as PRD rollup does:
567
+ - Prefer the machine-readable `## Tickets` / `## Generated Work` section (`lisa:gw` tokens).
568
+ - If the machine-readable section is absent but an older Lisa ticketing comment exists, parse only
569
+ its structured `Top-level work:` block as a compatibility fallback. Do not scrape arbitrary
570
+ prose.
571
+ 2. Select only generated **top-level** work:
572
+ - `lisa:gw` entries whose `parent` token is empty.
573
+ - Older ticketing-comment entries under `Top-level work:`.
574
+ Leaf Sub-tasks and descendant Stories are never direct PRD children.
575
+ 3. Restrict native repair to same-repo GitHub issues. Cross-repo or cross-vendor generated work stays
576
+ documented-only; record a warning instead of failing.
577
+ 4. Read the PRD's existing native sub-issues with the same GraphQL `subIssues` query documented by
578
+ `lisa:prd-backlink` / `lisa:github-read-issue`, and dedupe by child-ref
579
+ (`owner/repo#number`).
580
+ 5. For each missing same-repo top-level child, resolve node IDs and call the same GitHub GraphQL
581
+ mutation as `prd-backlink`:
582
+
583
+ ```graphql
584
+ mutation($parentId:ID!,$childId:ID!){
585
+ addSubIssue(input:{issueId:$parentId,subIssueId:$childId}){issue{number}subIssue{number}}
586
+ }
587
+ ```
588
+
589
+ Treat "already linked" duplicate rejections as success. If `subIssues` / `addSubIssue` is
590
+ unavailable, leave the documented generated-work fallback intact, record a capability warning, and
591
+ continue.
592
+ 6. Post one idempotent `[lisa-repair-intake]` note when a missing native PRD child link is repaired
593
+ or when the native-link capability is unavailable. Include the generated top-level child set, the
594
+ pre-existing native child set, and repaired child refs in the state fingerprint so repeated cycles
595
+ do not spam comments.
596
+ 7. Do not transition the PRD lifecycle merely because child links were repaired. Rollup/ship remains
597
+ governed by the PRD rollup path after the child graph is complete.
598
+
553
599
  ### GitHub missing official ready-label normalization → configured ready
554
600
 
555
601
  For GitHub queues, enumerate open issues that have **no configured Lisa lifecycle label** in the
@@ -708,6 +754,9 @@ It MAY:
708
754
  applies only to containers, never to leaves.
709
755
  - Move a PRD with fully terminal generated work to `shipped` and close/archive the source artifact
710
756
  where the source vendor supports native close-out, per `prd-lifecycle-rollup`.
757
+ - Repair missing native GitHub PRD child links from the generated-work fallback by replaying the
758
+ `prd-backlink` top-level-only, same-repo, idempotent `addSubIssue` contract. This repairs
759
+ structure only; it does not ship or verify the PRD.
711
760
  - Normalize a GitHub issue with no configured lifecycle label by adding the configured PRD or build
712
761
  `ready` label after classifying the issue. This is a visibility repair, not a claim; the item
713
762
  remains open and unclaimed for normal intake.
@@ -715,6 +764,8 @@ It MAY:
715
764
  It MUST NOT:
716
765
 
717
766
  - Move a PRD out of `draft` or `verified` (those are product-owned), or set `verified` itself.
767
+ - Link leaf Sub-tasks or descendant Stories directly under a PRD. Only generated top-level work
768
+ (empty parent token / `Top-level work:` entries) may become PRD children.
718
769
  - Apply a build `done` value other than via the env-resolution rules, or close a native item at
719
770
  any value other than the true terminal `done` (see `leaf-only-lifecycle`).
720
771
  - Touch `ready` **leaves** (that is `lisa:intake`'s lane). A container carrying `ready` is the
@@ -728,21 +779,23 @@ It MUST NOT:
728
779
  1. **Resolve the queue** — detect vendor/lifecycle (Source dispatch); resolve stuck role names
729
780
  from config. For JIRA, confirm the needed transitions are reachable; stop on misconfig.
730
781
  2. **Enumerate repair candidates** — query in-progress role(s), `blocked` role(s), terminal/open
731
- items, rollup parents/PRDs with child work, **containers carrying the `ready` role** (a
782
+ items, GitHub PRDs whose generated-work fallback names top-level children missing from native
783
+ sub-issues, rollup parents/PRDs with child work, **containers carrying the `ready` role** (a
732
784
  leaf-only-invariant violation to reconcile), and GitHub issues with no configured lifecycle label,
733
785
  for the detected lifecycle(s), up to `max_candidates`, via the Access layer reads.
734
786
  3. **Order deterministically**, highest repair-confidence first:
735
787
  1. terminal-labeled items that only need native close / complete / resolve,
736
- 2. rollup parents/PRDs whose child sets are all terminal (close-out),
737
- 3. rollup parents whose children have advanced to an intermediate env, or stale-`ready`
788
+ 2. GitHub PRDs missing native links for generated top-level work (structure-only repair),
789
+ 3. rollup parents/PRDs whose child sets are all terminal (close-out),
790
+ 4. rollup parents whose children have advanced to an intermediate env, or stale-`ready`
738
791
  containers, that need their derived state applied (status-only reconciliation, no native
739
792
  close),
740
- 4. `blocked` items whose dependencies are now **cleared** (safe, high-value, one-cycle wins),
741
- 5. `blocked` items whose **validation / quality-gate self-block now re-validates PASS** —
793
+ 5. `blocked` items whose dependencies are now **cleared** (safe, high-value, one-cycle wins),
794
+ 6. `blocked` items whose **validation / quality-gate self-block now re-validates PASS** —
742
795
  a human filled in the missing sections (Class B; equally safe and high-value),
743
- 6. `blocked` items with **new clarifying answers**,
744
- 7. GitHub missing-official-label normalization candidates,
745
- 8. **stalled** in-progress items, oldest activity first.
796
+ 7. `blocked` items with **new clarifying answers**,
797
+ 8. GitHub missing-official-label normalization candidates,
798
+ 9. **stalled** in-progress items, oldest activity first.
746
799
  4. **Walk the ordered list**, evaluating each candidate (terminal close-out, rollup child tally,
747
800
  staleness, dependency, answer checks), and repair **every** candidate that is actionable inside
748
801
  the `max_candidates` cap. Continue after successful writes and after per-item errors.
@@ -773,6 +826,8 @@ Report outcomes in these buckets:
773
826
  - `rolled_up` — parent/container/PRD rollups advanced to their derived state: an intermediate env
774
827
  (e.g. all children at `On Stg` → parent `On Stg`), a fully-terminal close-out, or a stale-`ready`
775
828
  container reconciled from its children.
829
+ - `relinked` — GitHub PRDs whose missing native sub-issue links were repaired from the
830
+ generated-work fallback.
776
831
  - `normalized_ready` — GitHub issues missing official lifecycle labels that were classified and
777
832
  given the configured PRD/build `ready` label so normal intake can claim them.
778
833
  - `still_blocked` — examined and intentionally left `blocked`, with the active reason.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-openclaw",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Ruby on Rails-specific skills and hooks for RuboCop and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-rails",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Ruby on Rails-specific hooks — RuboCop linting/formatting and ast-grep scanning on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "TypeScript-specific hooks for formatting, linting, and ast-grep scanning on edit.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-typescript",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "TypeScript-specific hooks — Prettier formatting, ESLint linting, ast-grep scanning, and error-suppression blocking on edit",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "Distributable LLM Wiki kernel — ingest, query, lint, and maintain a git-native markdown knowledge base across Claude and Codex.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Deterministic wiki source safety helpers.
4
+ *
5
+ * This module intentionally uses only Node built-ins and pure string scanning so
6
+ * downstream wiki connectors can run the same redaction pass before persisting
7
+ * reader-safe source notes.
8
+ */
9
+
10
+ const PLACEHOLDERS = {
11
+ ssn: "[REDACTED:SSN]",
12
+ credit_card: "[REDACTED:CREDIT_CARD]",
13
+ private_key: "[REDACTED:PRIVATE_KEY]",
14
+ password: "[REDACTED:PASSWORD]",
15
+ api_key: "[REDACTED:API_KEY]",
16
+ oauth_token: "[REDACTED:OAUTH_TOKEN]",
17
+ bank_account: "[REDACTED:BANK_ACCOUNT]",
18
+ routing_number: "[REDACTED:ROUTING_NUMBER]",
19
+ };
20
+
21
+ const PATTERNS = [
22
+ {
23
+ entityType: "private_key",
24
+ confidence: "high",
25
+ re: /-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/g,
26
+ },
27
+ {
28
+ entityType: "ssn",
29
+ confidence: "high",
30
+ re: /\b(?!000|666|9\d\d)\d{3}-(?!00)\d{2}-(?!0000)\d{4}\b/g,
31
+ },
32
+ {
33
+ entityType: "password",
34
+ confidence: "high",
35
+ re: /\b(?:password|passwd|pwd)\s*[:=]\s*(['"]?)([^\s'",;]{8,})\1/gi,
36
+ valueGroup: 2,
37
+ },
38
+ {
39
+ entityType: "api_key",
40
+ confidence: "medium",
41
+ re: /\b(?:api[_-]?key|access[_-]?key|secret[_-]?key|client[_-]?secret)\s*[:=]\s*(['"]?)([A-Za-z0-9._-]{20,})\1/gi,
42
+ valueGroup: 2,
43
+ },
44
+ {
45
+ entityType: "oauth_token",
46
+ confidence: "high",
47
+ re: /\b(?:oauth[_-]?token|refresh[_-]?token|access[_-]?token|bearer)\s*[:= ]\s*(['"]?)([A-Za-z0-9._-]{24,})\1/gi,
48
+ valueGroup: 2,
49
+ },
50
+ {
51
+ entityType: "routing_number",
52
+ confidence: "medium",
53
+ re: /\b(?:routing|routing_number|aba)\s*(?:number|no\.?)?\s*[:#=]?\s*(\d{9})\b/gi,
54
+ valueGroup: 1,
55
+ },
56
+ {
57
+ entityType: "bank_account",
58
+ confidence: "medium",
59
+ re: /\b(?:bank\s+)?(?:account|acct)\s*(?:number|no\.?)?\s*[:#=]?\s*(\d{6,17})\b/gi,
60
+ valueGroup: 1,
61
+ },
62
+ ];
63
+
64
+ function luhnValid(candidate) {
65
+ const digits = candidate.replace(/\D/g, "");
66
+ if (digits.length < 13 || digits.length > 19) return false;
67
+ let sum = 0;
68
+ let doubleDigit = false;
69
+ for (let i = digits.length - 1; i >= 0; i -= 1) {
70
+ let n = Number(digits[i]);
71
+ if (doubleDigit) {
72
+ n *= 2;
73
+ if (n > 9) n -= 9;
74
+ }
75
+ sum += n;
76
+ doubleDigit = !doubleDigit;
77
+ }
78
+ return sum % 10 === 0;
79
+ }
80
+
81
+ function applyFinding(text, match, pattern) {
82
+ const raw = match[0];
83
+ const value = pattern.valueGroup ? match[pattern.valueGroup] : raw;
84
+ const valueOffset = pattern.valueGroup ? raw.indexOf(value) : 0;
85
+ const start = match.index + valueOffset;
86
+ const end = start + value.length;
87
+ return {
88
+ sanitized:
89
+ text.slice(0, start) + PLACEHOLDERS[pattern.entityType] + text.slice(end),
90
+ finding: {
91
+ entityType: pattern.entityType,
92
+ confidence: pattern.confidence,
93
+ range: { start, end },
94
+ },
95
+ delta: PLACEHOLDERS[pattern.entityType].length - value.length,
96
+ };
97
+ }
98
+
99
+ function collectCreditCardFindings(text) {
100
+ const findings = [];
101
+ const re = /\b(?:\d[ -]?){13,19}\b/g;
102
+ let match;
103
+ while ((match = re.exec(text)) !== null) {
104
+ const value = match[0].trim();
105
+ if (!luhnValid(value)) continue;
106
+ findings.push({
107
+ entityType: "credit_card",
108
+ confidence: "high",
109
+ range: { start: match.index, end: match.index + match[0].length },
110
+ });
111
+ }
112
+ return findings;
113
+ }
114
+
115
+ function summarizeFindings(sourceMetadata, findings) {
116
+ const sourceId =
117
+ sourceMetadata.sourceId ??
118
+ sourceMetadata.id ??
119
+ sourceMetadata.path ??
120
+ sourceMetadata.url ??
121
+ "unknown";
122
+ const byType = new Map();
123
+ for (const finding of findings) {
124
+ const current = byType.get(finding.entityType) ?? {
125
+ sourceId,
126
+ entityType: finding.entityType,
127
+ confidence: finding.confidence,
128
+ count: 0,
129
+ ranges: [],
130
+ };
131
+ current.count += 1;
132
+ current.ranges.push(finding.range);
133
+ byType.set(finding.entityType, current);
134
+ }
135
+ return [...byType.values()].sort((a, b) =>
136
+ a.entityType.localeCompare(b.entityType)
137
+ );
138
+ }
139
+
140
+ function collectFindings(rawText) {
141
+ const text = String(rawText ?? "");
142
+ const findings = [];
143
+
144
+ for (const pattern of PATTERNS) {
145
+ pattern.re.lastIndex = 0;
146
+ let match;
147
+ while ((match = pattern.re.exec(text)) !== null) {
148
+ findings.push(applyFinding(text, match, pattern).finding);
149
+ }
150
+ }
151
+ findings.push(...collectCreditCardFindings(text));
152
+ findings.sort((a, b) => a.range.start - b.range.start);
153
+ return findings;
154
+ }
155
+
156
+ export function scanWikiSourceText(rawText, sourceMetadata = {}) {
157
+ const findings = collectFindings(rawText);
158
+
159
+ return {
160
+ sourceId:
161
+ sourceMetadata.sourceId ??
162
+ sourceMetadata.id ??
163
+ sourceMetadata.path ??
164
+ sourceMetadata.url ??
165
+ "unknown",
166
+ reviewRequired: findings.length > 0,
167
+ findings: summarizeFindings(sourceMetadata, findings),
168
+ };
169
+ }
170
+
171
+ export function sanitizeWikiSourceText(rawText, sourceMetadata = {}) {
172
+ let sanitized = String(rawText ?? "");
173
+ const rawFindings = collectFindings(rawText);
174
+ for (const finding of [...rawFindings].sort(
175
+ (a, b) => b.range.start - a.range.start
176
+ )) {
177
+ sanitized =
178
+ sanitized.slice(0, finding.range.start) +
179
+ PLACEHOLDERS[finding.entityType] +
180
+ sanitized.slice(finding.range.end);
181
+ }
182
+
183
+ return {
184
+ text: sanitized,
185
+ reviewRequired: rawFindings.length > 0,
186
+ findings: summarizeFindings(sourceMetadata, rawFindings),
187
+ };
188
+ }
189
+
190
+ export function serializeWikiSafetyFindings(result) {
191
+ return JSON.stringify(
192
+ {
193
+ reviewRequired: Boolean(result?.reviewRequired),
194
+ findings: Array.isArray(result?.findings) ? result.findings : [],
195
+ },
196
+ null,
197
+ 2
198
+ );
199
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-wiki",
3
- "version": "2.142.3",
3
+ "version": "2.143.1",
4
4
  "description": "LLM Wiki — a distributable, git-native markdown knowledge base for Claude Code and Codex",
5
5
  "author": {
6
6
  "name": "Cody Swann"