pipulate 2.4__tar.gz → 2.42__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.4/pipulate.egg-info → pipulate-2.42}/PKG-INFO +1 -1
- {pipulate-2.4 → pipulate-2.42}/__init__.py +12 -2
- {pipulate-2.4 → pipulate-2.42}/cli.py +13 -2
- {pipulate-2.4 → pipulate-2.42}/imports/durable_backup_system.py +28 -2
- {pipulate-2.4 → pipulate-2.42/pipulate.egg-info}/PKG-INFO +1 -1
- {pipulate-2.4 → pipulate-2.42}/pyproject.toml +1 -1
- {pipulate-2.4 → pipulate-2.42}/LICENSE +0 -0
- {pipulate-2.4 → pipulate-2.42}/MANIFEST.in +0 -0
- {pipulate-2.4 → pipulate-2.42}/README.md +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/010_introduction.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/015_config.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/020_profiles.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/025_aspect.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/030_roles.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/040_hello_workflow.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/050_documentation.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/060_tasks.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/070_history.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/110_parameter_buster.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/120_link_graph.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/130_gap_analysis.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/200_workflow_genesis.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/210_widget_examples.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/220_roadmap.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/230_dev_assistant.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/240_simon_mcp.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/300_blank_placeholder.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/400_botify_trifecta.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/440_browser_automation.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/450_stream_simulator.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/510_text_field.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/520_text_area.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/530_dropdown.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/540_checkboxes.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/550_radios.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/560_range.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/570_switch.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/580_upload.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/610_markdown.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/620_mermaid.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/630_prism.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/640_javascript.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/710_pandas.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/720_rich.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/730_matplotlib.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/810_webbrowser.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/820_selenium.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/apps/830_pico_slider.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/config.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/__init__.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/ai_dictdb.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/ai_tool_discovery_simple_parser.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/append_only_conversation.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/ascii_displays.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/botify/__init__.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/botify/code_generators.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/botify/true_schema_discoverer.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/botify_code_generation.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/crud.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/database_safety_wrapper.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/dom_processing/__init__.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/dom_processing/ai_dom_beautifier.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/dom_processing/enhanced_dom_processor.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/mcp_orchestrator.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/server_logging.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/stream_orchestrator.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/imports/voice_synthesis.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/pipulate/__init__.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/pipulate/core.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/pipulate.egg-info/SOURCES.txt +0 -0
- {pipulate-2.4 → pipulate-2.42}/pipulate.egg-info/dependency_links.txt +0 -0
- {pipulate-2.4 → pipulate-2.42}/pipulate.egg-info/entry_points.txt +0 -0
- {pipulate-2.4 → pipulate-2.42}/pipulate.egg-info/requires.txt +0 -0
- {pipulate-2.4 → pipulate-2.42}/pipulate.egg-info/top_level.txt +0 -0
- {pipulate-2.4 → pipulate-2.42}/server.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/setup.cfg +0 -0
- {pipulate-2.4 → pipulate-2.42}/tests/test_mck_rep2.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/tools/__init__.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/tools/advanced_automation_tools.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/tools/botify_tools.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/tools/conversation_tools.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/tools/dom_tools.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/tools/keychain_tools.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/tools/llm_optics.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/tools/mcp_tools.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/tools/scraper_tools.py +0 -0
- {pipulate-2.4 → pipulate-2.42}/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.42
|
|
4
4
|
Summary: AI-readiness for the agentic web — local-first, Nix-reproducible workflows. The successor to AI SEO software.
|
|
5
5
|
Author-email: Mike Levin <pipulate@gmail.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -12,8 +12,18 @@ Usage:
|
|
|
12
12
|
pipulate
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
-
__version__ = "2.
|
|
16
|
-
|
|
15
|
+
__version__ = "2.42"
|
|
16
|
+
# APOSTROPHES RESTORED (2026-08-04). They were stripped as a workaround for
|
|
17
|
+
# flake.nix's descMatch regex, whose character class excluded ' from the
|
|
18
|
+
# CAPTURE and truncated the banner to "(So)". That regex was fixed in the same
|
|
19
|
+
# ride, and this line is now the only thing that exercises the fix: with the
|
|
20
|
+
# apostrophes gone, the old regex and the new one print an IDENTICAL string, so
|
|
21
|
+
# the straddle could not discriminate between a landed patch and a missing one.
|
|
22
|
+
# A convention the author has to remember ("no apostrophes in version names")
|
|
23
|
+
# is not a property of the system; the regex is. Blast radius is one banner:
|
|
24
|
+
# nothing but flake.nix reads this name -- version_sync.py syncs __version__
|
|
25
|
+
# and __description__, never this. So'wI' chu' -- "engage the cloaking device."
|
|
26
|
+
__version_description__ = "Reviving Dead Backup System"
|
|
17
27
|
# SPDX expression, single source of truth, synced into pyproject.toml by
|
|
18
28
|
# scripts/release/version_sync.py. "-or-later" (not bare AGPL-3.0, which is
|
|
19
29
|
# deprecated SPDX) because the header below grants "any later version".
|
|
@@ -428,9 +428,20 @@ def main():
|
|
|
428
428
|
uninstall_pipulate(args.app_name)
|
|
429
429
|
|
|
430
430
|
elif args.command == 'db-inspect':
|
|
431
|
+
# SAME FOSSIL, SECOND FILE (2026-08-04). db-inspect opened
|
|
432
|
+
# data/botifython_dev.db -- last written May 3 -- and printed its tables
|
|
433
|
+
# under the heading "Tables in botifython_dev.db", so an inspector built
|
|
434
|
+
# to show live state was confidently reporting a dead file's contents.
|
|
435
|
+
# Derived from the same identity value as the backup roster next door.
|
|
436
|
+
try:
|
|
437
|
+
from config import APP_NAME
|
|
438
|
+
app_stem = APP_NAME.lower()
|
|
439
|
+
except Exception as e:
|
|
440
|
+
console.print(f"⚠️ Could not resolve app name from config ({e}); assuming 'pipulate'.")
|
|
441
|
+
app_stem = 'pipulate'
|
|
431
442
|
db_map = {
|
|
432
|
-
'main_dev': 'data/
|
|
433
|
-
'main_prod': 'data/
|
|
443
|
+
'main_dev': f'data/{app_stem}_dev.db',
|
|
444
|
+
'main_prod': f'data/{app_stem}.db',
|
|
434
445
|
'discussion': 'data/discussion.db',
|
|
435
446
|
'keychain': 'data/ai_keychain.db'
|
|
436
447
|
}
|
|
@@ -60,6 +60,32 @@ class DurableBackupManager:
|
|
|
60
60
|
logger.debug(f"Could not set backup directory permissions: {e}")
|
|
61
61
|
|
|
62
62
|
logger.info(f"🗃️ Rolling backup root: {self.backup_root}")
|
|
63
|
+
# THE ROSTER IS DERIVED, NOT LITERAL (2026-08-04, fossil-convicted on
|
|
64
|
+
# the maintainer's own box). The app database filename is a pure
|
|
65
|
+
# function of whitelabel.txt: config.py builds data/{APP_NAME.lower()}.db
|
|
66
|
+
# and server.py:322 independently builds the same string. This roster
|
|
67
|
+
# hardcoded 'botifython'. whitelabel.txt here says Pipulate, so the live
|
|
68
|
+
# databases are data/pipulate*.db (mtime Jul 30) while the roster kept
|
|
69
|
+
# copying data/botifython_dev.db (mtime MAY 3) once per server start,
|
|
70
|
+
# forever. The distinct backup stems were ai_keychain / botifython /
|
|
71
|
+
# botifython_dev / discussion: the live Profiles/Tasks database had NEVER
|
|
72
|
+
# been backed up, and the two stale files are exactly what hid it --
|
|
73
|
+
# os.path.exists returned True, no warning fired, and the summary table
|
|
74
|
+
# printed a green checkmark beside a file nobody had touched in three
|
|
75
|
+
# months. A stranger with only one family at least gets a "not found"
|
|
76
|
+
# line in a log. THE DERIVED-PATH RULE: compute the target from an
|
|
77
|
+
# identity value you read and cannot author, so the mismatch becomes
|
|
78
|
+
# unrepresentable instead of merely unlikely.
|
|
79
|
+
try:
|
|
80
|
+
from config import get_app_name
|
|
81
|
+
app_stem = get_app_name().lower()
|
|
82
|
+
except Exception as e:
|
|
83
|
+
# Fail LOUD, then mirror config.py's own basename rule. A silent
|
|
84
|
+
# fallback would be the same disease this patch is curing.
|
|
85
|
+
logger.warning(f"⚠️ Could not resolve app name from config ({e}); "
|
|
86
|
+
f"deriving the backup roster from the install directory name.")
|
|
87
|
+
root_name = Path(__file__).resolve().parent.parent.name
|
|
88
|
+
app_stem = (root_name[:-5] if root_name.endswith('-main') else root_name).lower()
|
|
63
89
|
|
|
64
90
|
# 🎯 CRITICAL DATABASES TO PROTECT
|
|
65
91
|
self.critical_databases = {
|
|
@@ -76,13 +102,13 @@ class DurableBackupManager:
|
|
|
76
102
|
'cross_cutting': True
|
|
77
103
|
},
|
|
78
104
|
'app_prod': {
|
|
79
|
-
'source_path': 'data/
|
|
105
|
+
'source_path': f'data/{app_stem}.db',
|
|
80
106
|
'description': 'Production Profiles/Tasks',
|
|
81
107
|
'critical': True,
|
|
82
108
|
'cross_cutting': False
|
|
83
109
|
},
|
|
84
110
|
'app_dev': {
|
|
85
|
-
'source_path': 'data/
|
|
111
|
+
'source_path': f'data/{app_stem}_dev.db',
|
|
86
112
|
'description': 'Development Profiles/Tasks',
|
|
87
113
|
'critical': False,
|
|
88
114
|
'cross_cutting': False
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pipulate
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.42
|
|
4
4
|
Summary: AI-readiness for the agentic web — local-first, Nix-reproducible workflows. The successor to AI SEO software.
|
|
5
5
|
Author-email: Mike Levin <pipulate@gmail.com>
|
|
6
6
|
License-Expression: AGPL-3.0-or-later
|
|
@@ -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.42"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name="Mike Levin", email="pipulate@gmail.com" },
|
|
11
11
|
]
|
|
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
|
|
File without changes
|
|
File without changes
|