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.
- {pipulate-2.62/pipulate.egg-info → pipulate-2.64}/PKG-INFO +5 -3
- {pipulate-2.62 → pipulate-2.64}/README.md +4 -2
- {pipulate-2.62 → pipulate-2.64}/__init__.py +2 -2
- {pipulate-2.62 → pipulate-2.64}/apps/030_roles.py +3 -3
- {pipulate-2.62 → pipulate-2.64}/imports/ascii_displays.py +10 -8
- {pipulate-2.62 → pipulate-2.64}/pipulate/__init__.py +3 -3
- {pipulate-2.62 → pipulate-2.64}/pipulate/core.py +6 -6
- {pipulate-2.62 → pipulate-2.64/pipulate.egg-info}/PKG-INFO +5 -3
- {pipulate-2.62 → pipulate-2.64}/pyproject.toml +3 -3
- {pipulate-2.62 → pipulate-2.64}/server.py +2 -2
- {pipulate-2.62 → pipulate-2.64}/LICENSE +0 -0
- {pipulate-2.62 → pipulate-2.64}/MANIFEST.in +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/010_introduction.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/015_config.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/020_profiles.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/025_aspect.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/040_hello_workflow.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/050_documentation.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/060_tasks.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/070_history.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/110_parameter_buster.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/120_link_graph.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/130_gap_analysis.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/200_workflow_genesis.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/210_widget_examples.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/220_roadmap.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/230_dev_assistant.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/240_simon_mcp.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/300_blank_placeholder.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/400_botify_trifecta.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/440_browser_automation.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/450_stream_simulator.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/510_text_field.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/520_text_area.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/530_dropdown.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/540_checkboxes.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/550_radios.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/560_range.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/570_switch.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/580_upload.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/610_markdown.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/620_mermaid.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/630_prism.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/640_javascript.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/710_pandas.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/720_rich.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/730_matplotlib.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/810_webbrowser.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/820_selenium.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/apps/830_pico_slider.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/cli.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/config.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/__init__.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/ai_dictdb.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/ai_tool_discovery_simple_parser.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/append_only_conversation.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/botify/__init__.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/botify/code_generators.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/botify/true_schema_discoverer.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/botify_code_generation.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/crud.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/database_safety_wrapper.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/dom_processing/__init__.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/dom_processing/ai_dom_beautifier.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/dom_processing/enhanced_dom_processor.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/durable_backup_system.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/mcp_orchestrator.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/server_logging.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/stream_orchestrator.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/imports/voice_synthesis.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/pipulate.egg-info/SOURCES.txt +0 -0
- {pipulate-2.62 → pipulate-2.64}/pipulate.egg-info/dependency_links.txt +0 -0
- {pipulate-2.62 → pipulate-2.64}/pipulate.egg-info/entry_points.txt +0 -0
- {pipulate-2.62 → pipulate-2.64}/pipulate.egg-info/requires.txt +0 -0
- {pipulate-2.62 → pipulate-2.64}/pipulate.egg-info/top_level.txt +0 -0
- {pipulate-2.62 → pipulate-2.64}/setup.cfg +0 -0
- {pipulate-2.62 → pipulate-2.64}/tests/test_apply_airlock.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/tests/test_mck_rep2.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/tools/__init__.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/tools/advanced_automation_tools.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/tools/botify_tools.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/tools/connector_tools.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/tools/conversation_tools.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/tools/dom_tools.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/tools/keychain_tools.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/tools/llm_optics.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/tools/mcp_tools.py +0 -0
- {pipulate-2.62 → pipulate-2.64}/tools/scraper_tools.py +0 -0
- {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.
|
|
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
|
-
|
|
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
|
-
├──
|
|
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
|
-
|
|
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
|
-
├──
|
|
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.
|
|
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__ = "
|
|
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
|
|
48
|
-
skill_path = os.path.join(os.path.dirname(__file__), '..', '
|
|
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
|
|
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":
|
|
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="
|
|
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
|
|
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
|
-
|
|
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
|
-
├──
|
|
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="🗂️
|
|
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. `
|
|
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
|
-
# ├──
|
|
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 / "
|
|
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 / "
|
|
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 / "
|
|
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 / "
|
|
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 '
|
|
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 / "
|
|
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 / "
|
|
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 / "
|
|
3228
|
-
sentinel_path = self.paths.root / "
|
|
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.
|
|
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
|
-
|
|
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
|
-
├──
|
|
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.
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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("
|
|
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 / "
|
|
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
|
|
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
|