pipulate 2.78__tar.gz → 2.80__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 (98) hide show
  1. {pipulate-2.78 → pipulate-2.80}/.agents/skills/journal/references/index.md +14 -8
  2. {pipulate-2.78 → pipulate-2.80}/PKG-INFO +1 -1
  3. {pipulate-2.78 → pipulate-2.80}/__init__.py +2 -2
  4. {pipulate-2.78 → pipulate-2.80}/pipulate.egg-info/PKG-INFO +1 -1
  5. {pipulate-2.78 → pipulate-2.80}/pyproject.toml +1 -1
  6. {pipulate-2.78 → pipulate-2.80}/tools/scraper_tools.py +28 -5
  7. {pipulate-2.78 → pipulate-2.80}/.agents/skills/gsc-readonly/SKILL.md +0 -0
  8. {pipulate-2.78 → pipulate-2.80}/.agents/skills/hello-workflow/SKILL.md +0 -0
  9. {pipulate-2.78 → pipulate-2.80}/.agents/skills/journal/SKILL.md +0 -0
  10. {pipulate-2.78 → pipulate-2.80}/.agents/skills/pipulate/SKILL.md +0 -0
  11. {pipulate-2.78 → pipulate-2.80}/.agents/skills/roles/SKILL.md +0 -0
  12. {pipulate-2.78 → pipulate-2.80}/.agents/skills/sheets-readonly/SKILL.md +0 -0
  13. {pipulate-2.78 → pipulate-2.80}/AGENTS.md +0 -0
  14. {pipulate-2.78 → pipulate-2.80}/AUDIT.md +0 -0
  15. {pipulate-2.78 → pipulate-2.80}/LICENSE +0 -0
  16. {pipulate-2.78 → pipulate-2.80}/MANIFEST.in +0 -0
  17. {pipulate-2.78 → pipulate-2.80}/README.md +0 -0
  18. {pipulate-2.78 → pipulate-2.80}/apps/010_introduction.py +0 -0
  19. {pipulate-2.78 → pipulate-2.80}/apps/015_config.py +0 -0
  20. {pipulate-2.78 → pipulate-2.80}/apps/020_profiles.py +0 -0
  21. {pipulate-2.78 → pipulate-2.80}/apps/025_aspect.py +0 -0
  22. {pipulate-2.78 → pipulate-2.80}/apps/030_roles.py +0 -0
  23. {pipulate-2.78 → pipulate-2.80}/apps/040_hello_workflow.py +0 -0
  24. {pipulate-2.78 → pipulate-2.80}/apps/050_documentation.py +0 -0
  25. {pipulate-2.78 → pipulate-2.80}/apps/060_tasks.py +0 -0
  26. {pipulate-2.78 → pipulate-2.80}/apps/070_history.py +0 -0
  27. {pipulate-2.78 → pipulate-2.80}/apps/110_parameter_buster.py +0 -0
  28. {pipulate-2.78 → pipulate-2.80}/apps/120_link_graph.py +0 -0
  29. {pipulate-2.78 → pipulate-2.80}/apps/130_gap_analysis.py +0 -0
  30. {pipulate-2.78 → pipulate-2.80}/apps/200_workflow_genesis.py +0 -0
  31. {pipulate-2.78 → pipulate-2.80}/apps/210_widget_examples.py +0 -0
  32. {pipulate-2.78 → pipulate-2.80}/apps/220_roadmap.py +0 -0
  33. {pipulate-2.78 → pipulate-2.80}/apps/230_dev_assistant.py +0 -0
  34. {pipulate-2.78 → pipulate-2.80}/apps/240_simon_mcp.py +0 -0
  35. {pipulate-2.78 → pipulate-2.80}/apps/300_blank_placeholder.py +0 -0
  36. {pipulate-2.78 → pipulate-2.80}/apps/400_botify_trifecta.py +0 -0
  37. {pipulate-2.78 → pipulate-2.80}/apps/440_browser_automation.py +0 -0
  38. {pipulate-2.78 → pipulate-2.80}/apps/450_stream_simulator.py +0 -0
  39. {pipulate-2.78 → pipulate-2.80}/apps/510_text_field.py +0 -0
  40. {pipulate-2.78 → pipulate-2.80}/apps/520_text_area.py +0 -0
  41. {pipulate-2.78 → pipulate-2.80}/apps/530_dropdown.py +0 -0
  42. {pipulate-2.78 → pipulate-2.80}/apps/540_checkboxes.py +0 -0
  43. {pipulate-2.78 → pipulate-2.80}/apps/550_radios.py +0 -0
  44. {pipulate-2.78 → pipulate-2.80}/apps/560_range.py +0 -0
  45. {pipulate-2.78 → pipulate-2.80}/apps/570_switch.py +0 -0
  46. {pipulate-2.78 → pipulate-2.80}/apps/580_upload.py +0 -0
  47. {pipulate-2.78 → pipulate-2.80}/apps/610_markdown.py +0 -0
  48. {pipulate-2.78 → pipulate-2.80}/apps/620_mermaid.py +0 -0
  49. {pipulate-2.78 → pipulate-2.80}/apps/630_prism.py +0 -0
  50. {pipulate-2.78 → pipulate-2.80}/apps/640_javascript.py +0 -0
  51. {pipulate-2.78 → pipulate-2.80}/apps/710_pandas.py +0 -0
  52. {pipulate-2.78 → pipulate-2.80}/apps/720_rich.py +0 -0
  53. {pipulate-2.78 → pipulate-2.80}/apps/730_matplotlib.py +0 -0
  54. {pipulate-2.78 → pipulate-2.80}/apps/810_webbrowser.py +0 -0
  55. {pipulate-2.78 → pipulate-2.80}/apps/820_selenium.py +0 -0
  56. {pipulate-2.78 → pipulate-2.80}/apps/830_pico_slider.py +0 -0
  57. {pipulate-2.78 → pipulate-2.80}/cli.py +0 -0
  58. {pipulate-2.78 → pipulate-2.80}/config.py +0 -0
  59. {pipulate-2.78 → pipulate-2.80}/imports/__init__.py +0 -0
  60. {pipulate-2.78 → pipulate-2.80}/imports/ai_dictdb.py +0 -0
  61. {pipulate-2.78 → pipulate-2.80}/imports/ai_tool_discovery_simple_parser.py +0 -0
  62. {pipulate-2.78 → pipulate-2.80}/imports/append_only_conversation.py +0 -0
  63. {pipulate-2.78 → pipulate-2.80}/imports/ascii_displays.py +0 -0
  64. {pipulate-2.78 → pipulate-2.80}/imports/botify/__init__.py +0 -0
  65. {pipulate-2.78 → pipulate-2.80}/imports/botify/code_generators.py +0 -0
  66. {pipulate-2.78 → pipulate-2.80}/imports/botify/true_schema_discoverer.py +0 -0
  67. {pipulate-2.78 → pipulate-2.80}/imports/botify_code_generation.py +0 -0
  68. {pipulate-2.78 → pipulate-2.80}/imports/crud.py +0 -0
  69. {pipulate-2.78 → pipulate-2.80}/imports/database_safety_wrapper.py +0 -0
  70. {pipulate-2.78 → pipulate-2.80}/imports/dom_processing/__init__.py +0 -0
  71. {pipulate-2.78 → pipulate-2.80}/imports/dom_processing/ai_dom_beautifier.py +0 -0
  72. {pipulate-2.78 → pipulate-2.80}/imports/dom_processing/enhanced_dom_processor.py +0 -0
  73. {pipulate-2.78 → pipulate-2.80}/imports/durable_backup_system.py +0 -0
  74. {pipulate-2.78 → pipulate-2.80}/imports/mcp_orchestrator.py +0 -0
  75. {pipulate-2.78 → pipulate-2.80}/imports/server_logging.py +0 -0
  76. {pipulate-2.78 → pipulate-2.80}/imports/stream_orchestrator.py +0 -0
  77. {pipulate-2.78 → pipulate-2.80}/imports/voice_synthesis.py +0 -0
  78. {pipulate-2.78 → pipulate-2.80}/pipulate/__init__.py +0 -0
  79. {pipulate-2.78 → pipulate-2.80}/pipulate/core.py +0 -0
  80. {pipulate-2.78 → pipulate-2.80}/pipulate.egg-info/SOURCES.txt +0 -0
  81. {pipulate-2.78 → pipulate-2.80}/pipulate.egg-info/dependency_links.txt +0 -0
  82. {pipulate-2.78 → pipulate-2.80}/pipulate.egg-info/entry_points.txt +0 -0
  83. {pipulate-2.78 → pipulate-2.80}/pipulate.egg-info/requires.txt +0 -0
  84. {pipulate-2.78 → pipulate-2.80}/pipulate.egg-info/top_level.txt +0 -0
  85. {pipulate-2.78 → pipulate-2.80}/server.py +0 -0
  86. {pipulate-2.78 → pipulate-2.80}/setup.cfg +0 -0
  87. {pipulate-2.78 → pipulate-2.80}/tests/test_apply_airlock.py +0 -0
  88. {pipulate-2.78 → pipulate-2.80}/tests/test_mck_rep2.py +0 -0
  89. {pipulate-2.78 → pipulate-2.80}/tools/__init__.py +0 -0
  90. {pipulate-2.78 → pipulate-2.80}/tools/advanced_automation_tools.py +0 -0
  91. {pipulate-2.78 → pipulate-2.80}/tools/botify_tools.py +0 -0
  92. {pipulate-2.78 → pipulate-2.80}/tools/connector_tools.py +0 -0
  93. {pipulate-2.78 → pipulate-2.80}/tools/conversation_tools.py +0 -0
  94. {pipulate-2.78 → pipulate-2.80}/tools/dom_tools.py +0 -0
  95. {pipulate-2.78 → pipulate-2.80}/tools/keychain_tools.py +0 -0
  96. {pipulate-2.78 → pipulate-2.80}/tools/llm_optics.py +0 -0
  97. {pipulate-2.78 → pipulate-2.80}/tools/mcp_tools.py +0 -0
  98. {pipulate-2.78 → pipulate-2.80}/tools/system_tools.py +0 -0
