pipulate 2.62__tar.gz → 2.64__tar.gz

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 (89) hide show
  1. {pipulate-2.62/pipulate.egg-info → pipulate-2.64}/PKG-INFO +5 -3
  2. {pipulate-2.62 → pipulate-2.64}/README.md +4 -2
  3. {pipulate-2.62 → pipulate-2.64}/__init__.py +2 -2
  4. {pipulate-2.62 → pipulate-2.64}/apps/030_roles.py +3 -3
  5. {pipulate-2.62 → pipulate-2.64}/imports/ascii_displays.py +10 -8
  6. {pipulate-2.62 → pipulate-2.64}/pipulate/__init__.py +3 -3
  7. {pipulate-2.62 → pipulate-2.64}/pipulate/core.py +6 -6
  8. {pipulate-2.62 → pipulate-2.64/pipulate.egg-info}/PKG-INFO +5 -3
  9. {pipulate-2.62 → pipulate-2.64}/pyproject.toml +3 -3
  10. {pipulate-2.62 → pipulate-2.64}/server.py +2 -2
  11. {pipulate-2.62 → pipulate-2.64}/LICENSE +0 -0
  12. {pipulate-2.62 → pipulate-2.64}/MANIFEST.in +0 -0
  13. {pipulate-2.62 → pipulate-2.64}/apps/010_introduction.py +0 -0
  14. {pipulate-2.62 → pipulate-2.64}/apps/015_config.py +0 -0
  15. {pipulate-2.62 → pipulate-2.64}/apps/020_profiles.py +0 -0
  16. {pipulate-2.62 → pipulate-2.64}/apps/025_aspect.py +0 -0
  17. {pipulate-2.62 → pipulate-2.64}/apps/040_hello_workflow.py +0 -0
  18. {pipulate-2.62 → pipulate-2.64}/apps/050_documentation.py +0 -0
  19. {pipulate-2.62 → pipulate-2.64}/apps/060_tasks.py +0 -0
  20. {pipulate-2.62 → pipulate-2.64}/apps/070_history.py +0 -0
  21. {pipulate-2.62 → pipulate-2.64}/apps/110_parameter_buster.py +0 -0
  22. {pipulate-2.62 → pipulate-2.64}/apps/120_link_graph.py +0 -0
  23. {pipulate-2.62 → pipulate-2.64}/apps/130_gap_analysis.py +0 -0
  24. {pipulate-2.62 → pipulate-2.64}/apps/200_workflow_genesis.py +0 -0
  25. {pipulate-2.62 → pipulate-2.64}/apps/210_widget_examples.py +0 -0
  26. {pipulate-2.62 → pipulate-2.64}/apps/220_roadmap.py +0 -0
  27. {pipulate-2.62 → pipulate-2.64}/apps/230_dev_assistant.py +0 -0
  28. {pipulate-2.62 → pipulate-2.64}/apps/240_simon_mcp.py +0 -0
  29. {pipulate-2.62 → pipulate-2.64}/apps/300_blank_placeholder.py +0 -0
  30. {pipulate-2.62 → pipulate-2.64}/apps/400_botify_trifecta.py +0 -0
  31. {pipulate-2.62 → pipulate-2.64}/apps/440_browser_automation.py +0 -0
  32. {pipulate-2.62 → pipulate-2.64}/apps/450_stream_simulator.py +0 -0
  33. {pipulate-2.62 → pipulate-2.64}/apps/510_text_field.py +0 -0
  34. {pipulate-2.62 → pipulate-2.64}/apps/520_text_area.py +0 -0
  35. {pipulate-2.62 → pipulate-2.64}/apps/530_dropdown.py +0 -0
  36. {pipulate-2.62 → pipulate-2.64}/apps/540_checkboxes.py +0 -0
  37. {pipulate-2.62 → pipulate-2.64}/apps/550_radios.py +0 -0
  38. {pipulate-2.62 → pipulate-2.64}/apps/560_range.py +0 -0
  39. {pipulate-2.62 → pipulate-2.64}/apps/570_switch.py +0 -0
  40. {pipulate-2.62 → pipulate-2.64}/apps/580_upload.py +0 -0
  41. {pipulate-2.62 → pipulate-2.64}/apps/610_markdown.py +0 -0
  42. {pipulate-2.62 → pipulate-2.64}/apps/620_mermaid.py +0 -0
  43. {pipulate-2.62 → pipulate-2.64}/apps/630_prism.py +0 -0
  44. {pipulate-2.62 → pipulate-2.64}/apps/640_javascript.py +0 -0
  45. {pipulate-2.62 → pipulate-2.64}/apps/710_pandas.py +0 -0
  46. {pipulate-2.62 → pipulate-2.64}/apps/720_rich.py +0 -0
  47. {pipulate-2.62 → pipulate-2.64}/apps/730_matplotlib.py +0 -0
  48. {pipulate-2.62 → pipulate-2.64}/apps/810_webbrowser.py +0 -0
  49. {pipulate-2.62 → pipulate-2.64}/apps/820_selenium.py +0 -0
  50. {pipulate-2.62 → pipulate-2.64}/apps/830_pico_slider.py +0 -0
  51. {pipulate-2.62 → pipulate-2.64}/cli.py +0 -0
  52. {pipulate-2.62 → pipulate-2.64}/config.py +0 -0
  53. {pipulate-2.62 → pipulate-2.64}/imports/__init__.py +0 -0
  54. {pipulate-2.62 → pipulate-2.64}/imports/ai_dictdb.py +0 -0
  55. {pipulate-2.62 → pipulate-2.64}/imports/ai_tool_discovery_simple_parser.py +0 -0
  56. {pipulate-2.62 → pipulate-2.64}/imports/append_only_conversation.py +0 -0
  57. {pipulate-2.62 → pipulate-2.64}/imports/botify/__init__.py +0 -0
  58. {pipulate-2.62 → pipulate-2.64}/imports/botify/code_generators.py +0 -0
  59. {pipulate-2.62 → pipulate-2.64}/imports/botify/true_schema_discoverer.py +0 -0
  60. {pipulate-2.62 → pipulate-2.64}/imports/botify_code_generation.py +0 -0
  61. {pipulate-2.62 → pipulate-2.64}/imports/crud.py +0 -0
  62. {pipulate-2.62 → pipulate-2.64}/imports/database_safety_wrapper.py +0 -0
  63. {pipulate-2.62 → pipulate-2.64}/imports/dom_processing/__init__.py +0 -0
  64. {pipulate-2.62 → pipulate-2.64}/imports/dom_processing/ai_dom_beautifier.py +0 -0
  65. {pipulate-2.62 → pipulate-2.64}/imports/dom_processing/enhanced_dom_processor.py +0 -0
  66. {pipulate-2.62 → pipulate-2.64}/imports/durable_backup_system.py +0 -0
  67. {pipulate-2.62 → pipulate-2.64}/imports/mcp_orchestrator.py +0 -0
  68. {pipulate-2.62 → pipulate-2.64}/imports/server_logging.py +0 -0
  69. {pipulate-2.62 → pipulate-2.64}/imports/stream_orchestrator.py +0 -0
  70. {pipulate-2.62 → pipulate-2.64}/imports/voice_synthesis.py +0 -0
  71. {pipulate-2.62 → pipulate-2.64}/pipulate.egg-info/SOURCES.txt +0 -0
  72. {pipulate-2.62 → pipulate-2.64}/pipulate.egg-info/dependency_links.txt +0 -0
  73. {pipulate-2.62 → pipulate-2.64}/pipulate.egg-info/entry_points.txt +0 -0
  74. {pipulate-2.62 → pipulate-2.64}/pipulate.egg-info/requires.txt +0 -0
  75. {pipulate-2.62 → pipulate-2.64}/pipulate.egg-info/top_level.txt +0 -0
  76. {pipulate-2.62 → pipulate-2.64}/setup.cfg +0 -0
  77. {pipulate-2.62 → pipulate-2.64}/tests/test_apply_airlock.py +0 -0
  78. {pipulate-2.62 → pipulate-2.64}/tests/test_mck_rep2.py +0 -0
  79. {pipulate-2.62 → pipulate-2.64}/tools/__init__.py +0 -0
  80. {pipulate-2.62 → pipulate-2.64}/tools/advanced_automation_tools.py +0 -0
  81. {pipulate-2.62 → pipulate-2.64}/tools/botify_tools.py +0 -0
  82. {pipulate-2.62 → pipulate-2.64}/tools/connector_tools.py +0 -0
  83. {pipulate-2.62 → pipulate-2.64}/tools/conversation_tools.py +0 -0
  84. {pipulate-2.62 → pipulate-2.64}/tools/dom_tools.py +0 -0
  85. {pipulate-2.62 → pipulate-2.64}/tools/keychain_tools.py +0 -0
  86. {pipulate-2.62 → pipulate-2.64}/tools/llm_optics.py +0 -0
  87. {pipulate-2.62 → pipulate-2.64}/tools/mcp_tools.py +0 -0
  88. {pipulate-2.62 → pipulate-2.64}/tools/scraper_tools.py +0 -0
  89. {pipulate-2.62 → pipulate-2.64}/tools/system_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pipulate
