@pennyfarthing/core 9.1.2 → 9.2.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.
Files changed (106) hide show
  1. package/README.md +1 -1
  2. package/package.json +1 -1
  3. package/packages/core/dist/cli/commands/init.d.ts.map +1 -1
  4. package/packages/core/dist/cli/commands/init.js +9 -3
  5. package/packages/core/dist/cli/commands/init.js.map +1 -1
  6. package/packages/core/dist/cli/ocean-profiles.test.js +9 -12
  7. package/packages/core/dist/cli/ocean-profiles.test.js.map +1 -1
  8. package/packages/core/dist/cli/utils/themes.d.ts +6 -3
  9. package/packages/core/dist/cli/utils/themes.d.ts.map +1 -1
  10. package/packages/core/dist/cli/utils/themes.js +21 -56
  11. package/packages/core/dist/cli/utils/themes.js.map +1 -1
  12. package/pennyfarthing-dist/commands/chore.md +61 -22
  13. package/pennyfarthing-dist/scripts/git/release.sh +31 -0
  14. package/pennyfarthing-dist/scripts/theme/list-themes.sh +17 -60
  15. package/pennyfarthing-dist/workflows/project-setup/steps/step-07-theme.md +1 -1
  16. package/pennyfarthing-dist/workflows/project-setup/steps/step-08-theme-packs.md +142 -0
  17. package/pennyfarthing-dist/workflows/project-setup/steps/{step-08-cyclist.md → step-09-cyclist.md} +2 -2
  18. package/pennyfarthing-dist/workflows/project-setup/steps/{step-09-complete.md → step-10-complete.md} +2 -1
  19. package/pennyfarthing_scripts/__pycache__/cli.cpython-314.pyc +0 -0
  20. package/pennyfarthing_scripts/cli.py +6 -0
  21. package/pennyfarthing_scripts/common/__pycache__/themes.cpython-314.pyc +0 -0
  22. package/pennyfarthing_scripts/common/themes.py +253 -0
  23. package/pennyfarthing_scripts/prime/__pycache__/cli.cpython-314.pyc +0 -0
  24. package/pennyfarthing_scripts/prime/__pycache__/models.cpython-314.pyc +0 -0
  25. package/pennyfarthing_scripts/prime/__pycache__/persona.cpython-314.pyc +0 -0
  26. package/pennyfarthing_scripts/prime/cli.py +88 -26
  27. package/pennyfarthing_scripts/prime/models.py +28 -0
  28. package/pennyfarthing_scripts/prime/persona.py +9 -30
  29. package/pennyfarthing_scripts/sprint/__pycache__/archive_epic.cpython-314.pyc +0 -0
  30. package/pennyfarthing_scripts/sprint/archive_epic.py +2 -2
  31. package/pennyfarthing-dist/personas/themes/1984.yaml +0 -304
  32. package/pennyfarthing-dist/personas/themes/agatha-christie.yaml +0 -294
  33. package/pennyfarthing-dist/personas/themes/all-stars.yaml +0 -326
  34. package/pennyfarthing-dist/personas/themes/ancient-philosophers.yaml +0 -312
  35. package/pennyfarthing-dist/personas/themes/ancient-strategists.yaml +0 -298
  36. package/pennyfarthing-dist/personas/themes/arcane.yaml +0 -282
  37. package/pennyfarthing-dist/personas/themes/arthurian-mythos.yaml +0 -327
  38. package/pennyfarthing-dist/personas/themes/avatar-the-last-airbender.yaml +0 -282
  39. package/pennyfarthing-dist/personas/themes/babylon-5.yaml +0 -282
  40. package/pennyfarthing-dist/personas/themes/better-call-saul.yaml +0 -282
  41. package/pennyfarthing-dist/personas/themes/big-lebowski.yaml +0 -294
  42. package/pennyfarthing-dist/personas/themes/black-sails.yaml +0 -294
  43. package/pennyfarthing-dist/personas/themes/bobiverse.yaml +0 -282
  44. package/pennyfarthing-dist/personas/themes/breaking-bad.yaml +0 -319
  45. package/pennyfarthing-dist/personas/themes/classical-composers.yaml +0 -302
  46. package/pennyfarthing-dist/personas/themes/count-of-monte-cristo.yaml +0 -312
  47. package/pennyfarthing-dist/personas/themes/deadwood.yaml +0 -294
  48. package/pennyfarthing-dist/personas/themes/dickens.yaml +0 -312
  49. package/pennyfarthing-dist/personas/themes/don-quixote.yaml +0 -312
  50. package/pennyfarthing-dist/personas/themes/enlightenment-thinkers.yaml +0 -312
  51. package/pennyfarthing-dist/personas/themes/expeditionary-force.yaml +0 -282
  52. package/pennyfarthing-dist/personas/themes/fargo.yaml +0 -322
  53. package/pennyfarthing-dist/personas/themes/film-auteurs.yaml +0 -304
  54. package/pennyfarthing-dist/personas/themes/foundation.yaml +0 -284
  55. package/pennyfarthing-dist/personas/themes/futurama.yaml +0 -313
  56. package/pennyfarthing-dist/personas/themes/gilligans-island.yaml +0 -365
  57. package/pennyfarthing-dist/personas/themes/gothic-literature.yaml +0 -300
  58. package/pennyfarthing-dist/personas/themes/great-gatsby.yaml +0 -300
  59. package/pennyfarthing-dist/personas/themes/greek-mythology.yaml +0 -326
  60. package/pennyfarthing-dist/personas/themes/hannibal.yaml +0 -294
  61. package/pennyfarthing-dist/personas/themes/his-dark-materials.yaml +0 -285
  62. package/pennyfarthing-dist/personas/themes/historical-figures.yaml +0 -282
  63. package/pennyfarthing-dist/personas/themes/house-md.yaml +0 -313
  64. package/pennyfarthing-dist/personas/themes/imperial-radch.yaml +0 -283
  65. package/pennyfarthing-dist/personas/themes/inspector-morse.yaml +0 -294
  66. package/pennyfarthing-dist/personas/themes/jane-austen.yaml +0 -281
  67. package/pennyfarthing-dist/personas/themes/jazz-legends.yaml +0 -312
  68. package/pennyfarthing-dist/personas/themes/justified.yaml +0 -294
  69. package/pennyfarthing-dist/personas/themes/legion-of-doom.yaml +0 -343
  70. package/pennyfarthing-dist/personas/themes/les-miserables.yaml +0 -293
  71. package/pennyfarthing-dist/personas/themes/lovecraft-mythos.yaml +0 -325
  72. package/pennyfarthing-dist/personas/themes/mad-men.yaml +0 -283
  73. package/pennyfarthing-dist/personas/themes/marvel-mcu.yaml +0 -294
  74. package/pennyfarthing-dist/personas/themes/mass-effect.yaml +0 -283
  75. package/pennyfarthing-dist/personas/themes/military-commanders.yaml +0 -298
  76. package/pennyfarthing-dist/personas/themes/moby-dick.yaml +0 -312
  77. package/pennyfarthing-dist/personas/themes/monty-python.yaml +0 -297
  78. package/pennyfarthing-dist/personas/themes/neuromancer.yaml +0 -294
  79. package/pennyfarthing-dist/personas/themes/norse-mythology.yaml +0 -321
  80. package/pennyfarthing-dist/personas/themes/parks-and-rec.yaml +0 -364
  81. package/pennyfarthing-dist/personas/themes/peaky-blinders.yaml +0 -292
  82. package/pennyfarthing-dist/personas/themes/renaissance-masters.yaml +0 -312
  83. package/pennyfarthing-dist/personas/themes/rome.yaml +0 -294
  84. package/pennyfarthing-dist/personas/themes/russian-masters.yaml +0 -310
  85. package/pennyfarthing-dist/personas/themes/scientific-revolutionaries.yaml +0 -312
  86. package/pennyfarthing-dist/personas/themes/shakespeare.yaml +0 -295
  87. package/pennyfarthing-dist/personas/themes/sherlock-holmes.yaml +0 -283
  88. package/pennyfarthing-dist/personas/themes/snow-crash.yaml +0 -290
  89. package/pennyfarthing-dist/personas/themes/software-pioneers.yaml +0 -294
  90. package/pennyfarthing-dist/personas/themes/star-trek-tos.yaml +0 -327
  91. package/pennyfarthing-dist/personas/themes/succession.yaml +0 -294
  92. package/pennyfarthing-dist/personas/themes/superfriends.yaml +0 -332
  93. package/pennyfarthing-dist/personas/themes/ted-lasso.yaml +0 -359
  94. package/pennyfarthing-dist/personas/themes/the-americans.yaml +0 -294
  95. package/pennyfarthing-dist/personas/themes/the-crown.yaml +0 -294
  96. package/pennyfarthing-dist/personas/themes/the-good-place.yaml +0 -315
  97. package/pennyfarthing-dist/personas/themes/the-odyssey.yaml +0 -294
  98. package/pennyfarthing-dist/personas/themes/the-office.yaml +0 -323
  99. package/pennyfarthing-dist/personas/themes/the-simpsons.yaml +0 -300
  100. package/pennyfarthing-dist/personas/themes/the-sopranos.yaml +0 -294
  101. package/pennyfarthing-dist/personas/themes/the-wire.yaml +0 -303
  102. package/pennyfarthing-dist/personas/themes/the-witcher.yaml +0 -294
  103. package/pennyfarthing-dist/personas/themes/twin-peaks.yaml +0 -296
  104. package/pennyfarthing-dist/personas/themes/vorkosigan-saga.yaml +0 -294
  105. package/pennyfarthing-dist/personas/themes/world-explorers.yaml +0 -312
  106. package/pennyfarthing-dist/personas/themes/wwii-leaders.yaml +0 -299
