{
 "about": {
  "method": "crispr-spcas9-guides (src/lib/seq/crispr.ts)",
  "oracle": "An independent enumeration: one regular-expression search, (?=([ACGT]{20})([ACGT]GG)), run over the sequence for the + strand and over Biopython 1.88's reverse complement for the - strand, each hit's position mapped back to top-strand coordinates; the sequence doubled first when circular, so a PAM across the origin is found once; occurrences counted here by testing every window; GC and the longest homopolymer run computed here. One case is worked by hand base by base and the script refuses to write unless its search agrees with it.",
  "recordedOn": "2026-10-10",
  "generatedBy": "pipeline/plasmid-map/crispr.py",
  "convention": "SpCas9 NGG, 20 nt protospacer, both strands; a PAM across a circular origin found once. GC is G+C over the 20 protospacer bases; otherOccurrences is the exact count of other occurrences of the protospacer within the pasted sequence on both strands, the guide's own site excluded. No score of any kind, no mismatch search, no genome statement: the count is of exact matches inside the pasted sequence and says nothing about the genome.",
  "ruling": "CSO, 10 October 2026 (docs/board/memos/2026-10-10-cso-wave2-cloning.md §2.2)."
 },
 "cases": [
  {
   "id": "hand-worked-two-strands",
   "sequence": "ACGTATGCATAGTCATGCATAGGCCTATGCATTAGTCAGTATCAGA",
   "circular": false,
   "note": "Worked by hand, both guides read off the sequence base by base: one GG and one CC in the whole sequence, so one + guide and one - guide. The script refuses to write unless its own search agrees.",
   "guides": [
    {
     "start": 1,
     "end": 20,
     "strand": "+",
     "protospacer": "ACGTATGCATAGTCATGCAT",
     "pam": "AGG",
     "gc": 0.4,
     "longestHomopolymer": 1,
     "otherOccurrences": 0,
     "acrossOrigin": false
    },
    {
     "start": 27,
     "end": 46,
     "strand": "-",
     "protospacer": "TCTGATACTGACTAATGCAT",
     "pam": "AGG",
     "gc": 0.35,
     "longestHomopolymer": 2,
     "otherOccurrences": 0,
     "acrossOrigin": false
    }
   ]
  },
  {
   "id": "linear-both-strands",
   "sequence": "ATGCGTACCATGGGTCATCCAGAGTTTACGGACCATGGTTTAAACCCGGGAAA",
   "circular": false,
   "note": "A short linear sequence: + guides at GG PAMs and - guides at CC PAMs, enumerated by position.",
   "guides": [
    {
     "start": 9,
     "end": 28,
     "strand": "+",
     "protospacer": "CATGGGTCATCCAGAGTTTA",
     "pam": "CGG",
     "gc": 0.45,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": false
    },
    {
     "start": 11,
     "end": 30,
     "strand": "-",
     "protospacer": "CGTAAACTCTGGATGACCCA",
     "pam": "TGG",
     "gc": 0.5,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": false
    },
    {
     "start": 16,
     "end": 35,
     "strand": "+",
     "protospacer": "CATCCAGAGTTTACGGACCA",
     "pam": "TGG",
     "gc": 0.5,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": false
    },
    {
     "start": 22,
     "end": 41,
     "strand": "-",
     "protospacer": "AAACCATGGTCCGTAAACTC",
     "pam": "TGG",
     "gc": 0.45,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": false
    },
    {
     "start": 27,
     "end": 46,
     "strand": "+",
     "protospacer": "TACGGACCATGGTTTAAACC",
     "pam": "CGG",
     "gc": 0.45,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": false
    },
    {
     "start": 28,
     "end": 47,
     "strand": "+",
     "protospacer": "ACGGACCATGGTTTAAACCC",
     "pam": "GGG",
     "gc": 0.5,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": false
    }
   ]
  },
  {
   "id": "tandem-repeat-count",
   "sequence": "GACCATGGTTTACGTACGTAGGGACCATGGTTTACGTACGTAGGTTTT",
   "circular": false,
   "note": "A tandem repeat: the protospacer recurs, so a guide's otherOccurrences is non-zero; a naive unique-site assumption would mislead.",
   "guides": [
    {
     "start": 1,
     "end": 20,
     "strand": "+",
     "protospacer": "GACCATGGTTTACGTACGTA",
     "pam": "GGG",
     "gc": 0.45,
     "longestHomopolymer": 3,
     "otherOccurrences": 1,
     "acrossOrigin": false
    },
    {
     "start": 6,
     "end": 25,
     "strand": "-",
     "protospacer": "GTCCCTACGTACGTAAACCA",
     "pam": "TGG",
     "gc": 0.5,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": false
    },
    {
     "start": 8,
     "end": 27,
     "strand": "+",
     "protospacer": "GTTTACGTACGTAGGGACCA",
     "pam": "TGG",
     "gc": 0.5,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": false
    },
    {
     "start": 22,
     "end": 41,
     "strand": "+",
     "protospacer": "GGACCATGGTTTACGTACGT",
     "pam": "AGG",
     "gc": 0.5,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": false
    },
    {
     "start": 28,
     "end": 47,
     "strand": "-",
     "protospacer": "AAACCTACGTACGTAAACCA",
     "pam": "TGG",
     "gc": 0.4,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": false
    }
   ]
  },
  {
   "id": "opposite-strand-other-site",
   "sequence": "ACGTTGCACCATGGATCGAAAGGTTTTTTCGATCCATGGTGCAACGTTTT",
   "circular": false,
   "note": "The protospacer's only other occurrence is its reverse complement elsewhere, i.e. on the opposite strand: otherOccurrences counts it.",
   "guides": [
    {
     "start": 1,
     "end": 20,
     "strand": "+",
     "protospacer": "ACGTTGCACCATGGATCGAA",
     "pam": "AGG",
     "gc": 0.5,
     "longestHomopolymer": 2,
     "otherOccurrences": 1,
     "acrossOrigin": false
    },
    {
     "start": 12,
     "end": 31,
     "strand": "-",
     "protospacer": "CGAAAAAACCTTTCGATCCA",
     "pam": "TGG",
     "gc": 0.4,
     "longestHomopolymer": 6,
     "otherOccurrences": 0,
     "acrossOrigin": false
    },
    {
     "start": 17,
     "end": 36,
     "strand": "+",
     "protospacer": "CGAAAGGTTTTTTCGATCCA",
     "pam": "TGG",
     "gc": 0.4,
     "longestHomopolymer": 6,
     "otherOccurrences": 0,
     "acrossOrigin": false
    }
   ]
  },
  {
   "id": "circular-origin-pam",
   "sequence": "CATGGGACATGCAAGCTTCATGGTACCCGATCGTTTAAACG",
   "circular": true,
   "note": "A circular sequence: a PAM that crosses the origin is found once; positions wrap.",
   "guides": [
    {
     "start": 1,
     "end": 20,
     "strand": "+",
     "protospacer": "CATGGGACATGCAAGCTTCA",
     "pam": "TGG",
     "gc": 0.5,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": false
    },
    {
     "start": 24,
     "end": 2,
     "strand": "+",
     "protospacer": "TACCCGATCGTTTAAACGCA",
     "pam": "TGG",
     "gc": 0.45,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": true
    },
    {
     "start": 25,
     "end": 3,
     "strand": "+",
     "protospacer": "ACCCGATCGTTTAAACGCAT",
     "pam": "GGG",
     "gc": 0.45,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": true
    },
    {
     "start": 29,
     "end": 7,
     "strand": "-",
     "protospacer": "TCCCATGCGTTTAAACGATC",
     "pam": "GGG",
     "gc": 0.45,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": true
    },
    {
     "start": 30,
     "end": 8,
     "strand": "-",
     "protospacer": "GTCCCATGCGTTTAAACGAT",
     "pam": "CGG",
     "gc": 0.45,
     "longestHomopolymer": 3,
     "otherOccurrences": 0,
     "acrossOrigin": true
    }
   ]
  }
 ]
}