3
- Version: 2.62
3
+ Version: 2.64
4
4
  Summary: The context compiler that helps you prompt well — local-first, Nix-reproducible, replayable. The successor to AI SEO software.
5
5
  Author-email: Mike Levin <pipulate@gmail.com>
6
6
  License-Expression: AGPL-3.0-or-later
@@ -127,17 +127,19 @@ nix develop
127
127
  ### Where your work lives
128
128
  <!-- --- START WORKSPACE TREE --- -->
129
129
  ```text
130
- Notebooks/ — the JupyterLab root (NOT Pipulate's own root)
130
+ Workshop/ — the JupyterLab root (NOT Pipulate's own root)
131
131
  │ FLAT siblings. Nothing nests. Nothing to get wrong.
132
132
  │
133
133
  ├── Advanced_Notebooks/ canon · flake-delivered, copy-if-absent
134
134
  ├── Educational_Notebooks/ canon · your edits survive, updates do not arrive
135
135
  ├── imports/ canon · the code-behind "sauce" modules
136
136
  │
137
- ├── Playground/ personal · gitignored · your own git repo goes here
137
+ ├── personal/ personal · gitignored · your own git repo goes here
138
138
  ├── Client_Work/ personal · gitignored · never leaves this machine
139
139
  ├── Deliverables/ personal · gitignored
140
140
  │
141
+ ├── corporate/ the org's canon · gitignored · its own private repo
142
+ │
141
143
  └── Shared/ the ONE folder for handing work to a teammate
142
144
  ├── alice/ one folder per person; you write ONLY your own
143
145
  └── bob/ single-writer partitions = zero merge conflicts
@@ -70,17 +70,19 @@ nix develop
70
70
  ### Where your work lives
71
71
  <!-- --- START WORKSPACE TREE --- -->
72
72
  ```text