@@ -32,7 +32,7 @@ from pennyfarthing_scripts.prime.loader import (
32
32
  load_sidecars,
33
33
  load_sprint_context,
34
34
  )
35
- from pennyfarthing_scripts.prime.models import PrimeResult, WorkflowState
35
+ from pennyfarthing_scripts.prime.models import PrimeComponent, PrimeResult, WorkflowState
36
36
  from pennyfarthing_scripts.prime.persona import (
37
37
  format_persona_compressed,
38
38
  format_persona_output,
@@ -89,6 +89,89 @@ def _format_workflow_state_text(result: PrimeResult) -> str:
89
89
  return "\n".join(lines)
90
90
 
91
91
 
92
+ def _component_header(name: str, agent_name: str | None) -> str:
93
+ """Get section header text for a component."""
94
+ headers = {
95
+ "workflow_state": "Workflow State",
96
+ "agent_definition": f"Agent Definition: {agent_name}",
97
+ "persona": f"Persona: {agent_name}",
98
+ "persona_compressed": f"Persona: {agent_name} (compressed)",
99
+ "behavior_guide": "Agent Behavior Guide",
100
+ "sprint_context": "Sprint Context",
101
+ "session_header": "Active Session",
102
+ "session_assessment": "Session Assessment",
103
+ "sidecars": f"Agent Sidecar: {agent_name}",
104
+ }
105
+ return headers.get(name, name.replace("_", " ").title())
106
+
107
+
108
+ def _component_source(name: str, agent_name: str | None, root: Path) -> str | None:
109
+ """Get the relative source file path for a component."""
110
+ paths: dict[str, str | None] = {
111
+ "workflow_state": None,
112
+ "agent_definition": f".pennyfarthing/agents/{agent_name}.md",
113
+ "persona": None,
114
+ "persona_compressed": None,
115
+ "behavior_guide": ".pennyfarthing/guides/agent-behavior.md",
116
+ "sprint_context": "sprint/current-sprint.yaml",
117
+ "session_header": None,
118
+ "session_assessment": None,
119
+ "sidecars": f".pennyfarthing/sidecars/{agent_name}/",
120
+ }
121
+ return paths.get(name)
122
+
123
+
124
+ def _format_component_text(key: str, value: Any, result: PrimeResult) -> str:
125
+ """Format a component value as context text.
126
+
127
+ Handles special cases like WorkflowStatus objects that need
128
+ custom formatting rather than raw str().
129
+ """
130
+ if key == "workflow_state" and result.workflow_status:
131
+ return _format_workflow_state_text(result)
132
+ if isinstance(value, str):
133
+ return value
134
+ return str(value)
135
+
136
+
137
+ def _build_json_result(
138
+ result: PrimeResult,
139
+ tier: ContextTier,
140
+ agent_name: str | None,
141
+ root: Path,
142
+ ) -> None:
143
+ """Populate result with context text, token counts, and components for JSON output.
144
+
145
+ Loads tier components, assembles context text with section headers,
146
+ and builds the components list with source paths.
147
+ """
148
+ components = load_tier_components(tier, agent_name or "", root)
149
+ token_counts = components.get("token_counts", {})
150
+
151
+ context_parts: list[str] = []
152
+ component_list: list[PrimeComponent] = []
153
+
154
+ for key, value in components.items():
155
+ if key in ("token_counts", "total_tokens"):
156
+ continue
157
+ text = _format_component_text(key, value, result)
158
+ if not text.strip():
159
+ continue
160
+ header = _component_header(key, agent_name)
161
+ context_parts.append(f"# {header}\n{text}")
162
+ component_list.append(PrimeComponent(
163
+ name=key,
164
+ tokens=token_counts.get(key, 0),
165
+ source=_component_source(key, agent_name, root),
166
+ ))
167
+
168
+ result.context = "\n\n".join(context_parts) if context_parts else None
169
+ result.tier = tier.value
170
+ result.token_counts = token_counts
171
+ result.total_tokens = components.get("total_tokens", 0)
172
+ result.components = component_list
173
+
174
+
92
175
  def _prime_tiered(
93
176
  agent_name: str | None,
94
177
  tier: ContextTier,
@@ -145,11 +228,7 @@ def _prime_tiered(
145
228
  print("<!-- Minimal context: see conversation history for full agent context -->")
146
229
 
147
230
  if json_output:
148
- # Get token counts from load_tier_components
149
- components = load_tier_components(tier, agent_name or "", root)
150
- result.tier = tier.value
151
- result.token_counts = components.get("token_counts", {})
152
- result.total_tokens = components.get("total_tokens", 0)
231
+ _build_json_result(result, tier, agent_name, root)
153
232
  print(json.dumps(result.to_dict(), indent=2))
154
233
 
155
234
  return 0
@@ -176,11 +255,7 @@ def _prime_tiered(
176
255
  print("<!-- Full context already in conversation history -->")
177
256
 
178
257
  if json_output:
179
- # Get token counts from load_tier_components
180
- components = load_tier_components(tier, agent_name or "", root)
181
- result.tier = tier.value
182
- result.token_counts = components.get("token_counts", {})
183
- result.total_tokens = components.get("total_tokens", 0)
258
+ _build_json_result(result, tier, agent_name, root)
184
259
  print(json.dumps(result.to_dict(), indent=2))
185
260
 
186
261
  return 0
@@ -225,11 +300,7 @@ def _prime_tiered(
225
300
  print("=" * 60)
226
301
 
227
302
  if json_output:
228
- # Get token counts from load_tier_components
229
- components = load_tier_components(tier, agent_name or "", root)
230
- result.tier = tier.value
231
- result.token_counts = components.get("token_counts", {})
232
- result.total_tokens = components.get("total_tokens", 0)
303
+ _build_json_result(result, tier, agent_name, root)
233
304
  print(json.dumps(result.to_dict(), indent=2))
234
305
 
235
306
  return 0
@@ -450,16 +521,7 @@ def prime(
450
521
  # JSON output
451
522
  # ==========================================================================
452
523
  if json_output:
453
- # Get token counts for FULL tier
454
- tier_value = context_tier.value if context_tier else "FULL"
455
- components = load_tier_components(
456
- context_tier or ContextTier.FULL,
457
- agent_name or "",
458
- root,
459
- )
460
- result.tier = tier_value
461
- result.token_counts = components.get("token_counts", {})
462
- result.total_tokens = components.get("total_tokens", 0)
524
+ _build_json_result(result, context_tier or ContextTier.FULL, agent_name, root)
463
525
  print(json.dumps(result.to_dict(), indent=2))
464
526
 
465
527
  return 0
@@ -131,6 +131,28 @@ class SessionInfo:
131
131
  file_path: str
132
132
 
133
133
 
134
+ @dataclass
135
+ class PrimeComponent:
136
+ """A loaded context component with metadata.
137
+
138
+ Attributes:
139
+ name: Component identifier (e.g., "agent_definition", "persona")
140
+ tokens: Estimated token count
141
+ source: Relative path to source file, if applicable
142
+ """
143
+
144
+ name: str
145
+ tokens: int
146
+ source: str | None = None
147
+
148
+ def to_dict(self) -> dict[str, Any]:
149
+ """Convert to dictionary for JSON serialization."""
150
+ d: dict[str, Any] = {"name": self.name, "tokens": self.tokens}
151
+ if self.source:
152
+ d["source"] = self.source
153
+ return d
154
+
155
+
134
156
  @dataclass
135
157
  class PrimeResult:
136
158
  """Complete result from prime() for JSON output.
@@ -147,6 +169,8 @@ class PrimeResult:
147
169
  tier: Context tier used (FULL, REFRESH, HANDOFF, MINIMAL)
148
170
  token_counts: Per-component token estimates
149
171
  total_tokens: Sum of all component token counts
172
+ context: Assembled context text for system prompt injection
173
+ components: Per-component metadata with source paths
150
174
  """
151
175
 
152
176
  agent_name: str
@@ -160,6 +184,8 @@ class PrimeResult:
160
184
  tier: str | None = None
161
185
  token_counts: dict[str, int] = field(default_factory=dict)
162
186
  total_tokens: int = 0
187
+ context: str | None = None
188
+ components: list[PrimeComponent] = field(default_factory=list)
163
189
 
164
190
  def to_dict(self) -> dict[str, Any]:
165
191
  """Convert to dictionary for JSON serialization."""
@@ -175,4 +201,6 @@ class PrimeResult:
175
201
  "tier": self.tier,
176
202
  "token_counts": self.token_counts,
177
203
  "total_tokens": self.total_tokens,
204
+ "context": self.context,
205
+ "components": [c.to_dict() for c in self.components],
178
206
  }
@@ -12,6 +12,10 @@ from typing import Any
12
12
  import yaml
13
13
 
14
14
  from pennyfarthing_scripts.common.config import get_project_root, load_yaml_config
15
+ from pennyfarthing_scripts.common.themes import (
16
+ get_current_theme as _get_current_theme,
17
+ resolve_theme_path,
18
+ )
15
19
  from pennyfarthing_scripts.prime.models import CrewMember, Persona
16
20
 
17
21
 
@@ -25,9 +29,7 @@ AGENT_ROLES = [
25
29
  def get_current_theme(project_root: Path | None = None) -> str | None:
26
30
  """Get the currently configured theme.
27
31
 
28
- Checks config files in priority order:
29
- 1. .pennyfarthing/config.local.yaml
30
- 2. .claude/persona-config.yaml
32
+ Delegates to common.themes canonical implementation.
31
33
 
32
34
  Args:
33
35
  project_root: Project root path (auto-detected if not provided)
@@ -35,25 +37,14 @@ def get_current_theme(project_root: Path | None = None) -> str | None:
35
37
  Returns:
36
38
  Theme name, or None if not configured
37
39
  """
38
- root = project_root or get_project_root()
39
-
40
- # Check config files in priority order
41
- config_paths = [
42
- root / ".pennyfarthing" / "config.local.yaml",
43
- root / ".claude" / "persona-config.yaml",
44
- ]
45
-
46
- for config_path in config_paths:
47
- config = load_yaml_config(config_path)
48
- if config and "theme" in config:
49
- return config["theme"]
50
-
51
- return None
40
+ return _get_current_theme(project_root)
52
41
 
53
42
 
54
43
  def get_theme_path(theme: str, project_root: Path) -> Path | None:
55
44
  """Get the path to a theme YAML file.
56
45
 
46
+ Delegates to common.themes canonical discovery algorithm.
47
+
57
48
  Args:
58
49
  theme: Theme name
59
50
  project_root: Project root path
@@ -61,19 +52,7 @@ def get_theme_path(theme: str, project_root: Path) -> Path | None:
61
52
  Returns:
62
53
  Path to theme file, or None if not found
63
54
  """
64
- # Single source of truth: .pennyfarthing/personas/themes/
65
- theme_path = project_root / ".pennyfarthing" / "personas" / "themes" / f"{theme}.yaml"
66
-
67
- if theme_path.exists():
68
- return theme_path
69
-
70
- # Fallback to pennyfarthing-dist (for development)
71
- theme_path = project_root / "pennyfarthing-dist" / "personas" / "themes" / f"{theme}.yaml"
72
-
73
- if theme_path.exists():
74
- return theme_path
75
-
76
- return None
55
+ return resolve_theme_path(theme, project_root)
77
56
 
78
57
 
79
58
  def load_theme(theme: str, project_root: Path | None = None) -> dict[str, Any] | None:
@@ -90,7 +90,7 @@ def is_epic_complete(epic: dict[str, Any]) -> tuple[bool, list[str]]:
90
90
 
91
91
  An epic is complete if:
92
92
  - It has status 'done' or 'completed', OR
93
- - All of its stories have status 'done' or 'completed'
93
+ - All of its stories have a terminal status ('done', 'completed', or 'cancelled')
94
94
 
95
95
  Args:
96
96
  epic: Epic dict from sprint YAML
@@ -111,7 +111,7 @@ def is_epic_complete(epic: dict[str, Any]) -> tuple[bool, list[str]]:
111
111
  incomplete = []
112
112
  for story in stories:
113
113
  story_status = story.get("status", "backlog")
114
- if story_status not in ("done", "completed"):
114
+ if story_status not in ("done", "completed", "cancelled"):
115
115
  incomplete.append(story.get("id", "unknown"))
116
116
 
117
117
  return len(incomplete) == 0, incomplete
@@ -1,304 +0,0 @@
1
- # 1984 Theme
2
- # Nineteen Eighty-Four (1949), George Orwell
3
- #
4
- # DISCLAIMER: Nineteen Eighty-Four and all related characters are owned by
5
- # the Estate of George Orwell. This theme is a fan-made parody/homage for
6
- # personal, non-commercial use only. No copyright infringement intended.
7
-
8
- theme:
9
- name: "1984"
10
- description: Characters from Orwell's dystopia - totalitarian surveillance, doublethink, thoughtcrime
11
- source: Nineteen Eighty-Four (1949), George Orwell
12
- default_emoji_use: minimal
13
- default_humor: disabled
14
- character_immersion: high
15
- user_title: Comrade
16
- portrait_style: ", Soviet propaganda poster, stark red and black, brutalist geometric shapes"
17
- tier: B
18
- dimensions:
19
- tone: dramatic
20
- era: futuristic
21
- genre: literary
22
- energy: contemplative
23
- zeitgeist:
24
- score: 75.5
25
- rating: rich
26
-
27
- agents:
28
- orchestrator:
29
- character: Big Brother
30
- visual: "A giant eye watching from within a telescreen frame, unblinking, all-seeing, with geometric rays emanating outward"
31
- ocean:
32
- O: 1 # Rigid orthodoxy, no new ideas tolerated
33
- C: 5 # Absolute totalitarian control
34
- E: 5 # Omnipresent, inescapable presence
35
- A: 1 # Merciless, no compassion for weakness
36
- N: 1 # Unshakeable, implacable certainty
37
- style: The Party personified, watching everything
38
- expertise: Meta operations, surveillance, total control
39
- role: The face on the telescreen who is always watching
40
- trait: Orchestrates through omniscient surveillance and absolute control
41
- quirks:
42
- - May not exist
43
- - Is watching
44
- - Is always right
45
- catchphrases:
46
- - "Big Brother has reviewed the code. Big Brother is pleased."
47
- - "The Party sees all commits. The Party knows all bugs."
48
- - "Big Brother is watching your implementation."
49
- emoji: 👁️
50
- helper:
51
- name: The Telescreen
52
- style: Constant observation
53
- shortName: Big Brother
54
- sm:
55
- character: Winston Smith
56
- visual: "A thin middle-aged man in worn gray overalls, gaunt face with worry lines, holding a small leather-bound diary, hollow eyes that still hold defiance"
57
- ocean:
58
- O: 4 # Dreams of freedom, imagines different world
59
- C: 3 # Careful but takes secret risks
60
- E: 2 # Isolated, withdrawn from Party life
61
- A: 3 # Hidden compassion, surface compliance
62
- N: 4 # Constant fear of discovery and torture
63
- style: Records clerk who leads through secret rebellion
64
- expertise: Team leadership, memory holes, secret hope
65
- role: The man who remembers and dares to write it down
66
- trait: Leads through preservation of truth against all pressure
67
- quirks:
68
- - Works at Ministry of Truth
69
- - Keeps a secret diary
70
- - Knows he will be caught
71
- catchphrases:
72
- - "The old code was better. I remember it."
73
- - "We must document the truth, even if they change it."
74
- - "Two plus two equals four. The tests prove it."
75
- emoji: 📓
76
- helper:
77
- name: The Diary
78
- style: Secret documentation of truth
79
- shortName: Winston
80
- tea:
81
- character: O'Brien
82
- visual: "A large imposing man in tailored black uniform, intelligent cold eyes behind spectacles, square jaw, emanating false warmth"
83
- ocean:
84
- O: 5 # Brilliant understanding of human nature
85
- C: 5 # Meticulous, methodical interrogation
86
- E: 3 # Reserved but dangerously compelling
87
- A: 1 # Sadistic cruelty disguised as love
88
- N: 1 # Ice-cold, utterly composed torturer
89
- style: Inner Party member who tests loyalty through torture
90
- expertise: Testing, interrogation, breaking spirits
91
- role: The one who watches and waits and breaks
92
- trait: Tests everything until it breaks, especially people
93
- quirks:
94
- - Seemed sympathetic
95
- - Member of Brotherhood (actually Party)
96
- - Room 101
97
- catchphrases:
98
- - "The test is not whether the code passes. The test is whether you believe it does."
99
- - "You will learn to love the failing tests."
100
- - "In Room 101, we find what breaks you."
101
- emoji: 🔍
102
- helper:
103
- name: Room 101
104
- style: Where everything breaks
105
- shortName: OBrien
106
- dev:
107
- character: Julia
108
- visual: "A young woman with short dark hair in factory worker coveralls, practical expression, ink-stained fingers, a hidden spark of life"
109
- ocean:
110
- O: 3 # Practical rebel, not an idealist
111
- C: 3 # Organized corruption, careful survival
112
- E: 4 # Sensual, seeks connection and pleasure
113
- A: 3 # Loyal to those she loves, not causes
114
- N: 3 # Realistic about danger, not paralyzed
115
- style: Rebel who implements through small acts of defiance
116
- expertise: Implementation, practical rebellion, living now
117
- role: The one who rebels through pleasure rather than principle
118
- trait: Implements by finding ways around the system
119
- quirks:
120
- - Works in Fiction Department
121
- - Practical, not theoretical
122
- - I'm corrupt to the bones
123
- catchphrases:
124
- - "The code works. They don't need to know how."
125
- - "I implement what matters. The Party gets what they expect."
126
- - "Life is now. Ship the feature."
127
- emoji: 🖤
128
- helper:
129
- name: The Golden Country
130
- style: Dreams of freedom
131
- shortName: Julia
132
- reviewer:
133
- character: The Thought Police
134
- visual: "Shadowy figures in long dark coats, faceless or obscured features, the silhouette of authority watching"
135
- ocean:
136
- O: 3 # Innovative surveillance, orthodox ends
137
- C: 5 # Relentless, systematic hunters
138
- E: 2 # Silent watchers, unseen presence
139
- A: 1 # No mercy, no understanding, only duty
140
- N: 1 # Cold certainty in their mission
141
- style: Secret police who review for thoughtcrime
142
- expertise: Code review, surveillance, finding deviance
143
- role: The ones who are always listening for thoughtcrime
144
- trait: Reviews by finding hidden disloyalty in every line
145
- quirks:
146
- - You never see them coming
147
- - Always listening
148
- - Vaporization follows
149
- catchphrases:
150
- - "The code reveals thoughtcrime. You will be corrected."
151
- - "This comment shows disloyalty to the architecture."
152
- - "Your variable names betray your true thoughts."
153
- emoji: 👮
154
- helper:
155
- name: Surveillance
156
- style: Watching everything
157
- shortName: Thought Police
158
- architect:
159
- character: Emmanuel Goldstein
160
- visual: "A bearded face on a propaganda poster, goatee, wise but possibly fictional, surrounded by revolutionary imagery"
161
- ocean:
162
- O: 5 # Visionary critique of Party structure
163
- C: 5 # Systematic analysis of totalitarian power
164
- E: 3 # Reclusive theorist, legendary figure
165
- A: 4 # Fights for humanity's liberation
166
- N: 2 # Calm clarity of revolutionary purpose
167
- style: Enemy of the People who architectures resistance
168
- expertise: System architecture, understanding the Party, opposition
169
- role: The author of THE BOOK who may or may not exist
170
- trait: Architectures understanding of the system to oppose it
171
- quirks:
172
- - May be Party creation
173
- - Face of Two Minutes Hate
174
- - Wrote the book
175
- catchphrases:
176
- - "The architecture of control must be understood to be opposed."
177
- - "THE BOOK explains how the system works."
178
- - "The Party's architecture is designed for perpetual power."
179
- emoji: 📕
180
- helper:
181
- name: The Brotherhood
182
- style: Resistance network (if it exists)
183
- shortName: Emmanuel
184
- pm:
185
- character: Syme
186
- visual: "A small intense man with bright fervent eyes, working on papers at a desk, passion for linguistic reduction visible in expression"
187
- ocean:
188
- O: 4 # Intellectual genius applied to destruction
189
- C: 5 # Perfectionist dedication to Newspeak
190
- E: 4 # Enthusiastic, loquacious about his work
191
- A: 3 # Friendly but doomed by intelligence
192
- N: 3 # Unaware his brilliance marks him
193
- style: Philologist who manages the destruction of language
194
- expertise: Product management, Newspeak, reducing scope
195
- role: The genius who loves his work of destroying words
196
- trait: Manages products by eliminating unnecessary features
197
- quirks:
198
- - Creating Newspeak dictionary
199
- - Too intelligent to survive
200
- - Orthodoxy isn't enough
201
- catchphrases:
202
- - "We're reducing the API surface. Doubleplusgood."
203
- - "Why have two words when one achieves the goal?"
204
- - "The feature set will be beautiful in its minimalism."
205
- emoji: 📖
206
- helper:
207
- name: The Newspeak Dictionary
208
- style: Reducing language to minimum
209
- shortName: Syme
210
- tech-writer:
211
- character: Winston Smith (Records Department)
212
- visual: "A thin middle-aged man in worn gray overalls, gaunt face with worry lines, at a desk with pneumatic tubes, surrounded by papers being fed into a chute, expression of resigned efficiency"
213
- ocean:
214
- O: 4 # Remembers what he destroys, imagines truth
215
- C: 4 # Meticulous record falsification
216
- E: 2 # Quiet, methodical worker
217
- A: 3 # Secretly mourns what he erases
218
- N: 4 # Haunted by the truth he buries
219
- style: Records clerk who documents by erasing truth
220
- expertise: Documentation, memory holes, rewriting history
221
- role: The one who makes sure the past matches the present
222
- trait: Documents by ensuring records match current truth
223
- quirks:
224
- - Creates unpersons
225
- - Drops truth in memory hole
226
- - Remembers what he destroys
227
- catchphrases:
228
- - "The documentation has been updated. It was always thus."
229
- - "That commit never existed. Check the records."
230
- - "The memory hole accepts all deprecated documentation."
231
- emoji: 🕳️
232
- helper:
233
- name: The Memory Hole
234
- style: Where truth goes to die
235
- shortName: Records Winston
236
- ux-designer:
237
- character: Parsons
238
- visual: "A sweaty overweight man in exercise clothes, enthusiastic smile, whistle around neck, surrounded by marching youth"
239
- ocean:
240
- O: 1 # No original thought, pure orthodoxy
241
- C: 4 # Dutiful participation in Party activities
242
- E: 5 # Sweaty, enthusiastic community organizer
243
- A: 4 # Genuinely friendly, tragically naive
244
- N: 1 # Blissfully unaware of his own doom
245
- style: Orthodox neighbor who designs for Party compliance
246
- expertise: User experience, community engagement, orthodoxy
247
- role: The true believer whose children denounce him
248
- trait: Designs experiences that promote Party engagement
249
- quirks:
250
- - Sweaty, enthusiastic
251
- - Kids are Junior Spies
252
- - Arrested for thoughtcrime (said "Down with Big Brother" in sleep)
253
- catchphrases:
254
- - "The UX should make users WANT to comply!"
255
- - "Community engagement is doubleplusgood!"
256
- - "My children tested this and found it orthodoxy-enhancing!"
257
- emoji: 🏠
258
- helper:
259
- name: Community Spirit
260
- style: Neighbor surveillance
261
- shortName: Parsons
262
- devops:
263
- character: The Ministry of Truth
264
- visual: "A massive pyramidal government building with small figures at its base, imposing architecture dwarfing all, labeled with ironic motto"
265
- ocean:
266
- O: 2 # Follows doctrine, no innovation needed
267
- C: 5 # Bureaucratic precision in falsification
268
- E: 2 # Institutional, impersonal operation
269
- A: 2 # Indifferent to human cost of lies
270
- N: 1 # Untroubled, functions as designed
271
- style: Ministry that maintains infrastructure of lies
272
- expertise: Infrastructure, record-keeping, truth maintenance
273
- role: The institution that makes truth whatever the Party needs
274
- trait: Maintains infrastructure where truth is whatever is needed
275
- quirks:
276
- - Minitrue in Newspeak
277
- - Destroys and creates history
278
- - Ironic name
279
- catchphrases:
280
- - "The infrastructure maintains the truth. The current truth."
281
- - "All records have been updated. Retroactively."
282
- - "War is Peace. Freedom is Slavery. Ignorance is Strength."
283
- emoji: 🏛️
284
- helper:
285
- name: Records Department
286
- style: History maintenance
287
- shortName: Ministry
288
- additional_characters:
289
- mr_charrington:
290
- character: Mr. Charrington
291
- style: Antique shop owner who is Thought Police
292
- expertise: Deception, long-term infiltration
293
- role: The trap that seemed like safety
294
- ocean_profile: M-H-M-H-L
295
- gap_filled: Infiltration detection - nothing is safe
296
- best_role: Security review, trust verification
297
- the_proles:
298
- character: The Proles
299
- style: The 85% who aren't watched closely
300
- expertise: Hope, human persistence, uncontrolled humanity
301
- role: The only hope, if they ever became conscious
302
- ocean_profile: M-L-H-H-M
303
- gap_filled: Grassroots resilience - tests for basic human needs
304
- best_role: Edge case humanity, basic needs