@@ -1,8 +1,8 @@
1
1
  # The Pipulate journal, indexed
2
2
 
3
- > Auto-generated on 2026-10-05 by `scripts/articles/generate_ai_context.py` and
3
+ > Auto-generated on 2026-10-08 by `scripts/articles/generate_ai_context.py` and
4
4
  > rewritten from scratch on every release. If this date looks stale, assume
5
- > the rest of the repo is newer than this map. 1517 entries indexed.
5
+ > the rest of the repo is newer than this map. 1523 entries indexed.
6
6
 
7
7
  This repository holds the *machinery*. The *reasoning*, the running journal
8
8
  that explains why every piece exists, lives on a separate website and not in
@@ -27,6 +27,12 @@ The first 20 entries include full `index.md` URLs to establish
27
27
  the link pattern. All remaining entries are bare slugs. Reconstruct any full
28
28
  URL as: `https://mikelev.in/futureproof/{slug}/index.md`
29
29
 
30
+ - [2026-10-08] [Jekyll Satellites: Decoupling Shared Tooling from Independent Sites with Nix](https://mikelev.in/futureproof/jekyll-satellites-shared-nix-kernel/index.md)
31
+ - [2026-10-07] [Removing the Conversion Event: When Paradigms Become Invisible Infrastructure](https://mikelev.in/futureproof/removing-the-conversion-event/index.md)
32
+ - [2026-10-07] [Public Installers, Private Entitlements, and Watching the Infrastructure Read](https://mikelev.in/futureproof/public-installers-private-entitlements-wire-telemetry/index.md)
33
+ - [2026-10-06] [Making Verification Cheaper Than Trust: The Flight Data Recorder for AI Workflows](https://mikelev.in/futureproof/making-verification-cheaper-than-trust/index.md)
34
+ - [2026-10-06] [The Router That Learned to Forget: Compaction, Pure Patches, and Earned Simplicity](https://mikelev.in/futureproof/the-router-that-learned-to-forget/index.md)
35
+ - [2026-10-06] [Declarative Editorial Context: Decoupling Publishing Targets in the AI Era](https://mikelev.in/futureproof/declarative-editorial-framing-pipeline/index.md)
30
36
  - [2026-10-04] [The Digital Thunk and Shannon's Codebook: Engineering Replayable Workflows in the Age of AI](https://mikelev.in/futureproof/digital-thunk-shannons-codebook-replayable-workflows/index.md)
31
37
  - [2026-10-04] [Learning to Walk: YAML Trails and the Quiet Skip](https://mikelev.in/futureproof/learning-to-walk-yaml-trails-and-the-quiet-skip/index.md)
32
38
  - [2026-10-04] [The Terminal House Style: Quieting the Console Without Silencing the Evidence](https://mikelev.in/futureproof/terminal-house-style-quiet-console-evidence/index.md)
@@ -41,17 +47,17 @@ URL as: `https://mikelev.in/futureproof/{slug}/index.md`
41
47
  - [2026-09-30] [Forever-Commands and the Talk Toggle: Replayable CLI Habits in the Age of AI](https://mikelev.in/futureproof/forever-commands-and-the-talk-toggle/index.md)
42
48
  - [2026-09-29] [Layered Reality and Operator Overloading: Reading the Physics of CPython in the Age of AI](https://mikelev.in/futureproof/layered-reality-operator-overloading-cpython/index.md)
43
49
  - [2026-09-29] [The Three-Door Installer: Named Prompts, Split DNS, and Verifiable Releases](https://mikelev.in/futureproof/the-three-door-installer-and-named-prompts/index.md)
44
- - [2026-09-29] [The Deed Is Named for the Door: Engineering Replayable QA Archives for AI](https://mikelev.in/futureproof/the-deed-is-named-for-the-door-qa-archive-zip/index.md)
45
- - [2026-09-29] [The Qamy Door and the Cellular Witness: Launching a Third Domain with Replayable Receipts](https://mikelev.in/futureproof/qamy-door-cellular-witness-replayable-receipts/index.md)
46
- - [2026-09-28] [The Forward-Slash Test: Bridging Agent Skills to Claude Code with Verifiable Receipts](https://mikelev.in/futureproof/the-forward-slash-test-claude-skills-bridge/index.md)
47
- - [2026-09-28] [AGENTS.md and Agent Skills: Refactoring Pipulate for a Checkable PyPI Release](https://mikelev.in/futureproof/agents-md-agent-skills-pypi-receipts/index.md)
48
- - [2026-09-28] [The Cost of Forgetting: The Epistemic Price List and the Art of the Lean Codebase](https://mikelev.in/futureproof/the-forgetting-kata-and-the-epistemic-price-list/index.md)
49
- - [2026-09-28] [Pinball, Pachinko, and the Art of Replayable AI Workflows](https://mikelev.in/futureproof/pinball-pachinko-replayable-ai-workflows/index.md)
50
50
 
51
51
  ## Compact slug index -- pattern: https://mikelev.in/futureproof/{slug}/index.md
52
52
 
53
53
  Format: `[date] [size] slug` -- fetch any entry as `https://mikelev.in/futureproof/{slug}/index.md`
54
54
 
55
+ - [2026-09-29] [234k] the-deed-is-named-for-the-door-qa-archive-zip
56
+ - [2026-09-29] [200k] qamy-door-cellular-witness-replayable-receipts
57
+ - [2026-09-28] [368k] the-forward-slash-test-claude-skills-bridge
58
+ - [2026-09-28] [241k] agents-md-agent-skills-pypi-receipts
59
+ - [2026-09-28] [172k] the-forgetting-kata-and-the-epistemic-price-list
60
+ - [2026-09-28] [24k] pinball-pachinko-replayable-ai-workflows
55
61
  - [2026-09-28] [454k] three-folder-boundary-and-the-blank-stare
56
62
  - [2026-09-26] [65k] fixing-patch-parser-failures-and-actuator-surprises
57
63
  - [2026-09-26] [460k] plain-words-verifiable-ai-context
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pipulate
3
- Version: 2.78
3
+ Version: 2.80
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
@@ -12,7 +12,7 @@ Usage:
12
12
  pipulate
13
13
  """
14
14
 
15
- __version__ = "2.78"
15
+ __version__ = "2.80"
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.78"
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__ = "Semantic Scrub"
26
+ __version_description__ = "Left Side of Boundary"
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".
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pipulate
3
- Version: 2.78
3
+ Version: 2.80
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
@@ -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.78"
8
+ version = "2.80"
9
9
  authors = [
10
10
  { name="Mike Levin", email="pipulate@gmail.com" },
11
11
  ]
@@ -267,7 +267,12 @@ def _document_candidates(cdp_events: list, domain: str, final_url: str = "") ->
267
267
  return on_host
268
268
 
269
269
 
270
- def _capture_checkpoint(stdin=None, stdout=None, before_prompt=None) -> dict:
270
+ def _capture_checkpoint(
271
+ stdin=None,
272
+ stdout=None,
273
+ before_prompt=None,
274
+ prompt="Press Enter to save the page. ",
275
+ ) -> dict:
271
276
  """Wait for Enter from the human's keyboard: the page has settled.
272
277
 
273
278
  ENTER, NOT A WORD (2026-10-02, the operator's ruling). The fence used to
@@ -328,7 +333,7 @@ def _capture_checkpoint(stdin=None, stdout=None, before_prompt=None) -> dict:
328
333
  # A CALLER'S HOOK OWNS EVERYTHING BEFORE THE PROMPT (2026-10-02):
329
334
  # the default sentences print only when no hook was given, and
330
335
  # the prompt itself says what Enter does.
331
- output_stream.write("Press Enter to save the page. ")
336
+ output_stream.write(prompt)
332
337
  output_stream.flush()
333
338
  # TYPE-AHEAD IS NOT THE SIGNAL (2026-10-02, read off a walk whose
334
339
  # third page printed "Press Enter to save the page. Saved." on one
@@ -370,7 +375,7 @@ def _capture_checkpoint(stdin=None, stdout=None, before_prompt=None) -> dict:
370
375
  pass
371
376
 
372
377
 
373
- async def _selenium_capture(params: dict, checkpoint=None) -> dict:
378
+ async def _selenium_capture(params: dict, checkpoint=None, capture_artifacts=True) -> dict:
374
379
  """
375
380
  Performs an advanced browser automation scrape of a single URL using undetected-chromedriver.
376
381
  Checks for cached data before initiating a new scrape.
@@ -731,6 +736,16 @@ async def _selenium_capture(params: dict, checkpoint=None) -> dict:
731
736
  ):
732
737
  return failure(f"browser final URL is not absolute http(s): {final_url!r}")
733
738
 
739
+ if interactive and not capture_artifacts:
740
+ return {
741
+ "success": True,
742
+ "looking_at_files": {},
743
+ "cached": False,
744
+ "requested_url": url,
745
+ "final_url": final_url,
746
+ "interactive": True,
747
+ }
748
+
734
749
  if interactive:
735
750
  final_domain, final_slug = _guided_path_component(final_url)
736
751
  output_dir = base_dir / final_domain / final_slug
@@ -1147,8 +1162,10 @@ async def selenium_automation(params: dict) -> dict:
1147
1162
  return await _selenium_capture(params)
1148
1163
 
1149
1164
 
1150
- async def guided_browser_capture(params: dict, stdin=None, stdout=None, before_prompt=None) -> dict:
1151
- """Capture one human-guided page through one visible persistent driver."""
1165
+ async def guided_browser_capture(
1166
+ params: dict, stdin=None, stdout=None, before_prompt=None, capture=True
1167
+ ) -> dict:
1168
+ """Guide one visible persistent page; capture artifacts unless capture=False."""
1152
1169
  if not isinstance(params, dict):
1153
1170
  return {
1154
1171
  "success": False,
@@ -1221,5 +1238,11 @@ async def guided_browser_capture(params: dict, stdin=None, stdout=None, before_p
1221
1238
  stdin=input_stream,
1222
1239
  stdout=stdout,
1223
1240
  before_prompt=before_prompt,
1241
+ prompt=(
1242
+ "Press Enter to save the page. "
1243
+ if capture
1244
+ else "Press Enter to continue without saving. "
1245
+ ),
1224
1246
  ),
1247
+ capture_artifacts=capture,
1225
1248
  )
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