73
- Notebooks/ — the JupyterLab root (NOT Pipulate's own root)
73
+ Workshop/ — the JupyterLab root (NOT Pipulate's own root)
74
74
  │ FLAT siblings. Nothing nests. Nothing to get wrong.
75
75
  │
76
76
  ├── Advanced_Notebooks/ canon · flake-delivered, copy-if-absent
77
77
  ├── Educational_Notebooks/ canon · your edits survive, updates do not arrive
78
78
  ├── imports/ canon · the code-behind "sauce" modules
79
79
  │
80
- ├── Playground/ personal · gitignored · your own git repo goes here
80
+ ├── personal/ personal · gitignored · your own git repo goes here
81
81
  ├── Client_Work/ personal · gitignored · never leaves this machine
82
82
  ├── Deliverables/ personal · gitignored
83
83
  │
84
+ ├── corporate/ the org's canon · gitignored · its own private repo
85
+ │
84
86
  └── Shared/ the ONE folder for handing work to a teammate
85
87
  ├── alice/ one folder per person; you write ONLY your own
86
88
  └── bob/ single-writer partitions = zero merge conflicts
@@ -12,7 +12,7 @@ Usage:
12
12
  pipulate
13
13
  """
14
14
 
15
- __version__ = "2.62"
15
+ __version__ = "2.64"
16
16
  # APOSTROPHES RESTORED (2026-08-04). They were stripped as a workaround for
17
17
  # flake.nix's descMatch regex, whose character class excluded ' from the
18
18
  # CAPTURE and truncated the banner to "(So)". That regex was fixed in the same
@@ -23,7 +23,7 @@ __version__ = "2.62"
23
23
  # is not a property of the system; the regex is. Blast radius is one banner:
24
24
  # nothing but flake.nix reads this name -- version_sync.py syncs __version__
25
25
  # and __description__, never this. So'wI' chu' -- "engage the cloaking device."
26
- __version_description__ = "context, prompt, compile, audit"
26
+ __version_description__ = "Notebooks to Workshop"
27
27
  # SPDX expression, single source of truth, synced into pyproject.toml by
28
28
  # scripts/release/version_sync.py. "-or-later" (not bare AGPL-3.0, which is
29
29
  # deprecated SPDX) because the header below grants "any later version".
@@ -44,15 +44,15 @@ class PluginIdentityManager:
44
44
 
45
45
  @property
46
46
  def TRAINING_PROMPT(self):
47
- """Load the roles skill from Notebooks/.agents/skills/roles/SKILL.md (graceful fallback)."""
48
- skill_path = os.path.join(os.path.dirname(__file__), '..', 'Notebooks', '.agents', 'skills', 'roles', 'SKILL.md')
47
+ """Load the roles skill from Workshop/.agents/skills/roles/SKILL.md (graceful fallback)."""
48
+ skill_path = os.path.join(os.path.dirname(__file__), '..', 'Workshop', '.agents', 'skills', 'roles', 'SKILL.md')
49
49
  try:
50
50
  with open(skill_path, 'r', encoding='utf-8') as f:
51
51
  return f.read()
52
52
  except Exception:
53
53
  return (
54
54
  '# Pipulate Roles System\n\n'
55
- 'SKILL.md not found at Notebooks/.agents/skills/roles/SKILL.md. '
55
+ 'SKILL.md not found at Workshop/.agents/skills/roles/SKILL.md. '
56
56
  'The Roles app is the homepage and APP-menu control center: checkboxes toggle roles, '
57
57
  'drag reorders the APP menu, Core is always on. Secret word: ORCHESTRATOR.'
58
58
  )
@@ -66,7 +66,7 @@ FIGURATE_LEDGER: dict = {
66
66
  "canal_lock": 311868176,
67
67
  "mechanical_man": 4142234675,
68
68
  # CRC32 after _expand_color_bits_ai() + .strip()
69
- "workspace_tree": 2408173560, # CRC32 no-strip (leading newline preserved, like honeybot_pipeline)
69
+ "workspace_tree": 545211116, # CRC32 no-strip (leading newline preserved, like honeybot_pipeline); resealed 2026-09-27 for the Workshop rename, was 2408173560
70
70
  "forcing_pair": 3594006631, # CRC32 no-strip; seal re-taken 2026-07-27 — 208394658 sealed a re-typed copy of the art, not the bytes on disk; the straddle caught it (drift 1→0)
71
71
  # === FIGURATE_LEDGER_EXTRUDE_BOTTOM ===
72
72
  # Add new artwork CRC32 entries immediately above this line
@@ -536,7 +536,7 @@ def _figurate_white_rabbit():
536
536
  """
537
537
  ai_art = _expand_color_bits_ai(art)
538
538
  human_art = _expand_color_bits_human(art)
539
- human = Panel(human_art, title="🐰 ASCII Art Wax Seal (your vibe-coding safety-net)", border_style="white")
539
+ human = Panel(human_art, title="LLM Response Quality Assurance", border_style="white")
540
540
  return human, ai_art
541
541
 
542
542
  def _figurate_player_piano():
@@ -791,7 +791,7 @@ def _figurate_mechanical_man():
791
791
 
792
792
 
793
793
  def _figurate_workspace_tree():
794
- """Render the Notebooks workspace as it ACTUALLY sits on disk: flat.
794
+ """Render the Workshop as it ACTUALLY sits on disk: flat.
795
795
  THE NESTED VERSION WAS THE ONLY AUTHORITY THAT SHIPPED, AND IT WAS WRONG.
796
796
  update_agents_md_in_place() splices this art into AGENTS.md on every
797
797
  compile, so it is what every external agent tool reads -- while flake.nix
@@ -807,24 +807,26 @@ def _figurate_workspace_tree():
807
807
  _expand_color_bits_ai leaves it untouched and ai_art == art.
808
808
  """
809
809
  art = r"""
810
- Notebooks/ — the JupyterLab root (NOT Pipulate's own root)
810
+ Workshop/ — the JupyterLab root (NOT Pipulate's own root)
811
811
  │ FLAT siblings. Nothing nests. Nothing to get wrong.
812
812
  │
813
813
  ├── Advanced_Notebooks/ canon · flake-delivered, copy-if-absent
814
814
  ├── Educational_Notebooks/ canon · your edits survive, updates do not arrive
815
815
  ├── imports/ canon · the code-behind "sauce" modules
816
816
  │
817
- ├── Playground/ personal · gitignored · your own git repo goes here
817
+ ├── personal/ personal · gitignored · your own git repo goes here
818
818
  ├── Client_Work/ personal · gitignored · never leaves this machine
819
819
  ├── Deliverables/ personal · gitignored
820
820
  │
821
+ ├── corporate/ the org's canon · gitignored · its own private repo
822
+ │
821
823
  └── Shared/ the ONE folder for handing work to a teammate
822
824
  ├── alice/ one folder per person; you write ONLY your own
823
825
  └── bob/ single-writer partitions = zero merge conflicts
824
826
  """
825
827
  ai_art = _expand_color_bits_ai(art)
826
828
  human_art = _expand_color_bits_human(art)
827
- human = Panel(human_art, title="🗂️ Notebooks Workspace — canon · personal · Shared", border_style="white")
829
+ human = Panel(human_art, title="🗂️ Workshop — canon · personal · corporate · Shared", border_style="white")
828
830
  return human, ai_art
829
831
 
830
832
 
@@ -1860,7 +1862,7 @@ Rich console blocked on Mac (Error: {e}), using fallback display.
1860
1862
  # └── assets/ # optional templates and files
1861
1863
  # ```
1862
1864
  #
1863
- # You already have this. `Notebooks/.agents/skills/hello_workflow/SKILL.md`, `gsc_readonly`, `roles` — it's in your manifest.
1865
+ # You already have this. `Workshop/.agents/skills/hello_workflow/SKILL.md`, `gsc_readonly`, `roles` — it's in your manifest.
1864
1866
  #
1865
1867
  # **3. OKF** — what the v0.1 specification actually fixes is a folder layout, markdown files, YAML frontmatter, reserved filenames, and a single required field: `type`. A bundle is a directory of markdown files, each carrying a short YAML block — type, title, description — linking to its neighbors; add an index.md that lists the files so an agent can see what's there before opening everything, and that's the format. The spec fits on a single page.
1866
1868
  #
@@ -1886,7 +1888,7 @@ Rich console blocked on Mac (Error: {e}), using fallback display.
1886
1888
  # ├── cli.py # = the `allowed-tools` surface: mcp-discover / call
1887
1889
  # ├── apply.py # = "PR instructions" made executable (SEARCH/REPLACE actuator)
1888
1890
  # ├── flake.nix # = "Dev environment setup" made executable (nix develop)
1889
- # ├── Notebooks/.agents/skills/ # = Agent Skills, already standard-shaped
1891
+ # ├── Workshop/.agents/skills/ # = Agent Skills, already standard-shaped
1890
1892
  # │ ├── hello_workflow/SKILL.md
1891
1893
  # │ ├── gsc_readonly/SKILL.md
1892
1894
  # │ └── roles/SKILL.md
@@ -28,13 +28,13 @@ project_root = find_project_root(os.getcwd()) or Path.cwd()
28
28
 
29
29
  # ... after project_root is defined ...
30
30
  if project_root:
31
- notebooks_path = str(project_root / "Notebooks")
31
+ notebooks_path = str(project_root / "Workshop")
32
32
  if notebooks_path not in sys.path:
33
33
  sys.path.append(notebooks_path)
34
34
 
35
35
  # 🪄 THE FUSION DANCE: Merge core imports with user imports
36
36
  import imports
37
- notebook_imports_path = project_root / "Notebooks" / "imports"
37
+ notebook_imports_path = project_root / "Workshop" / "imports"
38
38
  if notebook_imports_path.exists() and str(notebook_imports_path) not in imports.__path__:
39
39
  imports.__path__.append(str(notebook_imports_path))
40
40
 
@@ -44,7 +44,7 @@ logger.remove()
44
44
  logger.add(sys.stderr, level="WARNING", colorize=True, format="<level>{level: <8}</level> | <cyan>{name}:{function}:{line}</cyan> - <level>{message}</level>")
45
45
 
46
46
  # 2. Instantiate the wand so we can use its Topological Manifold for paths
47
- DB_PATH = project_root / "Notebooks" / "data" / "pipeline.sqlite"
47
+ DB_PATH = project_root / "Workshop" / "data" / "pipeline.sqlite"
48
48
  DB_PATH.parent.mkdir(parents=True, exist_ok=True)
49
49
  wand = Pipulate(db_path=str(DB_PATH))
50
50
 
@@ -225,7 +225,7 @@ class Pipulate:
225
225
  class WorkspaceManifold:
226
226
  def __init__(self, root: Path, is_notebook: bool):
227
227
  self.root = root
228
- self.base = root / "Notebooks" if is_notebook else root
228
+ self.base = root / "Workshop" if is_notebook else root
229
229
  self.data = self.base / "data"
230
230
  self.logs = self.data / "logs"
231
231
  self.temp = self.data / "temp"
@@ -2437,7 +2437,7 @@ class Pipulate:
2437
2437
  def nbup(self, notebook_filename: str, modules: tuple = None):
2438
2438
  """
2439
2439
  Cleans and syncs a notebook and optionally its associated Python modules
2440
- from the working 'Notebooks/' directory back to the version-controlled
2440
+ from the working 'Workshop/' directory back to the version-controlled
2441
2441
  'assets/nbs/' template directory.
2442
2442
  """
2443
2443
  # Import necessary libraries inside the function
@@ -2536,7 +2536,7 @@ class Pipulate:
2536
2536
 
2537
2537
  # --- Notebook Sync Logic ---
2538
2538
  print(f"🔄 Syncing notebook '{notebook_filename}'...")
2539
- notebook_source_path = project_root / "Notebooks" / notebook_filename
2539
+ notebook_source_path = project_root / "Workshop" / notebook_filename
2540
2540
  notebook_dest_path = project_root / "assets" / "nbs" / notebook_filename
2541
2541
 
2542
2542
  if not notebook_source_path.exists():
@@ -2622,7 +2622,7 @@ class Pipulate:
2622
2622
  if isinstance(modules, str): modules = (modules,)
2623
2623
  for module_name in modules:
2624
2624
  module_filename = f"{module_name}.py"
2625
- module_source_path = project_root / "Notebooks" / "imports" / module_filename # Look inside imports/
2625
+ module_source_path = project_root / "Workshop" / "imports" / module_filename # Look inside imports/
2626
2626
  module_dest_path = project_root / "assets" / "nbs" / "imports" / module_filename # Sync back to imports/
2627
2627
  if module_source_path.exists():
2628
2628
  try:
@@ -3224,8 +3224,8 @@ class Pipulate:
3224
3224
  import json
3225
3225
 
3226
3226
  # 1. Explicitly define the path to the Jupyter chrysalis (ignoring current context)
3227
- jupyter_db_path = self.paths.root / "Notebooks" / "data" / "pipeline.sqlite"
3228
- sentinel_path = self.paths.root / "Notebooks" / "data" / ".onboarded"
3227
+ jupyter_db_path = self.paths.root / "Workshop" / "data" / "pipeline.sqlite"
3228
+ sentinel_path = self.paths.root / "Workshop" / "data" / ".onboarded"
3229
3229
 
3230
3230
  # 2. Safety Check: Only proceed if the chrysalis exists
3231
3231
  if not jupyter_db_path.exists():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pipulate
3
- Version: 2.62
3
+ Version: 2.64
4
4
  Summary: The context compiler that helps you prompt well — local-first, Nix-reproducible, replayable. The successor to AI SEO software.
5
5
  Author-email: Mike Levin <pipulate@gmail.com>
6
6
  License-Expression: AGPL-3.0-or-later
@@ -127,17 +127,19 @@ nix develop
127
127
  ### Where your work lives
128
128
  <!-- --- START WORKSPACE TREE --- -->
129
129
  ```text
130
- Notebooks/ — the JupyterLab root (NOT Pipulate's own root)
130
+ Workshop/ — the JupyterLab root (NOT Pipulate's own root)
131
131
  │ FLAT siblings. Nothing nests. Nothing to get wrong.
132
132
  │
133
133
  ├── Advanced_Notebooks/ canon · flake-delivered, copy-if-absent
134
134
  ├── Educational_Notebooks/ canon · your edits survive, updates do not arrive
135
135
  ├── imports/ canon · the code-behind "sauce" modules
136
136
  │
137
- ├── Playground/ personal · gitignored · your own git repo goes here
137
+ ├── personal/ personal · gitignored · your own git repo goes here
138
138
  ├── Client_Work/ personal · gitignored · never leaves this machine
139
139
  ├── Deliverables/ personal · gitignored
140
140
  │
141
+ ├── corporate/ the org's canon · gitignored · its own private repo
142
+ │
141
143
  └── Shared/ the ONE folder for handing work to a teammate
142
144
  ├── alice/ one folder per person; you write ONLY your own
143
145
  └── bob/ single-writer partitions = zero merge conflicts
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
  [project]
6
6
  name = "pipulate"
7
7
  # VERSION NOTE: Synced from pipulate/__init__.py.__version__ via python version_sync.py
8
- version = "2.62"
8
+ version = "2.64"
9
9
  authors = [
10
10
  { name="Mike Levin", email="pipulate@gmail.com" },
11
11
  ]
@@ -82,7 +82,7 @@ exclude = [
82
82
  "downloads*",
83
83
  "scripts*",
84
84
  "browser_cache*",
85
- "Notebooks*",
85
+ "Workshop*",
86
86
  ".venv*"
87
87
  ]
88
88
 
@@ -126,7 +126,7 @@ ignore = [
126
126
  # Never flag these directories
127
127
  exclude = [
128
128
  ".venv",
129
- "Notebooks",
129
+ "Workshop",
130
130
  "scripts",
131
131
  "browser_cache",
132
132
  "data",
@@ -2095,7 +2095,7 @@ async def home(request):
2095
2095
  logger.debug(f'Selected explore item: {menux}')
2096
2096
 
2097
2097
  # ---> THE NEW AIRLOCK TRIGGER <---
2098
- sentinel_path = Path("Notebooks/data/.onboarded")
2098
+ sentinel_path = Path("Workshop/data/.onboarded")
2099
2099
  # Add the database flag check here:
2100
2100
  if sentinel_path.exists() and pipulate.db.get('airlock_sealed') != 'true':
2101
2101
  logger.info("🚨 Sentinel detected and airlock unsealed. Triggering Airlock.")
@@ -3723,7 +3723,7 @@ async def reset_config_onboarding(request):
3723
3723
  # 1. Wipe the File System Sentinel
3724
3724
  try:
3725
3725
  project_root = Path(os.getcwd())
3726
- sentinel_path = project_root / "Notebooks" / "data" / ".onboarded"
3726
+ sentinel_path = project_root / "Workshop" / "data" / ".onboarded"
3727
3727
  if sentinel_path.exists():
3728
3728
  sentinel_path.unlink()
3729
3729
  logger.info(f"🗑️ Deleted sentinel file: {sentinel_path}")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes