Recent changes to this wiki:

Added a comment: Nice read
diff --git a/blog/entry/2020_hindsight/comment_1_3b6e1a0505889857385d4890c5e764b6._comment b/blog/entry/2020_hindsight/comment_1_3b6e1a0505889857385d4890c5e764b6._comment
new file mode 100644
index 00000000..8f81ff8b
--- /dev/null
+++ b/blog/entry/2020_hindsight/comment_1_3b6e1a0505889857385d4890c5e764b6._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="lioh@d60e27fddf08ba15c63b2b18e9521d7bc3453bb1"
+ nickname="lioh"
+ avatar="http://cdn.libravatar.org/avatar/65fa804f4ec5498f7b31a799aff0974d"
+ subject="Nice read"
+ date="2020-01-07T05:54:14Z"
+ content="""
+Thanks for sharing. Very interesting read. I wish you all the best on your way.
+"""]]

calendar update
diff --git a/blog/archives/2020.mdwn b/blog/archives/2020.mdwn
new file mode 100644
index 00000000..5b77de98
--- /dev/null
+++ b/blog/archives/2020.mdwn
@@ -0,0 +1 @@
+[[!calendar type=year year=2020 pages="blog/entry/* and !*/Discussion"]]
diff --git a/blog/archives/2020/01.mdwn b/blog/archives/2020/01.mdwn
new file mode 100644
index 00000000..b3a1b3cc
--- /dev/null
+++ b/blog/archives/2020/01.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=01 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(01) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2020/02.mdwn b/blog/archives/2020/02.mdwn
new file mode 100644
index 00000000..94ecd2cc
--- /dev/null
+++ b/blog/archives/2020/02.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=02 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(02) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2020/03.mdwn b/blog/archives/2020/03.mdwn
new file mode 100644
index 00000000..7340dfe1
--- /dev/null
+++ b/blog/archives/2020/03.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=03 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(03) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2020/04.mdwn b/blog/archives/2020/04.mdwn
new file mode 100644
index 00000000..d24c3726
--- /dev/null
+++ b/blog/archives/2020/04.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=04 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(04) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2020/05.mdwn b/blog/archives/2020/05.mdwn
new file mode 100644
index 00000000..bb0c2006
--- /dev/null
+++ b/blog/archives/2020/05.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=05 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(05) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2020/06.mdwn b/blog/archives/2020/06.mdwn
new file mode 100644
index 00000000..83d8ca9e
--- /dev/null
+++ b/blog/archives/2020/06.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=06 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(06) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2020/07.mdwn b/blog/archives/2020/07.mdwn
new file mode 100644
index 00000000..f173ac48
--- /dev/null
+++ b/blog/archives/2020/07.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=07 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(07) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2020/08.mdwn b/blog/archives/2020/08.mdwn
new file mode 100644
index 00000000..0c954fd9
--- /dev/null
+++ b/blog/archives/2020/08.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=08 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(08) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2020/09.mdwn b/blog/archives/2020/09.mdwn
new file mode 100644
index 00000000..695319b9
--- /dev/null
+++ b/blog/archives/2020/09.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=09 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(09) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2020/10.mdwn b/blog/archives/2020/10.mdwn
new file mode 100644
index 00000000..661cf045
--- /dev/null
+++ b/blog/archives/2020/10.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=10 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(10) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2020/11.mdwn b/blog/archives/2020/11.mdwn
new file mode 100644
index 00000000..48fb75f4
--- /dev/null
+++ b/blog/archives/2020/11.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=11 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(11) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]
diff --git a/blog/archives/2020/12.mdwn b/blog/archives/2020/12.mdwn
new file mode 100644
index 00000000..8b3218be
--- /dev/null
+++ b/blog/archives/2020/12.mdwn
@@ -0,0 +1,5 @@
+[[!sidebar content="""
+[[!calendar type=month month=12 year=2020 pages="blog/entry/* and !*/Discussion"]]
+"""]]
+
+[[!inline pages="creation_month(12) and creation_year(2020) and blog/entry/* and !*/Discussion" show=0 feeds=no reverse=yes]]

typo
diff --git a/blog/entry/2020_hindsight.mdwn b/blog/entry/2020_hindsight.mdwn
index 7c95db52..141aa802 100644
--- a/blog/entry/2020_hindsight.mdwn
+++ b/blog/entry/2020_hindsight.mdwn
@@ -36,7 +36,7 @@ After two idyllic years of depleting savings, I did a Kickstarter for
 git-annex and raised not much, but I was now living on very little, so that
 was a [[nice windfall|the_rocket]]. I went full crowdfunding for a couple
 of years. After a while, I started getting contracting work,
-supplimenting the croudfunding, as git-annex found use in science
+supplementing the croudfunding, as git-annex found use in science
 and education. Both have continued ever since, amazingly.
 
 I was free to do whatever I wanted to. A lot of that was

post
diff --git a/blog/entry/2020_hindsight.mdwn b/blog/entry/2020_hindsight.mdwn
index 9bacd239..7c95db52 100644
--- a/blog/entry/2020_hindsight.mdwn
+++ b/blog/entry/2020_hindsight.mdwn
@@ -3,66 +3,71 @@ and suggested I write a followup...)
 
 This has been a big decade for me.
 
-Ten years ago, I'd been in an increasingly stale job for several years
-too long. I was tired of living in the city, and had a yurt as a weekend
-relief valve. I had the feeling a big change was coming.
+[[Ten years ago|naught_but_a_decade]], I'd been in an increasingly stale
+job for several years too long. I was tired of living in the city, and had
+a yurt as a weekend relief valve. I had the feeling a big change was
+coming.
 
 Four months on and I quit my job, despite the ongoing financial crisis
 making prospects poor for other employment, especially work on free software.
 
-I tried to start a business, Branchable, with liw, based on my
-earlier ikiwiki project, but it never really took off. However, I'm proud
+I tried to start a business, Branchable, with liw, based on my earlier
+[[code/ikiwiki]] project, but it never really took off. However, I'm proud
 it's still serving the users it did find, 10 years later.
 
 Then, through luck and connections, I found a patch of land in a blank spot
-in the map with the most absurd rent ever ($5/acre/month). It had a house on
-it, no running water, barely solar power, a phone line, no cell service or
+in the map with the most absurd rent ever ($5/acre/month). It had a 
+[[house|old_house]] on it, no running water, 
+[[barely solar power|solar_day_2]], a phone line, no cell service or
 internet, total privacy.
 
 This proved very inspiring. Once again I was hauling water, chopping wood,
-poking at web pages on the other end of a dialup modem. Just like it were
-2000 again. Now I was also hacking by candle-light until the ancient
-batteries got so depleted I could hear the voltage regulator crackle with
-every surge of CPU activity.
+[poking at web pages on the other end of a dialup modem](https://1-minute-modem.branchable.com/).
+Just like it was 2000 again. Now I was also hacking by lantern-light until
+the [[ancient batteries|solar_year]] got so depleted I could hear the
+voltage regulator crackle with every surge of CPU activity.
 
 I had wanted to learn Haskell, but could never concentrate on it enough. I
-learned me some Haskell and I wrote [[code/git-annex]], my first real world
+learned me some Haskell and wrote [[code/git-annex]], my first real world
 Haskell program, to help me deal with shuttling data back and forth from
 civilization on sneakernet.
 
-After two years of depleting savings, I did a Kickstarter for git-annex and
-raised not much, but I was now living on very little, so that
-was a nice windfall. I went full crowdfunding for a couple of years.
-After a while, I started getting contracting work on git-annex,
-supplimenting the croudfunding. Both have continued ever since, amazingly.
+After two idyllic years of depleting savings, I did a Kickstarter for
+git-annex and raised not much, but I was now living on very little, so that
+was a [[nice windfall|the_rocket]]. I went full crowdfunding for a couple
+of years. After a while, I started getting contracting work,
+supplimenting the croudfunding, as git-annex found use in science
+and education. Both have continued ever since, amazingly.
 
-I was free and working on whatever I wanted to. A lot of that was
+I was free to do whatever I wanted to. A lot of that was
 git-annex, with some Debian, and some smaller projects, too many to list
 here.
 
-Then in 2014, I left the Debian project. I'm still sad, still miss
-everybody, but I also think, if I had not been so free, I would not have
+Then, mid-decade, I left the Debian project. I'm still sad, still miss
+everybody, but I also think, had I not been so free, I would not have
 been able to leave it. It had driven most of my career before this point.
 I was lucky to be able to leave Debian. 💧
 
-Adding to the stress, my patch of countryside was being sold out from under me.
-I considered moving to some city, but the income that's freeing here would be
-barely getting by there. I bought the place, using git-annex income,
-plus a crucial loan from a wonderful friend.
+Adding to the stress of that, my patch of countryside was being sold out
+from under me. I considered moving to some city, but the income that's
+freeing here would be barely getting by there. Instead, I bought the place,
+using git-annex income, plus a crucial loan from a wonderful friend.
 
 That changed how I dealt with being offgrid. Before it was an interesting
 constraint, something to adapt to, an added texture to life. Now it's all of
-those and also a source of inspiration and learning. How to install solar
-panels on a roof. How to wire things to code. Circuit design. Plumbing.
-Ditch digging. Functional reactive programming for automation.
-With my [[offgrid fridge|code/fride0]] project, offgrid things 
-are getting interdisciplinary in ways my work has not been before.
+those and also a source of inspiration and learning. How to 
+[[install solar panels on a roof|DIY_professional_grade_solar_panel_installation]].
+How to wire things to code. [[Circuit design|AIMS_inverter_control_via_GPIO_ports]].
+[[Plumbing|hacking_water]]. [[Ditch digging|hacking_water]].
+With my [[offgrid fridge|code/fridge0]] project, things are feeling
+interdisciplinary in ways my work has not been before.
+
+From here at its end, this decade feels both inevitable and highly unlikely.
+Now I feel.. comfortable. Settled. Surely older. More unsure of myself
+than ever really, nearly everything is more complicated than I used to think
+it was. Maybe a little stuck? But not really.
 
-From here, this decade feels both inevitable and highly unlikely.
-Now I feel.. comfortable. Settled. Maybe a little stuck? But not really.
 I'm planting fruit trees, something says I will be here to enjoy them.
-But times are getting interesting. Anything could be around the corner.
+But times are getting beyond interesting. Anything could be around the corner.
 
 [[!tag lay]]
-
-[[!tag unfinished]]

blog update
diff --git a/blog/entry/2020_hindsight.mdwn b/blog/entry/2020_hindsight.mdwn
new file mode 100644
index 00000000..9bacd239
--- /dev/null
+++ b/blog/entry/2020_hindsight.mdwn
@@ -0,0 +1,68 @@
+(Someone stumbled upon my [[2010 decade retrospective post|naught_but_a_decade]]
+and suggested I write a followup...)
+
+This has been a big decade for me.
+
+Ten years ago, I'd been in an increasingly stale job for several years
+too long. I was tired of living in the city, and had a yurt as a weekend
+relief valve. I had the feeling a big change was coming.
+
+Four months on and I quit my job, despite the ongoing financial crisis
+making prospects poor for other employment, especially work on free software.
+
+I tried to start a business, Branchable, with liw, based on my
+earlier ikiwiki project, but it never really took off. However, I'm proud
+it's still serving the users it did find, 10 years later.
+
+Then, through luck and connections, I found a patch of land in a blank spot
+in the map with the most absurd rent ever ($5/acre/month). It had a house on
+it, no running water, barely solar power, a phone line, no cell service or
+internet, total privacy.
+
+This proved very inspiring. Once again I was hauling water, chopping wood,
+poking at web pages on the other end of a dialup modem. Just like it were
+2000 again. Now I was also hacking by candle-light until the ancient
+batteries got so depleted I could hear the voltage regulator crackle with
+every surge of CPU activity.
+
+I had wanted to learn Haskell, but could never concentrate on it enough. I
+learned me some Haskell and I wrote [[code/git-annex]], my first real world
+Haskell program, to help me deal with shuttling data back and forth from
+civilization on sneakernet.
+
+After two years of depleting savings, I did a Kickstarter for git-annex and
+raised not much, but I was now living on very little, so that
+was a nice windfall. I went full crowdfunding for a couple of years.
+After a while, I started getting contracting work on git-annex,
+supplimenting the croudfunding. Both have continued ever since, amazingly.
+
+I was free and working on whatever I wanted to. A lot of that was
+git-annex, with some Debian, and some smaller projects, too many to list
+here.
+
+Then in 2014, I left the Debian project. I'm still sad, still miss
+everybody, but I also think, if I had not been so free, I would not have
+been able to leave it. It had driven most of my career before this point.
+I was lucky to be able to leave Debian. 💧
+
+Adding to the stress, my patch of countryside was being sold out from under me.
+I considered moving to some city, but the income that's freeing here would be
+barely getting by there. I bought the place, using git-annex income,
+plus a crucial loan from a wonderful friend.
+
+That changed how I dealt with being offgrid. Before it was an interesting
+constraint, something to adapt to, an added texture to life. Now it's all of
+those and also a source of inspiration and learning. How to install solar
+panels on a roof. How to wire things to code. Circuit design. Plumbing.
+Ditch digging. Functional reactive programming for automation.
+With my [[offgrid fridge|code/fride0]] project, offgrid things 
+are getting interdisciplinary in ways my work has not been before.
+
+From here, this decade feels both inevitable and highly unlikely.
+Now I feel.. comfortable. Settled. Maybe a little stuck? But not really.
+I'm planting fruit trees, something says I will be here to enjoy them.
+But times are getting interesting. Anything could be around the corner.
+
+[[!tag lay]]
+
+[[!tag unfinished]]

comment
diff --git a/blog/archives/2010/01/discussion.mdwn b/blog/archives/2010/01/discussion.mdwn
new file mode 100644
index 00000000..60b6956e
--- /dev/null
+++ b/blog/archives/2010/01/discussion.mdwn
@@ -0,0 +1 @@
+As the sun sets on another decade, I hope you post another writing reflecting on the past 10 years, the changes, and some milestones. I hope to join you in my own western island of Offgridistan in the not-so-distant future.

comment
diff --git a/blog/entry/announcing_the_filepath-bytestring_haskell_library/comment_1_b8887a5557ff195ddacb67f3ea8e3c80._comment b/blog/entry/announcing_the_filepath-bytestring_haskell_library/comment_1_b8887a5557ff195ddacb67f3ea8e3c80._comment
new file mode 100644
index 00000000..e2a222a4
--- /dev/null
+++ b/blog/entry/announcing_the_filepath-bytestring_haskell_library/comment_1_b8887a5557ff195ddacb67f3ea8e3c80._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2019-12-11T19:02:06Z"
+ content="""
+Using this library in git-annex, I saw a real-world speedup of 30%
+in `git annex find`. That command has to read a list of files from 
+`git ls-files`, and read all their symlinks, and check if the symlinks are
+broken or not. So there's a fair amount of IO, but FilePath overhead was
+still significant and worth eliminating.
+"""]]

blog update
diff --git a/blog/entry/announcing_the_filepath-bytestring_haskell_library.mdwn b/blog/entry/announcing_the_filepath-bytestring_haskell_library.mdwn
new file mode 100644
index 00000000..ff684617
--- /dev/null
+++ b/blog/entry/announcing_the_filepath-bytestring_haskell_library.mdwn
@@ -0,0 +1,22 @@
+[filepath-bytestring](https://hackage.haskell.org/package/filepath-bytestring)
+is a drop-in replacement for the standard haskell
+[filepath](https://hackage.haskell.org/package/filepath)
+library, that operates on RawFilePath rather than FilePath.
+
+The benefit, of course, is speed. `"foo" </> "bar"` is around 25% faster
+with the new library. `dropTrailingPathSeparator`
+is 120% faster. But the real speed benefits probably come when a program
+is able to input filepaths as ByteStrings, manipulate them, and operate
+on the files, all without using String.
+
+It's extensively tested, not only does it run all the same doctests
+that the filepath library does, but each function is quickchecked to
+behave the same as the equivilant function from filepath.
+
+While I implemented almost everything, I did leave
+off some functions that operate on PATH, which seem unlikely to be useful,
+and the complicated `normalise` and stuff that uses it.
+
+This work was sponsored by Jake Vosloo [on Patron](https://patreon.com/joeyh/).
+
+[[!tag code/haskell-filepath-bytestring haskell]]

add
diff --git a/code.mdwn b/code.mdwn
index 29cc1a79..1b9d8389 100644
--- a/code.mdwn
+++ b/code.mdwn
@@ -19,6 +19,7 @@ The stuff that's swapped into my local cache at the moment.
 [[reactive-banana-automation]]
 [[easy-peasy-devicetree-squeezy]]
 [[fridge0]]
+[[haskell-filepath-bytestring]]
 
 ## Less active projects
 
diff --git a/code/haskell-filepath-bytestring.mdwn b/code/haskell-filepath-bytestring.mdwn
new file mode 100644
index 00000000..d93b3dbd
--- /dev/null
+++ b/code/haskell-filepath-bytestring.mdwn
@@ -0,0 +1,3 @@
+haskell library like `filepath` but for RawFilePaths.
+
+<http://hackage.haskell.org/package/filepath-bytestring>

Added a comment: other data beside emails?
diff --git a/blog/entry/counterpoint_on_Yahoo_Groups_archiving/comment_1_9ce30dd3e43877e654c538dde1fd14db._comment b/blog/entry/counterpoint_on_Yahoo_Groups_archiving/comment_1_9ce30dd3e43877e654c538dde1fd14db._comment
new file mode 100644
index 00000000..2cbfdfe1
--- /dev/null
+++ b/blog/entry/counterpoint_on_Yahoo_Groups_archiving/comment_1_9ce30dd3e43877e654c538dde1fd14db._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="valhalla-l@e2780e0d58d6ecca363abfbfa3e831cb7ff27b6b"
+ nickname="valhalla-l"
+ avatar="http://cdn.libravatar.org/avatar/a07f8021309ce9a02c37940c99a8ae12"
+ subject="other data beside emails?"
+ date="2019-12-10T16:40:55Z"
+ content="""
+As far as I remember, yahoo groups didn't just offer a mailing list, but also storage for shared files (and I've seen the feature used extensively); those files haven't been pushed to anybody's mailbox and so are at a higher risk of disappearing (if the submitter doesn't have them properly¹ backed up themselves and is still available to re-upload them elsewhere, of course).
+
+¹ once locally for ease of retrieval, once 30km away, 30 meters up from ground level, once 30 km away from both locations, 30 meters underground.
+"""]]

Added a comment
diff --git a/blog/entry/how_I_maybe_didnt_burn_out/comment_5_e78e4e720e49b844b5911b40d4bd77cf._comment b/blog/entry/how_I_maybe_didnt_burn_out/comment_5_e78e4e720e49b844b5911b40d4bd77cf._comment
new file mode 100644
index 00000000..58c627e1
--- /dev/null
+++ b/blog/entry/how_I_maybe_didnt_burn_out/comment_5_e78e4e720e49b844b5911b40d4bd77cf._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="CandyAngel"
+ avatar="http://cdn.libravatar.org/avatar/15c0aade8bec5bf004f939dd73cf9ed8"
+ subject="comment 5"
+ date="2019-12-10T13:01:25Z"
+ content="""
+I would have been happy to help, you only had to ask.
+"""]]

typo
diff --git a/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn b/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn
index eec9baa4..7cf6870c 100644
--- a/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn
+++ b/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn
@@ -4,7 +4,7 @@ they're deleting these mailing list archives, and
 [blocking attempts to save them](https://modsandmembersblog.wordpress.com/2019/12/08/verizon-yahoo-bad-form/)
 and so huge amount of things will be lost from the historical record.
 
-That's a common story these data, but it's not entirely accurate in this
+That's a common story these days, but it's not entirely accurate in this
 case. These are mailing lists, so they're not necessarily only archived by
 Yahoo. Anyone who subscribed to a mailing list may have archived it. I've
 been on a couple of those mailing lists, and the emails I kept from them are

typo
diff --git a/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn b/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn
index 8e9a4238..eec9baa4 100644
--- a/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn
+++ b/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn
@@ -7,7 +7,7 @@ and so huge amount of things will be lost from the historical record.
 That's a common story these data, but it's not entirely accurate in this
 case. These are mailing lists, so they're not necessarily only archived by
 Yahoo. Anyone who subscribed to a mailing list may have archived it. I've
-been on a couple of those mailing lists, and the email I kept from them are
+been on a couple of those mailing lists, and the emails I kept from them are
 already archived rather well (10+ copies). I probably didn't keep every
 email, and I probably won't be exhuming those emails to add them to some
 large archive.org collection of Yahoo Groups. But multiply all the people

link
diff --git a/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn b/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn
index 0d8a92e7..8e9a4238 100644
--- a/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn
+++ b/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn
@@ -20,3 +20,5 @@ enough to satisfy a historian.
 
 Probably even after Gmail and the other cloud mail services shut down and
 delete all *their* archives.
+
+Previously: [[I_am_ArchiveTeam]] (but not speaking for them above)

blog update
diff --git a/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn b/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn
new file mode 100644
index 00000000..0d8a92e7
--- /dev/null
+++ b/blog/entry/counterpoint_on_Yahoo_Groups_archiving.mdwn
@@ -0,0 +1,22 @@
+Yahoo Groups being shut down and the data deleted is a big enough story
+that it's being talked about on the radio. The typical presentation is that
+they're deleting these mailing list archives, and
+[blocking attempts to save them](https://modsandmembersblog.wordpress.com/2019/12/08/verizon-yahoo-bad-form/)
+and so huge amount of things will be lost from the historical record.
+
+That's a common story these data, but it's not entirely accurate in this
+case. These are mailing lists, so they're not necessarily only archived by
+Yahoo. Anyone who subscribed to a mailing list may have archived it. I've
+been on a couple of those mailing lists, and the email I kept from them are
+already archived rather well (10+ copies). I probably didn't keep every
+email, and I probably won't be exhuming those emails to add them to some
+large archive.org collection of Yahoo Groups. But multiply all the people
+who subscribed to these lists by all the traffic to them, by the
+probability that people keep copies of mailing list mails, and there's a
+huge, well-distributed archive of Yahoo Groups out there.
+
+That ensures some of it will survive in the historical record, probably
+enough to satisfy a historian.
+
+Probably even after Gmail and the other cloud mail services shut down and
+delete all *their* archives.

post
diff --git a/blog/entry/left_handed_scissors.mdwn b/blog/entry/left_handed_scissors.mdwn
new file mode 100644
index 00000000..4dc864f9
--- /dev/null
+++ b/blog/entry/left_handed_scissors.mdwn
@@ -0,0 +1,8 @@
+They return my hand's grasp, smotheringly close. Was this how it was meant
+to feel, in a classroom cutting multi-colored construction paper? Not a pain
+to be gotten through, but comfort, closeness, togetherness. Their design
+now feels aggressively overdone, broad curve just so around the thumb,
+as if they might tighten and snap it off. Only too large index finger's
+knuckle, chafing, provides some relief, some reminder that I shouldn't run.
+
+(Thanks, liw.)

Added a comment: Thanks Joey for all your labor over the years
diff --git a/blog/entry/how_I_maybe_didnt_burn_out/comment_4_012b4cefa227327121b8ef9e93bf8088._comment b/blog/entry/how_I_maybe_didnt_burn_out/comment_4_012b4cefa227327121b8ef9e93bf8088._comment
new file mode 100644
index 00000000..55b33f0c
--- /dev/null
+++ b/blog/entry/how_I_maybe_didnt_burn_out/comment_4_012b4cefa227327121b8ef9e93bf8088._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="eric@32f82325cb666b88570a0d152d9605f5f5923e78"
+ nickname="eric"
+ avatar="http://cdn.libravatar.org/avatar/fbecd2cf5679e59a46df57e550fa6e51"
+ subject="Thanks Joey for all your labor over the years"
+ date="2019-11-25T10:21:07Z"
+ content="""
+I'm an Ikiwiki user since way back and am finally about to deploy git-annex across my devices after too many data losses with syncthing.
+
+I have always been inspired by your work and ethics. It's tough to find good role models so thank you.
+"""]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index 1717fcdf..270458c9 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 59 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 60 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

Added a comment: Off-topic
diff --git a/blog/entry/how_I_maybe_didnt_burn_out/comment_3_8b0295c9e6bdb28eb2e01dca7a513081._comment b/blog/entry/how_I_maybe_didnt_burn_out/comment_3_8b0295c9e6bdb28eb2e01dca7a513081._comment
new file mode 100644
index 00000000..afeea16f
--- /dev/null
+++ b/blog/entry/how_I_maybe_didnt_burn_out/comment_3_8b0295c9e6bdb28eb2e01dca7a513081._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="meribold"
+ avatar="http://cdn.libravatar.org/avatar/8cfdfc37c8459a7320aa6bb9f2689112"
+ subject="Off-topic"
+ date="2019-11-03T06:18:57Z"
+ content="""
+I just want to say that git-annex is awesome and makes my life better.
+"""]]

Added a comment: sorry, and thoughts
diff --git a/blog/entry/how_I_maybe_didnt_burn_out/comment_2_6446db82e8cff3737c41e0d4b6b30e29._comment b/blog/entry/how_I_maybe_didnt_burn_out/comment_2_6446db82e8cff3737c41e0d4b6b30e29._comment
new file mode 100644
index 00000000..831ab947
--- /dev/null
+++ b/blog/entry/how_I_maybe_didnt_burn_out/comment_2_6446db82e8cff3737c41e0d4b6b30e29._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="Ilya_Shlyakhter"
+ avatar="http://cdn.libravatar.org/avatar/34c90de0aa8b47144f32671827bd97d1"
+ subject="sorry, and thoughts"
+ date="2019-10-30T19:05:14Z"
+ content="""
+Sorry Joey it went down like this.  People focus on their own use case and don't always consider the larger picture.  Which is how one ends up pushing [half-baked fixes](https://git-annex.branchable.com/todo/separate_annex.largefiles.git-add_and_annex.largefiles.git-annex-add_settings/) that break [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself).  Your final design is certainly better.
+
+In retrospect I see how my adding to an already one-sided discussion felt like 'piling on'. Sorry about that.
+
+I think people's reaction stemmed not from \"a decision about git-annex\", but from a decision about git, which people still see as a distinct tool, even when used on repos with annexes.  Pure-git workflows on such repos were affected.  People are \"fearful of change\" to git, \"invested in it, and so defensive of how they want it to work\" -- but this may not yet be true for git-annex.
+"""]]

removed
diff --git a/blog/entry/how_I_maybe_didnt_burn_out/comment_2_cbd45ad8ea6c025924b1757e754893e7._comment b/blog/entry/how_I_maybe_didnt_burn_out/comment_2_cbd45ad8ea6c025924b1757e754893e7._comment
deleted file mode 100644
index 8c09dc2a..00000000
--- a/blog/entry/how_I_maybe_didnt_burn_out/comment_2_cbd45ad8ea6c025924b1757e754893e7._comment
+++ /dev/null
@@ -1,15 +0,0 @@
-[[!comment format=mdwn
- username="Ilya_Shlyakhter"
- avatar="http://cdn.libravatar.org/avatar/34c90de0aa8b47144f32671827bd97d1"
- subject="sorry"
- date="2019-10-28T21:25:44Z"
- content="""
-Sorry Joey it went down like this.  People focus on their own use case and don't always consider the larger picture.  Which is how one ends up pushing [half-baked fixes](https://git-annex.branchable.com/todo/separate_annex.largefiles.git-add_and_annex.largefiles.git-annex-add_settings/) that break [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself).  Your final design is
-certainly better.
-
-In retrospect I see how my adding to an already one-sided discussion felt like 'piling on'.   Sorry about that.
-
-I think people's reaction is in part testament to git-annex's success, and to how [basic](https://www.goodreads.com/quotes/322979-there-was-no-way-his-imagination-could-feel-the-impact) to people's work it has become.
-
-
-"""]]

Added a comment: sorry
diff --git a/blog/entry/how_I_maybe_didnt_burn_out/comment_2_cbd45ad8ea6c025924b1757e754893e7._comment b/blog/entry/how_I_maybe_didnt_burn_out/comment_2_cbd45ad8ea6c025924b1757e754893e7._comment
new file mode 100644
index 00000000..8c09dc2a
--- /dev/null
+++ b/blog/entry/how_I_maybe_didnt_burn_out/comment_2_cbd45ad8ea6c025924b1757e754893e7._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="Ilya_Shlyakhter"
+ avatar="http://cdn.libravatar.org/avatar/34c90de0aa8b47144f32671827bd97d1"
+ subject="sorry"
+ date="2019-10-28T21:25:44Z"
+ content="""
+Sorry Joey it went down like this.  People focus on their own use case and don't always consider the larger picture.  Which is how one ends up pushing [half-baked fixes](https://git-annex.branchable.com/todo/separate_annex.largefiles.git-add_and_annex.largefiles.git-annex-add_settings/) that break [DRY](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself).  Your final design is
+certainly better.
+
+In retrospect I see how my adding to an already one-sided discussion felt like 'piling on'.   Sorry about that.
+
+I think people's reaction is in part testament to git-annex's success, and to how [basic](https://www.goodreads.com/quotes/322979-there-was-no-way-his-imagination-could-feel-the-impact) to people's work it has become.
+
+
+"""]]

Added a comment: sorry
diff --git a/blog/entry/how_I_maybe_didnt_burn_out/comment_1_02d38e627d54aa0b8b83bd83ece3415b._comment b/blog/entry/how_I_maybe_didnt_burn_out/comment_1_02d38e627d54aa0b8b83bd83ece3415b._comment
new file mode 100644
index 00000000..ee336fb4
--- /dev/null
+++ b/blog/entry/how_I_maybe_didnt_burn_out/comment_1_02d38e627d54aa0b8b83bd83ece3415b._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="anarcat"
+ avatar="http://cdn.libravatar.org/avatar/4ad594c1e13211c1ad9edb81ce5110b7"
+ subject="sorry"
+ date="2019-10-28T17:13:23Z"
+ content="""
+I'm sorry you had to go through with this joey... It's really too bad! Working on those projects should be fun, and while there can be friction sometimes, it shouldn't completely take the fun away. :) I do encourage you to do things the way they are going to make you feel better, and disengaging from the conversation does seem like a good stopgap measure.
+
+I think one of the problems is, as you identified, that everything is in the same bag: bug reports, documentation, todo lists, design discussion *and* the user forum are all in the same wiki. And ikiwik is great, but it's not the best forum tool out there. It lacks things like community moderation, for example...
+
+Maybe it's time to revisit the [forum system discussion](https://git-annex.branchable.com/todo/enable_a_discussion_forum_or_support_system/) again? I don't mean to bring you back to the site, but I suspect significant parts of the community would be quite happy to engage with user support, moderation and administration of a forum. It would take away a *lot* of traffic from the website and create a community for users that would feel like home.  You could, of course, participate there, but it would keep the more technical discussions (bug reports and official feature requests) separate from the larger group of users.
+
+Discourse does offer free hosting for free software projects, by the way. It might be something that could work for you. Or you could just squat an existing instance, although I'm not sure that there's an existing one that could match... Maybe https://pixls.us? There has been quite a few git-annex conversations over there and while I suspect I'm a minority in this, I do manage my photos with git-annex, so it's kind of on topic. :)
+
+let me know if i can help any further! -- [[anarcat]]
+"""]]

blog update
diff --git a/blog/entry/how_I_maybe_didnt_burn_out.mdwn b/blog/entry/how_I_maybe_didnt_burn_out.mdwn
new file mode 100644
index 00000000..7767a706
--- /dev/null
+++ b/blog/entry/how_I_maybe_didnt_burn_out.mdwn
@@ -0,0 +1,62 @@
+Last week I found myself in the uncomfortable position of many users
+strongly disagreeing with a decision I had made about git-annex. It felt
+much like a pile-on of them vs me, strong language was being deployed, and it
+was starting to get mentioned in multiple places on the website, in ways I
+felt would lead to fear, uncertainty, and doubt when other users saw it.
+
+It did not help that I had dental implant surgery recently, and was still
+more in recovery than I knew when I finally tackled looking at this long
+thread. So it hit hard.
+
+I've been involved in software projects that have a sometimes adversarial
+relationship with their users. At times, Debian has been one. I don't know
+if it is today, but I remember being on #debian and #debian-devel, or
+debian-user@lists and debian-devel@lists, and seeing two almost 
+entirely diverged communities who were interacting only begrudgingly and
+with friction.
+
+I don't want that in any of my projects now. My perspective on the
+history of git-annex is that most of the best developments have come after
+I made a not great decision or a mistake and got user feedback, and we
+talked it over and found a way to improve things, leading to a better
+result than would have been possible without the original mistake, much
+how a broken bone heals stronger. So this felt wrong, wrong, wrong.
+
+Part of the problem with this discussion was that, though I'd tried to
+explain the constraints that led to the design decision -- which I'd made
+well over three years ago -- not everyone was able to follow that or engage
+with it constructively. Largely, I think because git-annex has a lot more
+users now, with a wider set of viewpoints.
+(Which is generally why Debian has to split off user discussions of course.)
+The users are more fearful of change than earlier adopters tended to be,
+and have more to lose if git-annex stops meeting their use case. They're
+invested in it, and so defensive of how they want it to work.
+
+It also doesn't help that, surgery aside, I lack time to keep up with every
+discussion about git-annex now, if I'm going to also develop it. Just
+looking at the website tends to eat an entire day with maybe a couple bug
+fixes and some support answers being the only productive result. So, I have
+stepped back from following the git-annex website at all, for now. (I'll
+eventually start looking at parts of it again I'm sure.)
+
+I did find enough value in the thread that I was able to develop a fix that
+should meet everyone's needs, as I now understand them (released in version
+7.20191024). I actually come away with entirely new use cases; I did not
+realize that some users would perhaps use git-annex for a single large file
+in a repository otherwise kept entirely in git. Or quite how many users mix
+storing files in git and git-annex, which I have always seen as somewhat of
+an exception aside from the odd dotfile.
+
+So the open questions are: How do I keep up with discussion and support
+traffic now; can I find someone to provide lower-level support and filtering
+or something? (Good news is, some funding could probably be arranged.)
+How do I prevent the git-annex community fracturing along users/developer
+lines as it grows, given that I don't want to work within such a fractured
+community?
+
+I've been working on git-annex for 9 years this week. Have I avoided
+burning out? Probably, but maybe too early to tell. I think that being able
+to ask these questions is a good thing. I'd appreciate hearing from anyone
+who has grappled with these issues in their own software communities.
+
+[[!meta title="how I maybe didn't burn out"]]

link to new location for kickstarter video
diff --git a/blog/entry/kickstarter_for_git-annex_assistant.mdwn b/blog/entry/kickstarter_for_git-annex_assistant.mdwn
index e0b67cf9..fb496e18 100644
--- a/blog/entry/kickstarter_for_git-annex_assistant.mdwn
+++ b/blog/entry/kickstarter_for_git-annex_assistant.mdwn
@@ -39,4 +39,8 @@ video.
 Anyway, please consider [backing me](http://www.kickstarter.com/projects/joeyh/git-annex-assistant-like-dropbox-but-with-your-own) if you can, and more importantly,
 do anything you can to help spread the word. Thanks!
 
+> 2019 update: Kickstarter is no longer hosting the video,
+> so I've pulled it out of git-annex storage and put it
+> [here](https://downloads.kitenet.net/videos/kickstarter.avi).
+
 [[!meta title="kickstarter for git-annex assistant"]]

typo
diff --git a/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
index fe65d2c7..e897e1f3 100644
--- a/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
+++ b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
@@ -7,7 +7,7 @@ With a 5 watt LED bulb (sold separately), the lamp will total a mere 7.2
 watts while on, making it extremely energy efficient. While off, the lamp
 consumes a mere 19 kilowatt-hours per year.
 
-[[!img blog/pics/lamp/wastful.jpg size=400x alt="camp multimeter reading 0.02 amps AC, connected to a small circuit board with a yellow capacitor, a coil, and a heat sinked IC visible"]]
+[[!img blog/pics/lamp/wastful.jpg size=400x alt="clamp multimeter reading 0.02 amps AC, connected to a small circuit board with a yellow capacitor, a coil, and a heat sinked IC visible"]]
 [[!img blog/pics/lamp/rear.jpg size=400x alt="lamp from rear; a small round rocker switch has been added to the top of its half-globe shade"]]
 
 Though the lamp shade at first appears perhaps flimsy, while you are

update
diff --git a/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
index ad0550fb..fe65d2c7 100644
--- a/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
+++ b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
@@ -17,8 +17,9 @@ last for generations, should the planet continue to support human life
 for that long.
 
 As an additional bonus, the small plastic project box that comes free in
-this lamp will delight any electrical enthusiast. The 2 cubic foot of
-syrofoam packaging is less delightful.
+this lamp will delight any electrical enthusiast. As will the approximately
+1 hour conversion process to delete the touch switch phantom load. 
+The 2 cubic foot of syrofoam packaging is less delightful.
 
 Two allen screws attach the pole to the base; one was missing in my lamp.
 Also, while the base is very heavily weighted, the lamp still rocks a bit

syro
diff --git a/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
index 450b113c..ad0550fb 100644
--- a/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
+++ b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
@@ -17,7 +17,8 @@ last for generations, should the planet continue to support human life
 for that long.
 
 As an additional bonus, the small plastic project box that comes free in
-this lamp will delight any electrical enthusiast.
+this lamp will delight any electrical enthusiast. The 2 cubic foot of
+syrofoam packaging is less delightful.
 
 Two allen screws attach the pole to the base; one was missing in my lamp.
 Also, while the base is very heavily weighted, the lamp still rocks a bit

wording
diff --git a/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
index 0bf7769c..450b113c 100644
--- a/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
+++ b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
@@ -16,7 +16,7 @@ metal, though not brass all the way through. Indeed, this lamp should
 last for generations, should the planet continue to support human life
 for that long.
 
-As an additional bonus, the small black project box that comes free in
+As an additional bonus, the small plastic project box that comes free in
 this lamp will delight any electrical enthusiast.
 
 Two allen screws attach the pole to the base; one was missing in my lamp.

final
diff --git a/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
index 99b4d7cc..0bf7769c 100644
--- a/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
+++ b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
@@ -7,15 +7,14 @@ With a 5 watt LED bulb (sold separately), the lamp will total a mere 7.2
 watts while on, making it extremely energy efficient. While off, the lamp
 consumes a mere 19 kilowatt-hours per year.
 
-[[!img size=1024x blog/pics/lamp/wastful.jpg alt="camp multimeter reading 0.02 amps AC, connected to a small circuit board with a yellow capacitor, a coil, and a heat sinked IC visible"]]
+[[!img blog/pics/lamp/wastful.jpg size=400x alt="camp multimeter reading 0.02 amps AC, connected to a small circuit board with a yellow capacitor, a coil, and a heat sinked IC visible"]]
+[[!img blog/pics/lamp/rear.jpg size=400x alt="lamp from rear; a small round rocker switch has been added to the top of its half-globe shade"]]
 
-While the lamp shade at first appears perhaps flimsy, while you are drilling
-a hole in it to add a physical switch, you will discover it's a reasonably
-soft metal, though not brass all the way through. Indeed, this lamp should
-last for generations, should the planet continue to support human life for
-that long.
-
-[[!img size=1024x blog/pics/lamp/rear.jpg alt="lamp from rear; a small round rocker switch has been added to the top of its half-globe shade"]]
+Though the lamp shade at first appears perhaps flimsy, while you are
+drilling a hole in it to add a physical switch, you will discover
+metal, though not brass all the way through. Indeed, this lamp should
+last for generations, should the planet continue to support human life
+for that long.
 
 As an additional bonus, the small black project box that comes free in
 this lamp will delight any electrical enthusiast.
@@ -25,5 +24,5 @@ Also, while the base is very heavily weighted, the lamp still rocks a bit
 when using the aftermarket switch. So I am forced to give it a mere 4 out
 of 5 stars.
 
-[[!img size=1024x blog/pics/lamp/front.jpg alt="front view of lit lamp beside a bookcase"]]
+[[!img blog/pics/lamp/front.jpg size=640x alt="front view of lit lamp beside a bookcase"]]
 

blog update
diff --git a/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
new file mode 100644
index 00000000..99b4d7cc
--- /dev/null
+++ b/blog/entry/Project_62_Valencia_Floor_Lamp_review.mdwn
@@ -0,0 +1,29 @@
+From Target, this brass finish floor lamp evokes 60's modernism,
+updated for the mid-Anthropocene with a touch plate switch.
+
+The integrated microcontroller consumes a mere 2.2 watts while the lamp is
+turned off, in order to allow you to turn the lamp on with a stylish flick.
+With a 5 watt LED bulb (sold separately), the lamp will total a mere 7.2
+watts while on, making it extremely energy efficient. While off, the lamp
+consumes a mere 19 kilowatt-hours per year.
+
+[[!img size=1024x blog/pics/lamp/wastful.jpg alt="camp multimeter reading 0.02 amps AC, connected to a small circuit board with a yellow capacitor, a coil, and a heat sinked IC visible"]]
+
+While the lamp shade at first appears perhaps flimsy, while you are drilling
+a hole in it to add a physical switch, you will discover it's a reasonably
+soft metal, though not brass all the way through. Indeed, this lamp should
+last for generations, should the planet continue to support human life for
+that long.
+
+[[!img size=1024x blog/pics/lamp/rear.jpg alt="lamp from rear; a small round rocker switch has been added to the top of its half-globe shade"]]
+
+As an additional bonus, the small black project box that comes free in
+this lamp will delight any electrical enthusiast.
+
+Two allen screws attach the pole to the base; one was missing in my lamp.
+Also, while the base is very heavily weighted, the lamp still rocks a bit
+when using the aftermarket switch. So I am forced to give it a mere 4 out
+of 5 stars.
+
+[[!img size=1024x blog/pics/lamp/front.jpg alt="front view of lit lamp beside a bookcase"]]
+

add
diff --git a/blog/pics/lamp/front.jpg b/blog/pics/lamp/front.jpg
new file mode 100644
index 00000000..3a9ddfe2
Binary files /dev/null and b/blog/pics/lamp/front.jpg differ
diff --git a/blog/pics/lamp/rear.jpg b/blog/pics/lamp/rear.jpg
new file mode 100644
index 00000000..04a1fd89
Binary files /dev/null and b/blog/pics/lamp/rear.jpg differ
diff --git a/blog/pics/lamp/wastful.jpg b/blog/pics/lamp/wastful.jpg
new file mode 100644
index 00000000..8ffefeee
Binary files /dev/null and b/blog/pics/lamp/wastful.jpg differ

Added a comment: still shorter…
diff --git a/blog/entry/turing_complete_version_numbers/comment_1_218d94300cfd331f4cbd3e004f73ef16._comment b/blog/entry/turing_complete_version_numbers/comment_1_218d94300cfd331f4cbd3e004f73ef16._comment
new file mode 100644
index 00000000..cc4de122
--- /dev/null
+++ b/blog/entry/turing_complete_version_numbers/comment_1_218d94300cfd331f4cbd3e004f73ef16._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="jon+joeyh@58e0bb898cec29edb297cf4a4a52efd862bef676"
+ nickname="jon+joeyh"
+ avatar="http://cdn.libravatar.org/avatar/7a82c206030ba192f78d073eaa43cdc5"
+ subject="still shorter…"
+ date="2019-09-30T09:54:48Z"
+ content="""
+that \"hello world\" is still shorter than this ludicrous thing
+
+acorn 6.2.1+ds+~0.4.0+~4.0.0+really4.0.0+~1.0.0+~5.0.1+ds+~1.7.0+ds+~0.1.1+~0.3.1+~0.2.0+~0.1.0+~0.3.0+~0.3.0-5
+(<https://bugs.debian.org/940708>)
+
+— [Jon](https://jmtd.net)
+"""]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index c171f8ae..1717fcdf 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 58 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 59 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

blog update
diff --git a/blog/entry/turing_complete_version_numbers.mdwn b/blog/entry/turing_complete_version_numbers.mdwn
new file mode 100644
index 00000000..2d642ac6
--- /dev/null
+++ b/blog/entry/turing_complete_version_numbers.mdwn
@@ -0,0 +1,35 @@
+A quick standard for when you want to embed an arbitrary program in the
+version number of your program.
+
+	2 	increment the data pointer (to point to the next cell to the right).
+	3 	decrement the data pointer (to point to the next cell to the left).
+	+ 	increment (increase by one) the byte at the data pointer.
+	- 	decrement (decrease by one) the byte at the data pointer.
+	. 	output the byte at the data pointer.
+	4 	accept one byte of input, storing its value in the byte at the data pointer.
+	6 	if the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching 9 command.
+	9 	if the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching 6 command. 
+
+This is simply [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck)
+with operators that are legal in (Debian) version numbers kept as-is,
+and some numbers replacing the rest.
+
+Note that all other operators are ignored as usual. In particular, 1 and 8 are ignored,
+which make it easy to build version number programs that compare properly with past versions.
+And in some cases, adding 1 or 8 will be needed to make a particular program be a properly
+formatted version number.
+
+For example, an infinite loop version number is:
+
+	1+69
+
+A nice short hello world is:
+
+	1+6-6336+6-8-1-29-6333999222-92-1.1-1-1-8.2.8.2.3333-1.3+1.22222.2.33.3-1.1
+
+Licensing: Yes, there should also be a way to embed a license in a version ...
+Oh, I mean to say, the Wikipedia excerpt above is CC-BY-SA, and 
+the hello world is based on
+<https://esolangs.org/wiki/Hello_world_program_in_esoteric_languages>
+
+Previously: [[a_brainfuck_monad]]

poll vote (watched some, boring)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index af75f617..c171f8ae 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 58 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 58 "watched it all, liked it" 9 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

Added a comment
diff --git a/blog/entry/how_to_detect_chef/comment_2_bf90645fd0e419b7c83ae89d78ad4e18._comment b/blog/entry/how_to_detect_chef/comment_2_bf90645fd0e419b7c83ae89d78ad4e18._comment
new file mode 100644
index 00000000..58005cdf
--- /dev/null
+++ b/blog/entry/how_to_detect_chef/comment_2_bf90645fd0e419b7c83ae89d78ad4e18._comment
@@ -0,0 +1,9 @@
+[[!comment format=mdwn
+ username="oz@fa83dac6e37245c88f2e67cd2a590df799bf36e9"
+ nickname="oz"
+ avatar="http://cdn.libravatar.org/avatar/0a6f759ed6dcc27727ae0b70f430d00d"
+ subject="comment 2"
+ date="2019-09-23T16:28:42Z"
+ content="""
+Thanks for caring.
+"""]]

Added a comment: You are a monster.
diff --git a/blog/entry/how_to_detect_chef/comment_1_2f31ba7257e4c09d513c314bf7d35d48._comment b/blog/entry/how_to_detect_chef/comment_1_2f31ba7257e4c09d513c314bf7d35d48._comment
new file mode 100644
index 00000000..7ba7d831
--- /dev/null
+++ b/blog/entry/how_to_detect_chef/comment_1_2f31ba7257e4c09d513c314bf7d35d48._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="ThirteenthLetter"
+ avatar="http://cdn.libravatar.org/avatar/217043e0fd7a23e751cbd9d0eeac594f"
+ subject="You are a monster."
+ date="2019-09-22T19:32:55Z"
+ content="""
+Open source is a principle, an ideal, and you pee all over it in the name of enforcing a political consensus you couldn't have cared less about four years ago. You should not be permitted near a computer. But hey, I'm sure you'll get plenty of Twitter likes and Reddit upvotes for throwing open software in the trash, so I guess that makes up for it.
+"""]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index 2e2e824a..af75f617 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 57 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 58 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index cea2a0a7..2e2e824a 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 56 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 57 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

blog update
diff --git a/blog/entry/how_to_detect_chef.mdwn b/blog/entry/how_to_detect_chef.mdwn
new file mode 100644
index 00000000..66b37fae
--- /dev/null
+++ b/blog/entry/how_to_detect_chef.mdwn
@@ -0,0 +1,12 @@
+If you want your program to detect when it's being run by chef, here's
+one way to do that.
+
+	sleep 1 while $ENV{PATH} =~ m#chef[^:]+/bin#;
+
+This works because Chef's `shell_out` adds `Gem.bindir` to `PATH`,
+which is something like `/opt/chefdk/embedded/bin`.
+
+You may want to delete the "sleep", which will make it run faster.
+
+Would I or anyone ever really do this? Chef Inc's management seems determined
+to test the question, don't they.

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index ca5e8c10..cea2a0a7 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 55 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 56 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index 3004ce97..ca5e8c10 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 54 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 55 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index 537e6c72..3004ce97 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 53 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 54 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index 35b979ae..537e6c72 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 52 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 53 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index c849aed9..35b979ae 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 51 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 52 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index b600f7d7..c849aed9 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 50 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 51 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

poll vote (watched it all, liked it)
diff --git a/blog/entry/watch_me_code_for_half_an_hour.mdwn b/blog/entry/watch_me_code_for_half_an_hour.mdwn
index 9a6c362d..b600f7d7 100644
--- a/blog/entry/watch_me_code_for_half_an_hour.mdwn
+++ b/blog/entry/watch_me_code_for_half_an_hour.mdwn
@@ -14,7 +14,7 @@ Not shown is the hour I spent the next day changing the "optimize"
 subcommand implemented here into "--auto" options that can be passed to
 [[code/git-annex]]'s get and drop commands.
 
-[[!poll 49 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
+[[!poll 50 "watched it all, liked it" 8 "watched some, boring" 4 "too long for me" 15 "too haskell for me" 13 "not interested"]]
 
 [[!meta title="watch me program for half an hour"]]
 [[!tag haskell]]

fix link
diff --git a/blog/entry/releasing_two_haskell_libraries_in_one_day.mdwn b/blog/entry/releasing_two_haskell_libraries_in_one_day.mdwn
index b5ffc4c7..46a1772f 100644
--- a/blog/entry/releasing_two_haskell_libraries_in_one_day.mdwn
+++ b/blog/entry/releasing_two_haskell_libraries_in_one_day.mdwn
@@ -5,7 +5,7 @@ The first library is a [libmodbus binding in haskell](https://hackage.haskell.or
 There are a couple of other haskell modbus libraries, but none that support
 serial communication out of the box. I've been using a python library
 to talk to my solar charge controller, but it is not great at dealing with
-the slightly flakey interface. The [libmodbus](httpss://libmodbus.org/)
+the slightly flakey interface. The [libmodbus](https://libmodbus.org/)
 C library has features that make it more robust, and it also
 supports fast batched reads.
 

blog update
diff --git a/blog/entry/releasing_two_haskell_libraries_in_one_day.mdwn b/blog/entry/releasing_two_haskell_libraries_in_one_day.mdwn
new file mode 100644
index 00000000..b5ffc4c7
--- /dev/null
+++ b/blog/entry/releasing_two_haskell_libraries_in_one_day.mdwn
@@ -0,0 +1,80 @@
+[[!meta title="releasing two haskell libraries in one day: libmodbus and git-lfs"]]
+
+The first library is a [libmodbus binding in haskell](https://hackage.haskell.org/package/libmodbus).
+
+There are a couple of other haskell modbus libraries, but none that support
+serial communication out of the box. I've been using a python library
+to talk to my solar charge controller, but it is not great at dealing with
+the slightly flakey interface. The [libmodbus](httpss://libmodbus.org/)
+C library has features that make it more robust, and it also
+supports fast batched reads.
+
+So a haskell interface to it seemed worth starting while I was
+doing laundry, and then for some reason it seemed worth writing a whole
+bunch more FFIs that I may never use, so it covers libmodbus fairly
+extensively. 660 lines of code all told.
+
+Writing a good binding to a C library has art to it. I've seen ones that
+are so close you feel you're writing C and not haskell. On the other hand,
+some are so far removed from the underlying library that its documentation
+does not carry over at all.
+
+I tried to strike a balance. Same function names so the
+[extensive libmodbus documentation](https://libmodbus.org/docs/v3.1.6/)
+is easy to refer to while using it, but plenty of haskell data types
+so you won't mix up the parity with the stop bits.
+
+And while it uses a mutable vector under the hood as the buffer for the FFI
+interface, so it can be just as fast as the C library, I also made
+functions for reading stuff like registers and coils be polymorphic so
+easier data types can be used at the expense of a bit of extra allocation.
+
+The big win in this haskell binding is that you can leverage all the nice
+haskell libraries for dealing with binary data to parse the modbus data,
+rather than the ad-hoc integer and float conversion stuff from the C
+library.
+
+For example, the Epever solar charge controller has its own slightly
+nonstandard way to represent 16 bit and 32 bit floats. Using the
+`binary` library to parse its registers in applicative style came
+out quite nice:
+
+	data Epever = Epever
+		{ pv_array_voltage :: Float
+		, pv_array_current :: Float
+		, pv_array_power :: Float
+		, battery_voltage :: Float
+		} deriving (Show)
+
+	getEpever :: Get Epever
+	getEpever = Epever
+		<$> epeverfloat  -- register 0x3100
+		<*> epeverfloat  -- register 0x3101
+		<*> epeverfloat2 -- register 0x3102 (low) and 0x3103 (high)
+		<*> epeverfloat  -- register 0x3104
+	 where
+		epeverfloat = decimals 2 <$> getWord16host
+		epeverfloat2 = do
+			l <- getWord16host
+			h <- getWord16host
+			return (decimals 2 (l + h*2^16))
+		decimals n v = fromIntegral v / (10^n)
+
+----
+
+The second library is a [git-lfs implementation in pure Haskell](https://hackage.haskell.org/package/git-lfs).
+
+Emphasis on the *pure* -- there is not a scrap of IO code in 
+this library, just 400+ lines of data types, parsing, and serialization.
+
+I wrote it a couple weeks ago so
+[git-annex can store files in a  git-lfs remote](https://git-annex.branchable.com/special_remotes/git-lfs/).
+I've also used it as a git-lfs server, mostly while exploring
+interesting edge cases of git-lfs.
+
+[[!tag code/haskell-libmodbus]]
+[[!tag code/haskell-git-lfs]]
+
+----
+
+This work was sponsored by Jake Vosloo [on Patreon](https://patreon.com/joeyh).
diff --git a/code.mdwn b/code.mdwn
index 29e174f0..29cc1a79 100644
--- a/code.mdwn
+++ b/code.mdwn
@@ -36,6 +36,7 @@ In maintenance mode mostly, but I still have my hands in it somewhat.
 [[http-client-restricted]]
 [[scuttlebutt-types]]
 [[haskell-libmodbus]]
+[[haskell-git-lfs]]
 [[haskell-mountpoints]]
 
 ## Past projects
diff --git a/code/haskell-git-lfs.mdwn b/code/haskell-git-lfs.mdwn
new file mode 100644
index 00000000..712e2dde
--- /dev/null
+++ b/code/haskell-git-lfs.mdwn
@@ -0,0 +1,3 @@
+An implementation of the git-lfs protocol in pure haskell.
+
+<https://hackage.haskell.org/package/git-lfs>

add
diff --git a/code.mdwn b/code.mdwn
index c31824ba..29e174f0 100644
--- a/code.mdwn
+++ b/code.mdwn
@@ -35,6 +35,8 @@ In maintenance mode mostly, but I still have my hands in it somewhat.
 [[github-backup]]
 [[http-client-restricted]]
 [[scuttlebutt-types]]
+[[haskell-libmodbus]]
+[[haskell-mountpoints]]
 
 ## Past projects
 
diff --git a/code/haskell-libmodbus.mdwn b/code/haskell-libmodbus.mdwn
new file mode 100644
index 00000000..48b8eca1
--- /dev/null
+++ b/code/haskell-libmodbus.mdwn
@@ -0,0 +1,3 @@
+Haskell bindings to the C modbus library
+
+<https://hackage.haskell.org/package/libmodbus>
diff --git a/code/haskell-mountpoints.mdwn b/code/haskell-mountpoints.mdwn
new file mode 100644
index 00000000..54e881db
--- /dev/null
+++ b/code/haskell-mountpoints.mdwn
@@ -0,0 +1,3 @@
+little haskell library to list mount points on several OS's
+
+<http://hackage.haskell.org/package/mountpoints>

Added a comment: poor data vs no data
diff --git a/blog/entry/the_popcon_problem/comment_8_730fdaf4e2d070cd6fc7e4f70ac3ab42._comment b/blog/entry/the_popcon_problem/comment_8_730fdaf4e2d070cd6fc7e4f70ac3ab42._comment
new file mode 100644
index 00000000..dcdcdaa1
--- /dev/null
+++ b/blog/entry/the_popcon_problem/comment_8_730fdaf4e2d070cd6fc7e4f70ac3ab42._comment
@@ -0,0 +1,13 @@
+[[!comment format=mdwn
+ username="plugwash@4317577d3e8f55a5f1c81ec62473a733cf6cd35b"
+ nickname="plugwash"
+ avatar="http://cdn.libravatar.org/avatar/cdb5c572e59332b285a2874238bd0705"
+ subject="poor data vs no data"
+ date="2019-08-13T12:07:39Z"
+ content="""
+I agree that low popcon alone should not be a reason to remove a well-maintained package.
+
+The unfortunate reality though is that many packages in Debian are not well-maintained. They are kept on life support by rc bug squashers and by the people whose progress they are blocking. Ultimately a decision has to be made which packages are worth keeping on life support and which are not. 
+
+Popcon isn't a great tool, but it's about the best we can have while keeping to our principles.
+"""]]

Added a comment: Robust water solutions
diff --git a/blog/entry/hacking_water/comment_6_834b316d78faccab55f3ae5079f87e5d._comment b/blog/entry/hacking_water/comment_6_834b316d78faccab55f3ae5079f87e5d._comment
new file mode 100644
index 00000000..fa7f27c1
--- /dev/null
+++ b/blog/entry/hacking_water/comment_6_834b316d78faccab55f3ae5079f87e5d._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="dgray@c271d419d641bd22709a8e53c8b644231a99fa0c"
+ nickname="dgray"
+ avatar="http://cdn.libravatar.org/avatar/e17da7ffdecec6c96edd2d4a69879bd8"
+ subject="Robust water solutions"
+ date="2019-07-15T10:46:21Z"
+ content="""
+I read this with interest as it's pretty relevant for my situation, but with a totally different climate. In Crete we have a problem with power cuts, 
+but even though it's a dry climate we have a stable water supply. Also we run a co-op of a few of us to pump well water for irrigation, into our own tanks. This seems a ideal case to intermittently pump using solar power, since we get so much sunshine. Also the lowest recorded temperature here is 0.8C so no worries about frost damage. 
+
+Dave
+"""]]

layout
diff --git a/blog/entry/custom_type_checker_errors_for_propellor.mdwn b/blog/entry/custom_type_checker_errors_for_propellor.mdwn
index 14ad1410..20804db0 100644
--- a/blog/entry/custom_type_checker_errors_for_propellor.mdwn
+++ b/blog/entry/custom_type_checker_errors_for_propellor.mdwn
@@ -103,7 +103,7 @@ let's see if we can make it better.
 [[!tag propellor devblog]]
 [[!tag haskell]]
 
---
+----
 
 This was sponsored by Jake Vosloo and Trenton Cronholm
 <a href="https://patreon.com/joeyh">on Patreon</a>.

layout
diff --git a/blog/entry/custom_type_checker_errors_for_propellor.mdwn b/blog/entry/custom_type_checker_errors_for_propellor.mdwn
index 81f51a43..14ad1410 100644
--- a/blog/entry/custom_type_checker_errors_for_propellor.mdwn
+++ b/blog/entry/custom_type_checker_errors_for_propellor.mdwn
@@ -63,7 +63,7 @@ error, like this one:
 	    • Cannot combine properties:
 	        Property <unknown>
 	        Property HasInfo + Debian + Buntish + ArchLinux + FreeBSD
-		(Property <unknown> is often caused by applying a Property constructor to the wrong number of arguments.)
+	        (Property <unknown> is often caused by applying a Property constructor to the wrong number of arguments.)
 	    • In the first argument of ‘(&)’, namely
 	        ‘props & osDebian Unstable’
 

layout
diff --git a/blog/entry/custom_type_checker_errors_for_propellor.mdwn b/blog/entry/custom_type_checker_errors_for_propellor.mdwn
index c353634b..81f51a43 100644
--- a/blog/entry/custom_type_checker_errors_for_propellor.mdwn
+++ b/blog/entry/custom_type_checker_errors_for_propellor.mdwn
@@ -13,15 +13,15 @@ Most of the early wins came from using ghc's TypeError class, not
 the new library. I wanted custom type errors that were able to talk about
 problems with Property targets, like these:
     
-    • ensureProperty inner Property is missing support for: 
-	FreeBSD
+	    • ensureProperty inner Property is missing support for: 
+		FreeBSD
 
-    • This use of tightenTargets would widen, not narrow, adding: 
-        ArchLinux + FreeBSD
+	    • This use of tightenTargets would widen, not narrow, adding: 
+	        ArchLinux + FreeBSD
 
-    • Cannot combine properties:
-        Property FreeBSD
-        Property HasInfo + Debian + Buntish + ArchLinux
+	    • Cannot combine properties:
+	        Property FreeBSD
+	        Property HasInfo + Debian + Buntish + ArchLinux
 
 So I wrote a type-level pretty-printer for propellor's MetaType lists. One
 interesting thing about it is that it rewrites types such as `Targeting
@@ -40,43 +40,43 @@ Often a property constructor in propellor gets a new argument added to it.
 A propellor config that has not been updated to include the new argument
 used to result in this kind of enormous and useless error message:
 
-    • Couldn't match type ‘Propellor.Types.MetaTypes.CheckCombinable
-                             (Propellor.Types.MetaTypes.Concat
-                                (Propellor.Types.MetaTypes.NonTargets y0)
-                                (Data.Type.Bool.If
-                                   (Propellor.Types.MetaTypes.Elem
-                                      ('Propellor.Types.MetaTypes.Targeting 'OSDebian)
-                                      (Propellor.Types.MetaTypes.Targets y0))
-                                   ('Propellor.Types.MetaTypes.Targeting 'OSDebian
-                                      : Data.Type.Bool.If
-                                          (Propellor.Types.MetaTypes.Elem
-                                             ('Propellor.Types.MetaTypes.Targeting 'OSBuntish)
-    -- many, many lines elided
-    • In the first argument of ‘(&)’, namely
-        ‘props & osDebian Unstable’
+	    • Couldn't match type ‘Propellor.Types.MetaTypes.CheckCombinable
+	                             (Propellor.Types.MetaTypes.Concat
+	                                (Propellor.Types.MetaTypes.NonTargets y0)
+	                                (Data.Type.Bool.If
+	                                   (Propellor.Types.MetaTypes.Elem
+	                                      ('Propellor.Types.MetaTypes.Targeting 'OSDebian)
+	                                      (Propellor.Types.MetaTypes.Targets y0))
+	                                   ('Propellor.Types.MetaTypes.Targeting 'OSDebian
+	                                      : Data.Type.Bool.If
+	                                          (Propellor.Types.MetaTypes.Elem
+	                                             ('Propellor.Types.MetaTypes.Targeting 'OSBuntish)
+	    -- many, many lines elided
+	    • In the first argument of ‘(&)’, namely
+	        ‘props & osDebian Unstable’
 
 The type-errors library was a big help. It's able to detect when the type
 checker gets "stuck" reducing a type function, and is going to
 dump it all out to the user. And you can replace that with a custom type
 error, like this one:
 
-    • Cannot combine properties:
-        Property <unknown>
-        Property HasInfo + Debian + Buntish + ArchLinux + FreeBSD
-	(Property <unknown> is often caused by applying a Property constructor to the wrong number of arguments.)
-    • In the first argument of ‘(&)’, namely
-        ‘props & osDebian Unstable’
+	    • Cannot combine properties:
+	        Property <unknown>
+	        Property HasInfo + Debian + Buntish + ArchLinux + FreeBSD
+		(Property <unknown> is often caused by applying a Property constructor to the wrong number of arguments.)
+	    • In the first argument of ‘(&)’, namely
+	        ‘props & osDebian Unstable’
 
 Detecting when the type checker is "stuck" also let me add some custom
 type errors to handle cases where type inference has failed:
 
-    • ensureProperty outer Property type is not able to be inferred here.
-      Consider adding a type annotation.
-    • When checking the inferred type
-        writeConfig :: forall (outer :: [Propellor.Types.MetaTypes.MetaType]) t.
+	    • ensureProperty outer Property type is not able to be inferred here.
+	      Consider adding a type annotation.
+	    • When checking the inferred type
+	        writeConfig :: forall (outer :: [Propellor.Types.MetaTypes.MetaType]) t.
 
-    • Unable to infer desired Property type in this use of tightenTargets.
-      Consider adding a type annotation.
+	    • Unable to infer desired Property type in this use of tightenTargets.
+	      Consider adding a type annotation.
 
 Unfortunately, the use of TypeError caused one problem. When too many
 arguments are passed to a property constructor that's being combined with

blog update
diff --git a/blog/entry/custom_type_checker_errors_for_propellor.mdwn b/blog/entry/custom_type_checker_errors_for_propellor.mdwn
new file mode 100644
index 00000000..c353634b
--- /dev/null
+++ b/blog/entry/custom_type_checker_errors_for_propellor.mdwn
@@ -0,0 +1,109 @@
+Since [[code/propellor]] is configured by writing Haskell, type errors are
+an important part of its interface. As more type level machinery has been
+added to propellor, it's become more common for type errors to refer to
+hard to understand constraints. And sometimes simple mistakes in a
+propellor config result in the type checker getting confused and spewing an
+error that is thousands of lines of gobbledygook.
+
+Yesterday's release of the new 
+[type-errors](https://hackage.haskell.org/package/type-errors)
+library got me excited to improve propellor's type errors.
+
+Most of the early wins came from using ghc's TypeError class, not
+the new library. I wanted custom type errors that were able to talk about
+problems with Property targets, like these:
+    
+    • ensureProperty inner Property is missing support for: 
+	FreeBSD
+
+    • This use of tightenTargets would widen, not narrow, adding: 
+        ArchLinux + FreeBSD
+
+    • Cannot combine properties:
+        Property FreeBSD
+        Property HasInfo + Debian + Buntish + ArchLinux
+
+So I wrote a type-level pretty-printer for propellor's MetaType lists. One
+interesting thing about it is that it rewrites types such as `Targeting
+OSDebian` back to the `Debian` type alias that the user expects to see.
+
+To generate the first error message above, I used the pretty-printer
+like this:
+
+	(TypeError
+		('Text "ensureProperty inner Property is missing support for: "
+			':$$: PrettyPrintMetaTypes (Difference (Targets outer) (Targets inner))
+		)
+	)
+
+Often a property constructor in propellor gets a new argument added to it.
+A propellor config that has not been updated to include the new argument
+used to result in this kind of enormous and useless error message:
+
+    • Couldn't match type ‘Propellor.Types.MetaTypes.CheckCombinable
+                             (Propellor.Types.MetaTypes.Concat
+                                (Propellor.Types.MetaTypes.NonTargets y0)
+                                (Data.Type.Bool.If
+                                   (Propellor.Types.MetaTypes.Elem
+                                      ('Propellor.Types.MetaTypes.Targeting 'OSDebian)
+                                      (Propellor.Types.MetaTypes.Targets y0))
+                                   ('Propellor.Types.MetaTypes.Targeting 'OSDebian
+                                      : Data.Type.Bool.If
+                                          (Propellor.Types.MetaTypes.Elem
+                                             ('Propellor.Types.MetaTypes.Targeting 'OSBuntish)
+    -- many, many lines elided
+    • In the first argument of ‘(&)’, namely
+        ‘props & osDebian Unstable’
+
+The type-errors library was a big help. It's able to detect when the type
+checker gets "stuck" reducing a type function, and is going to
+dump it all out to the user. And you can replace that with a custom type
+error, like this one:
+
+    • Cannot combine properties:
+        Property <unknown>
+        Property HasInfo + Debian + Buntish + ArchLinux + FreeBSD
+	(Property <unknown> is often caused by applying a Property constructor to the wrong number of arguments.)
+    • In the first argument of ‘(&)’, namely
+        ‘props & osDebian Unstable’
+
+Detecting when the type checker is "stuck" also let me add some custom
+type errors to handle cases where type inference has failed:
+
+    • ensureProperty outer Property type is not able to be inferred here.
+      Consider adding a type annotation.
+    • When checking the inferred type
+        writeConfig :: forall (outer :: [Propellor.Types.MetaTypes.MetaType]) t.
+
+    • Unable to infer desired Property type in this use of tightenTargets.
+      Consider adding a type annotation.
+
+Unfortunately, the use of TypeError caused one problem. When too many
+arguments are passed to a property constructor that's being combined with
+other properties, ghc used to give its usual error message about too many
+arguments, but now it gives the custom "Cannot combine properties" type
+error, which is not as useful.
+
+[Seems likely that's a ghc bug](https://gitlab.haskell.org/ghc/ghc/issues/16894)
+but I need a better test case to make progress on that front. Anyway,
+I decided I can live with this problem for now, to get all the other
+nice custom type errors.
+
+The only other known problem with propellor's type errors is that,
+when there is a long list of properties being combined together, a single
+problem can result in a cascade of many errors. Sometimes that
+also causes ghc to use a lot of memory. While custom error messages don't
+help with this, at least the error cascade is nicer and individual messages
+are not as long.
+
+Propellor 5.9.0 has all the custom type error messages discussed here. If
+you see a hard to understand error message when using it, get in touch and
+let's see if we can make it better.
+
+[[!tag propellor devblog]]
+[[!tag haskell]]
+
+--
+
+This was sponsored by Jake Vosloo and Trenton Cronholm
+<a href="https://patreon.com/joeyh">on Patreon</a>.

Added a comment: re: udisks2
diff --git a/blog/entry/usb_drives_with_no_phantom_load/comment_16_cb53a97ad84573781050e59d71b6ac88._comment b/blog/entry/usb_drives_with_no_phantom_load/comment_16_cb53a97ad84573781050e59d71b6ac88._comment
new file mode 100644
index 00000000..dc657f72
--- /dev/null
+++ b/blog/entry/usb_drives_with_no_phantom_load/comment_16_cb53a97ad84573781050e59d71b6ac88._comment
@@ -0,0 +1,18 @@
+[[!comment format=mdwn
+ username="te36"
+ avatar="http://cdn.libravatar.org/avatar/7eebce89b2d86b0a9ed16d75fe7f978e"
+ subject="re: udisks2"
+ date="2019-06-24T06:32:37Z"
+ content="""
+If i just switch off ports via uhubctl and not bother removing the /dev nodes for it, then something in the system will later access the /dev node, which leads to I/O error, removal of the dev node from the file system, but also in powering on the port again and then recreation of the dev nodes. Aka: not good to ensure that ports will be powered off reliably. For example on my system, udisksd itself wakes up disks something like every 10 minutes for SMART check.
+
+When using udevadm or any other tool to just remove the /dev nodes, then the risk of unintentionally powering up the port/disk still exists when there are any appliation with still open files to the dev nodes i think. Worse yet, when all dev nodes are removed and one wants to power the port up again with uhubctl, then the system will not recreate the dev nodes - because the kernel never saw the disk to have gone away. Only the dev nodes where removed.
+
+udiskctl actually does the correct job: It removes the kernel notion of the disk, which then removes the dev nodes. Example:
+
+udisks-Message: 22:56:40.318: Successfully sent SCSI command SYNCHRONIZE CACHE to /dev/sdd
+udisks-Message: 22:56:41.088: Successfully sent SCSI command START STOP UNIT to /dev/sdd
+udisks-Message: 22:56:41.174: Powered off /dev/sdd - successfully wrote to sysfs path /sys/devices/pci0000:00/0000:00:08.1/0000:38:00.4/usb6/6-1/6-1.3/6-1.3.1/remove
+
+So the correct solution for me is to use udiskctl to remove dev nodes, then power down port with uhubctl. After powering up with uhubctl the kernel will correctly recreate the dev nodes. And in between, the only remaining risk for unintentionally waking up the disk is anything in the kernel resestting the whole hub.
+"""]]

comment
diff --git a/blog/entry/hacking_water/comment_5_c7bf44ead51288de3f255053307b70ca._comment b/blog/entry/hacking_water/comment_5_c7bf44ead51288de3f255053307b70ca._comment
new file mode 100644
index 00000000..7b71337d
--- /dev/null
+++ b/blog/entry/hacking_water/comment_5_c7bf44ead51288de3f255053307b70ca._comment
@@ -0,0 +1,16 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""Re: winter"""
+ date="2019-06-18T16:11:27Z"
+ content="""
+The water pump will be shut off and drained to winterize and probably only
+run a couple of times over the winter to refill tanks. I may eventually
+automate that with an arduino, temp sensor, and a couple of servos.
+
+The water tanks are unlikely to get more than a few inches of ice in them
+over a winter, which will not damage them, and I'm also going to paint them
+black to maximize solar heating. (And prevent algae growth.)
+
+My main concern is the buried line back to the house, which is on the
+marginal side of deep enough for this area, but probably deep enough.
+"""]]

Added a comment
diff --git a/blog/entry/hacking_water/comment_4_eb17d94ee65255913050e2c199a3374f._comment b/blog/entry/hacking_water/comment_4_eb17d94ee65255913050e2c199a3374f._comment
new file mode 100644
index 00000000..e59e3ebd
--- /dev/null
+++ b/blog/entry/hacking_water/comment_4_eb17d94ee65255913050e2c199a3374f._comment
@@ -0,0 +1,11 @@
+[[!comment format=mdwn
+ username="anthony@ad39673d230d75cbfd19d2757d754030049c7673"
+ nickname="anthony"
+ avatar="http://cdn.libravatar.org/avatar/05b48b72766177b3b0a6ff4afdb70790"
+ subject="comment 4"
+ date="2019-06-18T06:32:43Z"
+ content="""
+That's an impressive project! 
+
+Curious, what happens in the winter? Is it warm enough there that the tanks & lines don't freeze, or does it all have to be drained?
+"""]]

Added a comment: very interesting project
diff --git a/blog/entry/hacking_water/comment_3_ee711e07e3ee2e5c1b1721546b72321b._comment b/blog/entry/hacking_water/comment_3_ee711e07e3ee2e5c1b1721546b72321b._comment
new file mode 100644
index 00000000..76dd0de1
--- /dev/null
+++ b/blog/entry/hacking_water/comment_3_ee711e07e3ee2e5c1b1721546b72321b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="mudflap"
+ avatar="http://cdn.libravatar.org/avatar/b06245a6c156973d6ca8279307f737af"
+ subject="very interesting project"
+ date="2019-06-17T19:13:14Z"
+ content="""
+I will not be able to do this on my property- it's completely flat. But I sure enjoy all the pics. Keep it up!
+"""]]

clarify solar panels
diff --git a/blog/entry/hacking_water.mdwn b/blog/entry/hacking_water.mdwn
index ea2a2b2d..aeac5aa1 100644
--- a/blog/entry/hacking_water.mdwn
+++ b/blog/entry/hacking_water.mdwn
@@ -7,12 +7,13 @@ for longer periods in the fall, and the cisterns have barely been large
 enough to get through.
 
 And if I'm going to add storage, it ought to be above the house, so it can
-gravity flow. And I have these old 100 watts of solar panels sitting unused
-after my solar upgrade. And a couple of pumps for a pressure tank system
-that was not working when I moved in. And I stumbled across an odd little
-flat spot halfway up the hillside. And there's an exposed copper pipe next
-to the house's retaining wall; email to Africa establishes that it goes
-down and through the wall and connects into the plumbing.
+gravity flow. And I have this 100 watt array of 20 year old solar
+panels sitting unused after my solar upgrade. And a couple of pumps for a
+pressure tank system that was not working when I moved in. And I stumbled
+across an odd little flat spot halfway up the hillside. And there's an
+exposed copper pipe next to the house's retaining wall; email to Africa
+establishes that it goes down and through the wall and connects into the
+plumbing.
 
 [[!img blog/pics/hacking_water/oldsolarpanel.jpg size=x300 alt="a solar
 panel with a large impact crater; the glass has cracked into thousands of

Added a comment: pv panels
diff --git a/blog/entry/hacking_water/comment_2_a564768e0c41453a956a442322f98ede._comment b/blog/entry/hacking_water/comment_2_a564768e0c41453a956a442322f98ede._comment
new file mode 100644
index 00000000..fbd71146
--- /dev/null
+++ b/blog/entry/hacking_water/comment_2_a564768e0c41453a956a442322f98ede._comment
@@ -0,0 +1,12 @@
+[[!comment format=mdwn
+ username="val"
+ avatar="http://cdn.libravatar.org/avatar/53c3129da7459a10fa233e782dde5ed8"
+ subject="pv panels"
+ date="2019-06-16T04:34:07Z"
+ content="""
+out of curiosity how much solar do you have installed (how many 100w panels)
+
+also I noticed that the panel looked cracked, are you putting this in series with the other panels? This might reduce your yield by quite a lot.
+
+Nice write-up by the way.
+"""]]

Added a comment: Hey Joe
diff --git a/blog/entry/hacking_water/comment_1_ee4ad394abf97efff43dd3f33fa9a87b._comment b/blog/entry/hacking_water/comment_1_ee4ad394abf97efff43dd3f33fa9a87b._comment
new file mode 100644
index 00000000..cf4152c0
--- /dev/null
+++ b/blog/entry/hacking_water/comment_1_ee4ad394abf97efff43dd3f33fa9a87b._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="notjoey"
+ avatar="http://cdn.libravatar.org/avatar/a0071fb2ba33b0815fa61863b6e9d1bb"
+ subject="Hey Joe"
+ date="2019-06-16T01:24:09Z"
+ content="""
+where you goin' with that gun in your hand?
+"""]]

add pic
diff --git a/blog/entry/hacking_water.mdwn b/blog/entry/hacking_water.mdwn
index 3224eb1d..ea2a2b2d 100644
--- a/blog/entry/hacking_water.mdwn
+++ b/blog/entry/hacking_water.mdwn
@@ -113,6 +113,8 @@ the ground between two water tanks is a complex assembly of blue pipes and
 brass fittings, with several valves"]]
 [[!img blog/pics/hacking_water/oldsolarpaneldetail.jpg size=x300
 alt="close-up of old cracked solar panel"]]
+[[!img blog/pics/hacking_water/tanksinstalled.jpg size=x300
+alt="the two tanks installed, high on a hillside"]]
 
 Begin filling the tanks, unsure how long it will take as the pump balances
 available sunlight and spring flow.
diff --git a/blog/pics/hacking_water/tanksinstalled.jpg b/blog/pics/hacking_water/tanksinstalled.jpg
new file mode 100644
index 00000000..3b11d410
Binary files /dev/null and b/blog/pics/hacking_water/tanksinstalled.jpg differ

publish
diff --git a/blog/entry/hacking_plumbing.mdwn b/blog/entry/hacking_water.mdwn
similarity index 90%
rename from blog/entry/hacking_plumbing.mdwn
rename to blog/entry/hacking_water.mdwn
index df77b72e..3224eb1d 100644
--- a/blog/entry/hacking_plumbing.mdwn
+++ b/blog/entry/hacking_water.mdwn
@@ -9,10 +9,10 @@ enough to get through.
 And if I'm going to add storage, it ought to be above the house, so it can
 gravity flow. And I have these old 100 watts of solar panels sitting unused
 after my solar upgrade. And a couple of pumps for a pressure tank system
-that was not working when I moved in. And I stumbled across an old logging
-road high up the hillside. And there's an old copper pipe next to the
-house's retaining wall; email to Africa establishes that it goes down and
-through the wall and connects into the plumbing.
+that was not working when I moved in. And I stumbled across an odd little
+flat spot halfway up the hillside. And there's an exposed copper pipe next
+to the house's retaining wall; email to Africa establishes that it goes
+down and through the wall and connects into the plumbing.
 
 [[!img blog/pics/hacking_water/oldsolarpanel.jpg size=x300 alt="a solar
 panel with a large impact crater; the glass has cracked into thousands of
@@ -25,7 +25,8 @@ black plastic curves out of the ground next to a wall"]]
 So I have an old system that doesn't do what I want. Let's hack the
 system..
 
-(This took a year to put together.)
+(This took a year to research and put together, including learning a lot
+about plumbing.)
 
 Run a cable from the old solar panels 75 feet over to the spring.
 Repurpose an old cooler as a pumphouse, to keep the rain off the Shurflow 
@@ -39,10 +40,8 @@ labeled PUMP, PV, HIGH, LOW, GND, FLOAT SWITCH"]]
 [[!img blog/pics/hacking_water/temporary_water_barrel.jpeg size=x300 alt="50 gallon water barrel
 perched on a hillside with some hoses connected to it"]]
 
-Run a temporary hose up to the logging road, and verify that the pump can
-**just** manage to push the water up there. Replace with PEX pipe. Don't
-want to bury this spring/summer pipe, but it's damaged by UV, so rake fall
-leaves over it.
+Run a temporary pipe up to the logging road, and verify that the pump can
+**just** manage to push the water up there.
 
 Sidetrack into a week spent cleaning out and re-sealing the spring's
 settling tank. This was yak shaving, but it was going to fail. Build a
@@ -60,9 +59,6 @@ tank with walls bright and new, water level sensors and pipe to pump"]]
 Install water level sensors in the settling tank, cut a hole for pipe, 
 connect to pumphouse.
 
-Learn plumbing. Every PEX connection method and their pros and cons.
-Learn how to solder copper pipe.
-
 Now how to bury 250 feet of PEX pipe a foot deep up a steep hillside
 covered in rock piles and trees that you don't want to cut down to make way
 for equipment? Research every possibility, and pick the one that involves a
@@ -72,18 +68,17 @@ repurposed linemans's tool resembling a medieval axe.
 with trees wherever there are not rocks"]]
 [[!img blog/pics/hacking_water/wilton_thinline_trenching_tool.jpeg size=x300 alt="just unboxed
 trenching tool looks like a large black metal spatula"]]
-
-Dig 100 feet of 1 inch wide trench in a single afternoon by hand. Zeno in
-on the rest of the 300 foot run. Gain ability to bury underground cables
-without raising a sweat as an accidental superpower. Arms ache for a full
-month afterwards.
-
 [[!img blog/pics/hacking_water/wilton_trench.jpeg size=x300 alt="30 feet of very narrow trench
 comes out of the woods and along the side of the house past the satellite
 internet dish"]]
 [[!img blog/pics/hacking_water/pipe_route.jpeg size=x300 alt="lines drawn
 over a photo of the hillside show the pipe's curving route to the top"]]
 
+Dig 100 feet of 1 inch wide trench in a single afternoon by hand. Zeno in
+on the rest of the 300 foot run. Gain ability to bury underground cables
+without raising a sweat as an accidental superpower. Arms ache for a full
+month afterwards.
+
 Connect it all up with a temporary water barrel, and it works! Gravity flow
 yields 30 PSI!
 
@@ -121,5 +116,3 @@ alt="close-up of old cracked solar panel"]]
 
 Begin filling the tanks, unsure how long it will take as the pump balances
 available sunlight and spring flow.
-
-[[!tag unfinished]]

add
diff --git a/blog/entry/hacking_plumbing.mdwn b/blog/entry/hacking_plumbing.mdwn
index f99c61d5..df77b72e 100644
--- a/blog/entry/hacking_plumbing.mdwn
+++ b/blog/entry/hacking_plumbing.mdwn
@@ -14,7 +14,9 @@ road high up the hillside. And there's an old copper pipe next to the
 house's retaining wall; email to Africa establishes that it goes down and
 through the wall and connects into the plumbing.
 
-TODO solar panel picture
+[[!img blog/pics/hacking_water/oldsolarpanel.jpg size=x300 alt="a solar
+panel with a large impact crater; the glass has cracked into thousands of
+peices but is still hanging together"]]
 [[!img blog/pics/hacking_water/loggingroad.jpeg size=x300 alt="barely perceptable flat spot on tree
 covered hillside"]]
 [[!img blog/pics/hacking_water/copper_pipe_to_house.jpeg size=x300 alt="a copper pipe sheathed in
@@ -70,17 +72,18 @@ repurposed linemans's tool resembling a medieval axe.
 with trees wherever there are not rocks"]]
 [[!img blog/pics/hacking_water/wilton_thinline_trenching_tool.jpeg size=x300 alt="just unboxed
 trenching tool looks like a large black metal spatula"]]
-[[!img blog/pics/hacking_water/wilton_trench.jpeg size=x300 alt="30 feet of very narrow trench
-comes out of the woods and along the side of the house past the satellite
-internet dish"]]
-[[!img blog/pics/hacking_water/pipe_route.jpeg size=x300 alt="lines drawn
-over a photo of the hillside show the pipe's curving route to the top"]]
 
 Dig 100 feet of 1 inch wide trench in a single afternoon by hand. Zeno in
 on the rest of the 300 foot run. Gain ability to bury underground cables
 without raising a sweat as an accidental superpower. Arms ache for a full
 month afterwards.
 
+[[!img blog/pics/hacking_water/wilton_trench.jpeg size=x300 alt="30 feet of very narrow trench
+comes out of the woods and along the side of the house past the satellite
+internet dish"]]
+[[!img blog/pics/hacking_water/pipe_route.jpeg size=x300 alt="lines drawn
+over a photo of the hillside show the pipe's curving route to the top"]]
+
 Connect it all up with a temporary water barrel, and it works! Gravity flow
 yields 30 PSI!
 
@@ -95,7 +98,8 @@ house"]]
 faucet with water flowing into the kitchen sink"]]
 
 Clear a 6 foot wide path through the woods up the hill and roll up two 550
-gallon Norwesco water tanks. Level and prepare two 6 foot diameter pads.
+gallon Norwesco water tanks. Haul 650 pounds of sand up the hill, by hand,
+one 5 gallon bucket at a time. Level and prepare two 6 foot diameter pads.
 
 [[!img blog/pics/hacking_water/tanktruck.jpeg size=x300 alt="Joey standing in front of a black 4x4
 pickup truck with a large white 550 gallon water tank on its side in the
@@ -109,25 +113,13 @@ strewn around the cramped worksite"]]
 Build a buried manifold with valves turned by water meter key. Include a
 fire hose outlet just in case.
 
+[[!img blog/pics/hacking_water/tankconnect.jpg size=x300 alt="in a hole in
+the ground between two water tanks is a complex assembly of blue pipes and
+brass fittings, with several valves"]]
+[[!img blog/pics/hacking_water/oldsolarpaneldetail.jpg size=x300
+alt="close-up of old cracked solar panel"]]
+
 Begin filling the tanks, unsure how long it will take as the pump balances
 available sunlight and spring flow.
 
-Done for now. 
-
-----
-
-As with any project, this has a continuing todo list:
-
-* Paint tanks black to prevent algae growth and freezing.
-* Run overflow down hill to 1500 gallon cistern by the house.
-* Install water pressure sensor in utility room, read by ADC and fed into
-  house computer to alert when water is low.
-* Solar powered hot water heater.
-* Set up aux pump back up from lower cistern to water tanks for use during
-  drought.
-* Direct final overflow onto rocks so a waterfall sounds when the system is
-  full.
-* Automatic winterization of the pump house with an arduino, temp sensor,
-  and some servos.
-
 [[!tag unfinished]]
diff --git a/blog/pics/hacking_water/oldsolarpanel.jpg b/blog/pics/hacking_water/oldsolarpanel.jpg
new file mode 100644
index 00000000..626158de
Binary files /dev/null and b/blog/pics/hacking_water/oldsolarpanel.jpg differ
diff --git a/blog/pics/hacking_water/oldsolarpaneldetail.jpg b/blog/pics/hacking_water/oldsolarpaneldetail.jpg
new file mode 100644
index 00000000..dc09afd3
Binary files /dev/null and b/blog/pics/hacking_water/oldsolarpaneldetail.jpg differ
diff --git a/blog/pics/hacking_water/tankconnect.jpg b/blog/pics/hacking_water/tankconnect.jpg
new file mode 100644
index 00000000..54b2f4e6
Binary files /dev/null and b/blog/pics/hacking_water/tankconnect.jpg differ

add
diff --git a/blog/entry/hacking_plumbing.mdwn b/blog/entry/hacking_plumbing.mdwn
index 20616be6..f99c61d5 100644
--- a/blog/entry/hacking_plumbing.mdwn
+++ b/blog/entry/hacking_plumbing.mdwn
@@ -14,6 +14,12 @@ road high up the hillside. And there's an old copper pipe next to the
 house's retaining wall; email to Africa establishes that it goes down and
 through the wall and connects into the plumbing.
 
+TODO solar panel picture
+[[!img blog/pics/hacking_water/loggingroad.jpeg size=x300 alt="barely perceptable flat spot on tree
+covered hillside"]]
+[[!img blog/pics/hacking_water/copper_pipe_to_house.jpeg size=x300 alt="a copper pipe sheathed in
+black plastic curves out of the ground next to a wall"]]
+
 So I have an old system that doesn't do what I want. Let's hack the
 system..
 
@@ -24,6 +30,13 @@ Repurpose an old cooler as a pumphouse, to keep the rain off the Shurflow
 pump, and with the opening facing so it directs noise away from living areas.
 Add a Shurflow 902-200 linear current booster to control the pump.
 
+[[!img blog/pics/hacking_water/pump_house.jpeg size=x300 alt="red cooler attached to a tree with a
+pump in it. water is streaming out of one of the two pipes attached to it"]]
+[[!img blog/pics/hacking_water/pump_controller.jpeg size=x300 alt="circuit board with terminals
+labeled PUMP, PV, HIGH, LOW, GND, FLOAT SWITCH"]]
+[[!img blog/pics/hacking_water/temporary_water_barrel.jpeg size=x300 alt="50 gallon water barrel
+perched on a hillside with some hoses connected to it"]]
+
 Run a temporary hose up to the logging road, and verify that the pump can
 **just** manage to push the water up there. Replace with PEX pipe. Don't
 want to bury this spring/summer pipe, but it's damaged by UV, so rake fall
@@ -34,6 +47,14 @@ settling tank. This was yak shaving, but it was going to fail. Build a
 custom ladder because regular ladders are too wide to fit into it.
 Flashback to my tightest squeezes from caving. Yuurgh.
 
+[[!img blog/pics/hacking_water/settling_tank_ladder.jpeg size=x300 alt="very narrow concrete
+water tank with its concrete lid opened and a rough wooden ladder sticking
+out of it"]]
+[[!img blog/pics/hacking_water/settling_tank_original.jpeg size=x300 alt="interior of water tank
+drained with muck covering the bottom and plaster flaking from walls"]]
+[[!img blog/pics/hacking_water/settling_tank_reconditioned.jpeg size=x300 alt="interior of water
+tank with walls bright and new, water level sensors and pipe to pump"]]
+
 Install water level sensors in the settling tank, cut a hole for pipe, 
 connect to pumphouse.
 
@@ -43,10 +64,20 @@ Learn how to solder copper pipe.
 Now how to bury 250 feet of PEX pipe a foot deep up a steep hillside
 covered in rock piles and trees that you don't want to cut down to make way
 for equipment? Research every possibility, and pick the one that involves a
-repurposed linemans's tool resembling a mediaval axe. 
-
-Dig a hundred feet of 1 inch wide trench in a single afternoon by hand.
-Zeno in on the rest of the run. Gain ability to bury underground cables
+repurposed linemans's tool resembling a medieval axe. 
+
+[[!img blog/pics/hacking_water/rocky_path.jpeg size=x300 alt="hillside strewn in large rocks
+with trees wherever there are not rocks"]]
+[[!img blog/pics/hacking_water/wilton_thinline_trenching_tool.jpeg size=x300 alt="just unboxed
+trenching tool looks like a large black metal spatula"]]
+[[!img blog/pics/hacking_water/wilton_trench.jpeg size=x300 alt="30 feet of very narrow trench
+comes out of the woods and along the side of the house past the satellite
+internet dish"]]
+[[!img blog/pics/hacking_water/pipe_route.jpeg size=x300 alt="lines drawn
+over a photo of the hillside show the pipe's curving route to the top"]]
+
+Dig 100 feet of 1 inch wide trench in a single afternoon by hand. Zeno in
+on the rest of the 300 foot run. Gain ability to bury underground cables
 without raising a sweat as an accidental superpower. Arms ache for a full
 month afterwards.
 
@@ -57,22 +88,46 @@ Pressure-test the copper pipe going into the house to make sure it's not
 leaking behind the retaining wall. Fix all the old leaky plumbing and
 fixtures in the house.
 
+[[!img blog/pics/hacking_water/pressure_test.jpeg size=x300 alt="water pressure guage connected to
+PEX pipe coming out of trench and connecting to copper pipe that goes into
+house"]]
+[[!img blog/pics/hacking_water/faucet.jpeg size=x300 alt="modern restaurant-style sprung arched
+faucet with water flowing into the kitchen sink"]]
+
 Clear a 6 foot wide path through the woods up the hill and roll up two 550
 gallon Norwesco water tanks. Level and prepare two 6 foot diameter pads.
-Build an buried manifold with valves turned by water meter key. Include a
+
+[[!img blog/pics/hacking_water/tanktruck.jpeg size=x300 alt="Joey standing in front of a black 4x4
+pickup truck with a large white 550 gallon water tank on its side in the
+bed and arching high above"]]
+[[!img blog/pics/hacking_water/tankroll.jpeg size=x300 alt="Joey from the back as he rolls water
+tank up a forested hill"]]
+[[!img blog/pics/hacking_water/tankpad.jpeg size=x300 alt="six foot circle marked off with rope
+and filled with sand; a water tank is in the background and tools are
+strewn around the cramped worksite"]]
+
+Build a buried manifold with valves turned by water meter key. Include a
 fire hose outlet just in case.
 
 Begin filling the tanks, unsure how long it will take as the pump balances
-available sunlight and spring flow. Meanwhile, run an overflow pipe back
-down the hill to the 1500 gallon cistern by the house. Arrange it so the
-same pipe can be used to pump back from there up the hill if necessary.
+available sunlight and spring flow.
+
+Done for now. 
+
+----
 
-Direct the final overflow onto some rocks, so the sound of a waterfall
-indicates when all storage is full.
+As with any project, this has a continuing todo list:
 
-Paint the tanks black to prevent algae growth in summer and freezing in
-winter. Install a water pressure sensor in the utility room, to eventually
-be read by a ADC and fed into the house computer, to alert when the water
-is running low.
+* Paint tanks black to prevent algae growth and freezing.
+* Run overflow down hill to 1500 gallon cistern by the house.
+* Install water pressure sensor in utility room, read by ADC and fed into
+  house computer to alert when water is low.
+* Solar powered hot water heater.
+* Set up aux pump back up from lower cistern to water tanks for use during
+  drought.
+* Direct final overflow onto rocks so a waterfall sounds when the system is
+  full.
+* Automatic winterization of the pump house with an arduino, temp sensor,
+  and some servos.
 
 [[!tag unfinished]]
diff --git a/blog/pics/hacking_water/copper_pipe_to_house.jpeg b/blog/pics/hacking_water/copper_pipe_to_house.jpeg
new file mode 100644
index 00000000..95471c79
Binary files /dev/null and b/blog/pics/hacking_water/copper_pipe_to_house.jpeg differ
diff --git a/blog/pics/hacking_water/faucet.jpeg b/blog/pics/hacking_water/faucet.jpeg
new file mode 100644
index 00000000..22e32d5e
Binary files /dev/null and b/blog/pics/hacking_water/faucet.jpeg differ
diff --git a/blog/pics/hacking_water/loggingroad.jpeg b/blog/pics/hacking_water/loggingroad.jpeg
new file mode 100644
index 00000000..e8d8c45a
Binary files /dev/null and b/blog/pics/hacking_water/loggingroad.jpeg differ
diff --git a/blog/pics/hacking_water/pipe_route.jpeg b/blog/pics/hacking_water/pipe_route.jpeg
new file mode 100644
index 00000000..84b8198d
Binary files /dev/null and b/blog/pics/hacking_water/pipe_route.jpeg differ
diff --git a/blog/pics/hacking_water/pressure_test.jpeg b/blog/pics/hacking_water/pressure_test.jpeg
new file mode 100644
index 00000000..dd156439
Binary files /dev/null and b/blog/pics/hacking_water/pressure_test.jpeg differ
diff --git a/blog/pics/hacking_water/pump_controller.jpeg b/blog/pics/hacking_water/pump_controller.jpeg
new file mode 100644
index 00000000..9d86c358
Binary files /dev/null and b/blog/pics/hacking_water/pump_controller.jpeg differ
diff --git a/blog/pics/hacking_water/pump_house.jpeg b/blog/pics/hacking_water/pump_house.jpeg
new file mode 100644
index 00000000..d586970b
Binary files /dev/null and b/blog/pics/hacking_water/pump_house.jpeg differ
diff --git a/blog/pics/hacking_water/rocky_path.jpeg b/blog/pics/hacking_water/rocky_path.jpeg
new file mode 100644
index 00000000..6e3bc6af
Binary files /dev/null and b/blog/pics/hacking_water/rocky_path.jpeg differ
diff --git a/blog/pics/hacking_water/rough_elevation.png b/blog/pics/hacking_water/rough_elevation.png
new file mode 100644
index 00000000..f029d916
Binary files /dev/null and b/blog/pics/hacking_water/rough_elevation.png differ
diff --git a/blog/pics/hacking_water/settling_tank_ladder.jpeg b/blog/pics/hacking_water/settling_tank_ladder.jpeg
new file mode 100644
index 00000000..12100a01
Binary files /dev/null and b/blog/pics/hacking_water/settling_tank_ladder.jpeg differ
diff --git a/blog/pics/hacking_water/settling_tank_original.jpeg b/blog/pics/hacking_water/settling_tank_original.jpeg
new file mode 100644
index 00000000..c1baa08b
Binary files /dev/null and b/blog/pics/hacking_water/settling_tank_original.jpeg differ
diff --git a/blog/pics/hacking_water/settling_tank_reconditioned.jpeg b/blog/pics/hacking_water/settling_tank_reconditioned.jpeg
new file mode 100644
index 00000000..044f5221
Binary files /dev/null and b/blog/pics/hacking_water/settling_tank_reconditioned.jpeg differ
diff --git a/blog/pics/hacking_water/tankpad.jpeg b/blog/pics/hacking_water/tankpad.jpeg
new file mode 100644
index 00000000..849a9cf2
Binary files /dev/null and b/blog/pics/hacking_water/tankpad.jpeg differ
diff --git a/blog/pics/hacking_water/tankroll.jpeg b/blog/pics/hacking_water/tankroll.jpeg
new file mode 100644
index 00000000..462321f7
Binary files /dev/null and b/blog/pics/hacking_water/tankroll.jpeg differ
diff --git a/blog/pics/hacking_water/tanktruck.jpeg b/blog/pics/hacking_water/tanktruck.jpeg
new file mode 100644
index 00000000..5863e3f5
Binary files /dev/null and b/blog/pics/hacking_water/tanktruck.jpeg differ
diff --git a/blog/pics/hacking_water/temporary_water_barrel.jpeg b/blog/pics/hacking_water/temporary_water_barrel.jpeg
new file mode 100644
index 00000000..d680e62c
Binary files /dev/null and b/blog/pics/hacking_water/temporary_water_barrel.jpeg differ
diff --git a/blog/pics/hacking_water/wilton_thinline_trenching_tool.jpeg b/blog/pics/hacking_water/wilton_thinline_trenching_tool.jpeg
new file mode 100644
index 00000000..aa3e2b2a
Binary files /dev/null and b/blog/pics/hacking_water/wilton_thinline_trenching_tool.jpeg differ
diff --git a/blog/pics/hacking_water/wilton_trench.jpeg b/blog/pics/hacking_water/wilton_trench.jpeg
new file mode 100644
index 00000000..af19fd06
Binary files /dev/null and b/blog/pics/hacking_water/wilton_trench.jpeg differ

update
diff --git a/blog/entry/hacking_plumbing.mdwn b/blog/entry/hacking_plumbing.mdwn
index 7c4ef171..20616be6 100644
--- a/blog/entry/hacking_plumbing.mdwn
+++ b/blog/entry/hacking_plumbing.mdwn
@@ -1,53 +1,78 @@
-From water insecurity to offgrid, solar pumped, gravity flow 2500 gallons
+From water insecurity to offgrid, solar pumped, gravity flow 1000 gallons
 of running water.
 
 I enjoy hauling water by hand, which is why doing it for 8 years was not
 really a problem. But water insecurity is; the spring has been drying up
 for longer periods in the fall, and the cisterns have barely been large
-enough.
+enough to get through.
 
 And if I'm going to add storage, it ought to be above the house, so it can
-gravity flow. And I have these old 100 watts of solar panels sitting unused.
-And a couple of pumps for a pressure tank system that was not working when
-I moved in. And I stumbled across an old logging road high up the hillside.
-And there's an old copper pipe next to the house's retaining wall; email to
-Africa establishes that it goes down and through the wall and connects into
-the plumbing.
+gravity flow. And I have these old 100 watts of solar panels sitting unused
+after my solar upgrade. And a couple of pumps for a pressure tank system
+that was not working when I moved in. And I stumbled across an old logging
+road high up the hillside. And there's an old copper pipe next to the
+house's retaining wall; email to Africa establishes that it goes down and
+through the wall and connects into the plumbing.
 
 So I have an old system that doesn't do what I want. Let's hack the
 system..
 
 (This took a year to put together.)
 
-Run a cable from the old solar panels 75 feet over to the cistern.
+Run a cable from the old solar panels 75 feet over to the spring.
 Repurpose an old cooler as a pumphouse, to keep the rain off the Shurflow 
 pump, and with the opening facing so it directs noise away from living areas.
 Add a Shurflow 902-200 linear current booster to control the pump.
 
-Run a temporary hose up to the logging road, and verify that the pump can **just**
-manage to push the water up there. Replace with PEX pipe. Don't want to
-bury this spring/summer pipe, but it's damaged by UV, so rake fall
+Run a temporary hose up to the logging road, and verify that the pump can
+**just** manage to push the water up there. Replace with PEX pipe. Don't
+want to bury this spring/summer pipe, but it's damaged by UV, so rake fall
 leaves over it.
 
-Sidetrack into a week spent cleaning out and re-sealing the cistern.
-This is yak shaving, but it was going to fail. Build a custom ladder
-because regular ladders are too wide to fit into it. Yuurgh.
+Sidetrack into a week spent cleaning out and re-sealing the spring's
+settling tank. This was yak shaving, but it was going to fail. Build a
+custom ladder because regular ladders are too wide to fit into it.
+Flashback to my tightest squeezes from caving. Yuurgh.
 
-Install water level sensors in the cistern, cut a hole for pipe, 
+Install water level sensors in the settling tank, cut a hole for pipe, 
 connect to pumphouse.
 
 Learn plumbing. Every PEX connection method and their pros and cons.
 Learn how to solder copper pipe.
 
-Now how to bury 250 feet of PEX pipe a foot deep down a steep hillside
+Now how to bury 250 feet of PEX pipe a foot deep up a steep hillside
 covered in rock piles and trees that you don't want to cut down to make way
-for eqipment? Research every possibility, and pick the one that involves a
-repurposed linemans's tool resembling a mediaval axe. Dig a hundred feet of
-trench in a single afternoon by hand. Zeno in on the rest of the run. Gain
-ability to bury underground cables without raising a sweat as an accidental
-superpower.
-
-Connect it all up with a temporary water tank, and it works!
-Pressure-test at 30 PSI.
+for equipment? Research every possibility, and pick the one that involves a
+repurposed linemans's tool resembling a mediaval axe. 
+
+Dig a hundred feet of 1 inch wide trench in a single afternoon by hand.
+Zeno in on the rest of the run. Gain ability to bury underground cables
+without raising a sweat as an accidental superpower. Arms ache for a full
+month afterwards.
+
+Connect it all up with a temporary water barrel, and it works! Gravity flow
+yields 30 PSI!
+
+Pressure-test the copper pipe going into the house to make sure it's not
+leaking behind the retaining wall. Fix all the old leaky plumbing and
+fixtures in the house.
+
+Clear a 6 foot wide path through the woods up the hill and roll up two 550
+gallon Norwesco water tanks. Level and prepare two 6 foot diameter pads.
+Build an buried manifold with valves turned by water meter key. Include a
+fire hose outlet just in case.
+
+Begin filling the tanks, unsure how long it will take as the pump balances
+available sunlight and spring flow. Meanwhile, run an overflow pipe back
+down the hill to the 1500 gallon cistern by the house. Arrange it so the
+same pipe can be used to pump back from there up the hill if necessary.
+
+Direct the final overflow onto some rocks, so the sound of a waterfall
+indicates when all storage is full.
+
+Paint the tanks black to prevent algae growth in summer and freezing in
+winter. Install a water pressure sensor in the utility room, to eventually
+be read by a ADC and fed into the house computer, to alert when the water
+is running low.
 
 [[!tag unfinished]]

added two suggestions: even and wol
diff --git a/code/moreutils/discussion.mdwn b/code/moreutils/discussion.mdwn
index d05982cc..2a9a6571 100644
--- a/code/moreutils/discussion.mdwn
+++ b/code/moreutils/discussion.mdwn
@@ -1,6 +1,15 @@
 Feel free to edit this page to suggest tools to add, or make any other
 comments --[[Joey]]
 
+## tool suggestion: "even" and "wol"
+
+Written these two tiny tools, but figure they're useful to others:
+
+*even* was originally written to filter unicode files for use with grep/rg: https://gist.github.com/lionello/9166502
+
+*wol* is a portable wake-on-lan tool: https://gist.github.com/lionello/6481448
+
+
 ## tool suggestion: "fork after grep"
 
 I've written this tool for tzap (tuning DVB-T cards). Iit runs a process as a child, waits for a string to appear on its stdout/stderr, then daemonizes it.     

update
diff --git a/blog/entry/the_most_important_missing_unicode_extension.mdwn b/blog/entry/the_most_important_missing_unicode_extension.mdwn
index aaa4236a..aaa06cb5 100644
--- a/blog/entry/the_most_important_missing_unicode_extension.mdwn
+++ b/blog/entry/the_most_important_missing_unicode_extension.mdwn
@@ -6,7 +6,8 @@ Here's a symbol we all know well: &#65535;
 Aka, "box with 4 small F's in it".
 
 But that's not the only such symbol, there was a whole class of them in
-common use in the early 2000's, so common that they were called "tofu".
+common use in the early 2000's, so common that they were called "tofu" when
+grouped together.
 
 Modern unicode systems cannot display those historical characters!
 

blog update
diff --git a/blog/entry/the_most_important_missing_unicode_extension.mdwn b/blog/entry/the_most_important_missing_unicode_extension.mdwn
new file mode 100644
index 00000000..aaa4236a
--- /dev/null
+++ b/blog/entry/the_most_important_missing_unicode_extension.mdwn
@@ -0,0 +1,18 @@
+Unicode allows you to write any symbol in use in the world, and if one is
+somehow missing from Unicode, it'll get added in a future version of the
+specification. Right?
+
+Here's a symbol we all know well: &#65535;  
+Aka, "box with 4 small F's in it".
+
+But that's not the only such symbol, there was a whole class of them in
+common use in the early 2000's, so common that they were called "tofu".
+
+Modern unicode systems cannot display those historical characters!
+
+Clearly this needs to be fixed with an extension to the Unicode standard.
+I propose TOFU, a combining character that makes whatever it's combined
+with be displayed as a font fallback box glyph containing its Unicode code
+point.
+
+[[!tag unicode]]

Added a comment: Thank you!
diff --git a/blog/entry/80_percent/comment_1_6fb2810a54f7eecc08449f230a90c963._comment b/blog/entry/80_percent/comment_1_6fb2810a54f7eecc08449f230a90c963._comment
new file mode 100644
index 00000000..d18ab7c5
--- /dev/null
+++ b/blog/entry/80_percent/comment_1_6fb2810a54f7eecc08449f230a90c963._comment
@@ -0,0 +1,15 @@
+[[!comment format=mdwn
+ username="http://www.mirbsd.org/"
+ nickname="mirabilos"
+ avatar="http://cdn.libravatar.org/avatar/a023e7289de2880cf8d275a41e90c321ed7a5f5db9b3eef00ded69b878a1d367"
+ subject="Thank you!"
+ date="2019-05-27T15:31:17Z"
+ content="""
+Hi joeyh,
+
+thanks for expressing that; maybe this will have some weight.
+
+Despite initial reluctance, I adopted dh for some of my packages, but I still wish to have the flexibility to not use it (sometimes, a rules file with dh is longer and more complex than one without, due to the need for too many overrides; sometimes, buildsystem detection works against you, etc.), let alone the idea of being forced to use something turns me off of things.
+
+Being able to choose is **good**. (No matter what _some_ people say about this not being about choice, I disagree there.) Monocultures have inherent problems.
+"""]]

title
diff --git a/blog/entry/hacking_water_teaser.mdwn b/blog/entry/hacking_water_teaser.mdwn
index ff9c881a..b137a53d 100644
--- a/blog/entry/hacking_water_teaser.mdwn
+++ b/blog/entry/hacking_water_teaser.mdwn
@@ -1,3 +1,5 @@
 [[!img pics/trucktank.jpg alt="Joey standing in front of a black 4x4 pickup
 truck with a large white 550 gallon water tank on its side in the bed and
 arching high above"]]
+
+[[!meta title="hacking water (teaser)"]]

post
diff --git a/blog/entry/hacking_water_teaser.mdwn b/blog/entry/hacking_water_teaser.mdwn
new file mode 100644
index 00000000..ff9c881a
--- /dev/null
+++ b/blog/entry/hacking_water_teaser.mdwn
@@ -0,0 +1,3 @@
+[[!img pics/trucktank.jpg alt="Joey standing in front of a black 4x4 pickup
+truck with a large white 550 gallon water tank on its side in the bed and
+arching high above"]]
diff --git a/blog/pics/trucktank.jpg b/blog/pics/trucktank.jpg
new file mode 100644
index 00000000..5863e3f5
Binary files /dev/null and b/blog/pics/trucktank.jpg differ

ps
diff --git a/blog/entry/80_percent.mdwn b/blog/entry/80_percent.mdwn
index 3e2a5441..ba83f6e5 100644
--- a/blog/entry/80_percent.mdwn
+++ b/blog/entry/80_percent.mdwn
@@ -27,3 +27,7 @@ Starting at 100% and incrementally approaching 100% are very different
 design choices. The end results can look very similar, since in both cases
 it can appear that nearly everyone has settled on doing things in the same
 way. I feel though, that the underlying difference is important.
+
+PS: It's perhaps worth re-reading [the original debhelper email](https://lists.debian.org/debian-devel/1997/09/msg00901.html)
+and see how much my original problems with debstd would also apply to `dh` if
+its use were mandatory!

blog update
diff --git a/blog/entry/80_percent.mdwn b/blog/entry/80_percent.mdwn
new file mode 100644
index 00000000..3e2a5441
--- /dev/null
+++ b/blog/entry/80_percent.mdwn
@@ -0,0 +1,29 @@
+I added `dh` to debhelper a decade ago, and now Debian is considering
+making use of `dh` mandatory. Not being part of Debian anymore, I'm in
+the position of needing to point out something important about it anyway.
+So this post is less about pointing in a specific direction as giving a
+different angle to think about things.
+
+[[code/debhelper]] was intentionally designed as a 100% solution for
+simplifying building Debian packages. Any package it's used with gets
+simplified and streamlined and made less a bother to maintain. The way
+debhelper succeeds at 100% is not by doing everything, but by being usable
+in little pieces, that build up to a larger, more consistent whole, but
+that can just as well be used sparingly.
+
+`dh` was intentionally *not* designed to be a 100% solution, because it is
+not a collection of little pieces, but a framework. I first built
+an 80% solution, which is the canned sequences of commands it runs plus
+things like `dh_auto_build` that guess at how to build any software. Then I
+iterated to get closer to 100%. The main iteration was override targets in
+the debian/rules file, to let commands be skipped or run out of order or
+with options. That closed `dh`'s gap by a further 80%. 
+
+So, `dh` is probably somewhere around a 96% solution now. It may have crept
+closer still to 100%, but it seems likely there is still a gap, because it
+was never intended to completely close the gap. 
+
+Starting at 100% and incrementally approaching 100% are very different
+design choices. The end results can look very similar, since in both cases
+it can appear that nearly everyone has settled on doing things in the same
+way. I feel though, that the underlying difference is important.

update
diff --git a/contact.mdwn b/contact.mdwn
index cb322fe6..0ba240a2 100644
--- a/contact.mdwn
+++ b/contact.mdwn
@@ -1,5 +1,6 @@
 * email: <id@joeyh.name>
 * gpg key: [E85A 5F63 B31D 24C1 EBF0  D81C C910 D922 2512 E3C7](http://pgp.cs.uu.nl/stats/2512E3C7.html)
-* pump: <http://identi.ca/joeyh>
 * irc: joeyh (irc.oftc.net or irc.freenode.net)
+* mastodon: <a href="https://octodon.social/@joeyh">@joeyh@mastodon.social</a>
+* scuttlebutt: @BCM6DHYJvWzwWi1lFl2tjDXjaqyZAEmJH5ZONSpXhtc=.ed2551
 * some ways to send me a "thank you" for my work, if you're so inclined: [[thanks]]

Added a comment: sshdo
diff --git a/blog/entry/locking_down_ssh_authorized_keys/comment_4_daa16632d108bdfdec87ddc252772659._comment b/blog/entry/locking_down_ssh_authorized_keys/comment_4_daa16632d108bdfdec87ddc252772659._comment
new file mode 100644
index 00000000..338cf4f6
--- /dev/null
+++ b/blog/entry/locking_down_ssh_authorized_keys/comment_4_daa16632d108bdfdec87ddc252772659._comment
@@ -0,0 +1,25 @@
+[[!comment format=mdwn
+ username="joeyh@8cf8d34ae36060dccbe17095054064379c6214f1"
+ nickname="joeyh"
+ avatar="http://cdn.libravatar.org/avatar/062ee95a05337ca29b8ea6b1f08c213b"
+ subject="sshdo"
+ date="2019-04-23T02:31:00Z"
+ content="""
+[Disclosure: I wrote sshdo which is described below]
+
+There's a program called sshdo for doing this. It controls which commands may be executed via incoming ssh connections. It's available for download at:
+
+    http://raf.org/sshdo/ (read manual pages here)
+    https://github.com/raforg/sshdo/
+
+It has a training mode to allow all commands that are attempted, and a --learn option to produce the configuration needed to allow learned commands permanently. Then training mode can be turned off and any other commands will not be executed.
+
+It also has an --unlearn option to stop allowing commands that are no longer in use so as to maintain strict least privilege as requirements change over time.
+
+It is very fussy about what it allows. It won't allow a command with any arguments. Only complete shell commands can be allowed.
+
+But it does support simple patterns to represent similar commands that vary only in the digits that appear on the command line (e.g. sequence numbers or date/time stamps).
+
+It's like a firewall or whitelisting control for ssh commands.
+
+"""]]

renamed homepower to house
diff --git a/blog/entry/AIMS_inverter_control_via_GPIO_ports.mdwn b/blog/entry/AIMS_inverter_control_via_GPIO_ports.mdwn
index 824a6187..121f9ac1 100644
--- a/blog/entry/AIMS_inverter_control_via_GPIO_ports.mdwn
+++ b/blog/entry/AIMS_inverter_control_via_GPIO_ports.mdwn
@@ -31,7 +31,7 @@ myself.
 [[!img pics/aimsinvertercontrolschematic.jpg size=400x]]
 
 The full schematic and haskell code to control the inverter are in
-the git repository <https://git.joeyh.name/index.cgi/joey/homepower.git/tree/>.
+the git repository <https://git.joeyh.name/index.cgi/joey/house.git/tree/>.
 My design notebook for this build is [available in secure scuttlebutt](https://viewer.scuttlebot.io/%25EvpWKGJyYIuSiOr3WjDsBCVHLIkt5Ncqd7lBsLX%2B9bs%3D.sha256)
 along with [power consumption measurements](https://viewer.scuttlebot.io/%25lPj7KktYPERL4N3WpF64UXFjcj19mDpt5F1YVblYi2k%3D.sha256).
 
diff --git a/blog/entry/fridge_0.1.mdwn b/blog/entry/fridge_0.1.mdwn
index cbadaea0..2f881205 100644
--- a/blog/entry/fridge_0.1.mdwn
+++ b/blog/entry/fridge_0.1.mdwn
@@ -13,9 +13,9 @@ control system, the fridge itself becomes the battery -- a cold battery.
 I'm live coding my fridge, with that goal in mind.
 You can follow along in
 [this design thread on secure scuttlebutt](https://viewer.scuttlebot.io/%25Pg7%2BlVNJS13o2GBftbMLC2V0BgB3PSeX1L3cVdnUifc%3D.sha256),
-and [my git commits](https://git.joeyh.name/index.cgi/joey/homepower.git/log/),
+and [my git commits](https://git.joeyh.name/index.cgi/joey/house.git/log/),
 and you can watch
-[real-time data from my fridge](http://homepower.joeyh.name/fridge.html).
+[real-time data from my fridge](http://house.joeyh.name/fridge.html).
 
 Over the past two days, which were not especially sunny, my 1 kilowatt of
 solar panels has managed to cool the fridge down close to standard fridge
diff --git a/blog/entry/fridge_0.2.mdwn b/blog/entry/fridge_0.2.mdwn
index 35ed3699..bfd83669 100644
--- a/blog/entry/fridge_0.2.mdwn
+++ b/blog/entry/fridge_0.2.mdwn
@@ -3,7 +3,7 @@ has sucessfully made it through spring, summer, fall, and more than enough winte
 
 I've proven that it works. I've not gotten food poisoning, though I did lose
 half a gallon of milk on one super rainy week. I have 
-[piles of data](http://homepower.joeyh.name/fridge.html), and
+[piles of data](http://house.joeyh.name/fridge.html), and
 [a whole wiki](https://fridge0.branchable.com/) documenting how I built
 it. I've developed 3 thousand lines of control software. It purrs along
 without any assistance.
diff --git a/blog/entry/home_power_monitoring.mdwn b/blog/entry/home_power_monitoring.mdwn
index af8ef306..e54843f8 100644
--- a/blog/entry/home_power_monitoring.mdwn
+++ b/blog/entry/home_power_monitoring.mdwn
@@ -6,12 +6,12 @@ finally let me automate it.
 [[!img blog/pics/homepower.png caption="morning activity; by 8 am the sun is still behind the hill but, 
 16 watts are being produced, and by 11:30 am, the battery bank is full"]]
 
-You can explore my home power data here: <http://homepower.joeyh.name/>  
+You can explore my home power data here: <http://house.joeyh.name/>  
 (click and drag to zoom)
 
 The web interface loads the RRD files into a web browser
 using [javascriptRRD](http://javascriptrrd.sourceforge.net/).
-I wrote a [haskell program](https://git.joeyh.name/index.cgi/joey/homepower.git/tree/poller.hs)
+I wrote a [haskell program](https://git.joeyh.name/index.cgi/joey/house.git/tree/poller.hs)
 that drives the
 [epsolar-tracer python library](https://github.com/kasbert/epsolar-tracer)
 to poll for data, and stores it in RRD files. Could have used collectd or
@@ -19,4 +19,4 @@ something, but the interface to the charge controller is currently
 a bit flakey and I have to be careful about retries and polling frequencies. 
 Also I wanted full control over how much data is stored in the RRD files.
 
-[Full source code](https://git.joeyh.name/index.cgi/joey/homepower.git/)
+[Full source code](https://git.joeyh.name/index.cgi/joey/house.git/)
diff --git a/blog/entry/more_fun_with_reactive-banana-automation.mdwn b/blog/entry/more_fun_with_reactive-banana-automation.mdwn
index d8d51377..8c2a4636 100644
--- a/blog/entry/more_fun_with_reactive-banana-automation.mdwn
+++ b/blog/entry/more_fun_with_reactive-banana-automation.mdwn
@@ -69,7 +69,7 @@ The sensor data is available over http, so I can run this controller
 code in test mode, on my laptop, and observe how it reacts to
 real-world circumstances.
 
-	joey@darkstar:~/src/homepower>./controller test
+	joey@darkstar:~/src/house>./controller test
 	InverterPower PowerOn
 	FridgeRelay PowerOff
 
diff --git a/blog/entry/my_haskell_controlled_offgrid_fridge.mdwn b/blog/entry/my_haskell_controlled_offgrid_fridge.mdwn
index fc20c5af..37218894 100644
--- a/blog/entry/my_haskell_controlled_offgrid_fridge.mdwn
+++ b/blog/entry/my_haskell_controlled_offgrid_fridge.mdwn
@@ -38,7 +38,7 @@ used for something else (and to partly tackle the problem of using
 real-world time events when the underlying FRP library uses its own
 notion of time).
 
-[The code for my fridge](https://git.joeyh.name/index.cgi/joey/homepower.git/tree/src/Automation/Fridge.hs) 
+[The code for my fridge](https://git.joeyh.name/index.cgi/joey/house.git/tree/src/Automation/Fridge.hs) 
 is a work in progress since the fridge has not arrived yet, and because
 the question of in which situations an offgrid fridge should optimally 
 run and not run is really rather complicated.
diff --git a/offgrid/photovoltaic.mdwn b/offgrid/photovoltaic.mdwn
index 0ddd3c91..ee645dfa 100644
--- a/offgrid/photovoltaic.mdwn
+++ b/offgrid/photovoltaic.mdwn
@@ -25,4 +25,4 @@ no problem from time to time. On a typical cloudy day they'll produce
 Total cost of my PV system was around $3000 in 2017. ($2000 after tax
 rebates.)
 
-[Graphs of my PV data are here](https://homepower.joeyh.name/).
+[Graphs of my PV data are here](https://house.joeyh.name/).

remove old pump feed
diff --git a/grep.mdwn b/grep.mdwn
index 7c2fb83d..c1e0db29 100644
--- a/grep.mdwn
+++ b/grep.mdwn
@@ -8,6 +8,5 @@ on the net.
 List of feeds:
 
 * [[!aggregate expirecount=25 name="music" feedurl="http://libre.fm/rdf.php?fmt=rss&page=%2Fuser%2Fjoeyhess%2Frecent-tracks" url="http://libre.fm/user/joeyhess"]]
-* [[!aggregate expirecount=25 name="identi.ca posts" feedurl="https://tmp.joeyh.name/pump.atom" url="http://identi.ca/joeyh"]]
 * [[!aggregate expirecount=25 name="mastadon posts" feedurl="https://octodon.social/users/joeyh.atom" url="https://octodon.social/users/joeyh"]]
 * [[!aggregate expirecount=25 name="books" feedurl="http://www.goodreads.com/review/list_rss/2159448?key=afd7e8432b3f9e33edab442a7c94e95849af4527&shelf=currently-reading" url="http://www.goodreads.com/user/show/2159448"]]

add
diff --git a/talks/git-annex-developer-workshop/notes.otl b/talks/git-annex-developer-workshop/notes.otl
new file mode 100644
index 00000000..11a12e8e
--- /dev/null
+++ b/talks/git-annex-developer-workshop/notes.otl
@@ -0,0 +1,167 @@
+Day 1 (4 hours)
+	12:15-4:30 pm
+	with lunch and coffee breaks
+intro (20 minutes)
+	bus factor
+	introductions
+		what's your git-annex skill level?
+		your Haskell skill level?
+	Haskell for Readers
+		http://joeyh.name/talks/git-annex-developer-workshop/haskell-for-readers
+	schedule overview
+building git-annex from source (10 minutes)
+	git clone git://git-annex.branchable.com/ git-annex
+	sudo apt-get install haskell-stack  /  http://haskellstack.org/
+	stack build
+		(older OS: stack build --stack-yaml stack-lts-9.9.yaml)
+git-annex core concepts and types (60 minutes)
+	Key
+		Types/Key.hs (aka Types.Key)
+		key/value storage
+			not encryption key
+		annex symlinks and links
+		show examples
+	UUID
+		Types.UUID
+		unique identifier for git repository / special remote
+			does a normal git repository have an identifier?
+				no
+				any clone is much like any other
+				git repositories may contain unique data
+					but then no other repo knows about it
+			why does git-annex need a repository identifier?
+				each clone may contain a different set of contents of files
+				needs to know where the contents of a file is located
+		NoUUID
+			ugly and hides problems
+			thought exercise
+				imagine getting rid of NoUUID constructor
+				use Maybe UUID instead
+				eliminate the Maybe where possible
+	Remote
+		Types.Remote
+		git remote
+		special remote
+		important fields of the Remote data type
+			uuid
+			cost
+			storeKey
+			retrieveKeyFile
+			removeKey
+			checkPresent
+		compare Remote with external special remote protocol
+			http://git-annex.branchable.com/design/external_special_remote_protocol/
+interlude: how we use git-annex (30-60 minutes)
+	me
+		I built it for my own personal use
+		glimpse inside some of my git-annex repos and workflows
+	how datalad uses git-annex
+		over to yarik and michael
+	how others here use git-annex
+git-annex core concepts continued (30 minutes)
+	recap
+		Key
+		UUID
+		Remote
+	git-annex branch
+		http://git-annex.branchable.com/internals/
+		union merging
+		CRDTs & vector clocks
+			Annex.VectorClock
+		example
+			location tracking
+			Logs.Presence.Pure
+				LogLine
+				LogStatus
+				logParser
+				buildLog
+		exercise
+			design a new git-annex branch file format
+			how does this interact with union merging?
+			how are old values removed from the file?
+		space efficiency
+			repeated uuids, timestamps, etc		
+			git gc
+	what core git-annex concepts *don't* have types?
+		git-annex branch files
+		git-annex object files
+		would adding types for these improve the code?
+case study: adding a new, major feature to git-annex (60 minutes)
+	git-annex import tree
+		http://git-annex.branchable.com/design/importing_trees_from_special_remotes/
+	high level design
+		dual of export tree
+			after importing, exporting the same tree is a no-op
+			after exporting, importing yields the same tree
+		lists content of special remote
+		downloads new content from special remote
+			(necessary to generate keys?)
+		builds a git tree of its contents
+		potential for export tree conflict
+			important sticking point in design
+			mitigations
+				race safety via good ContentIdentifier
+				S3 versioning
+	UI
+		analogy to git fetch / git push
+			import tree and git fetch both update remote tracking branch
+				refs/remotes/$name/master 
+			git push and export tree also update remote tracking branch
+				to reflect their changes to the remote
+		import/export special remote becomes similar to a git working tree
+			without .git
+			but with files that may be modified there and later imported
+	api design
+		ImportActions
+	data types
+		ImportLocation
+		ContentIdentifier
+			storage
+				git-annex branch
+				Logs.ContentIdentifier
+			mappings between ContentIdentifier and Key
+				local sqlite database
+					Database.ContentIdentifier
+		ImportableContents
+		RemoteTrackingBranch
+		ImportTreeConfig
+		ImportCommitConfig
+	option parsing
+		Parser ImportOptions
+			added RemoteImportOptions
+			optparse-applicative
+planning for tomorrow (10 minutes)
+	start thinking about a feature you'd like to see in git-annex
+	or a part of git-annex implementation you want to explore
+	to discuss tomorrow morning
+
+Day 2 (4 hours)
+	9 am-1pm with coffee and lunch breaks
+git-annex implementation details (60 minutes)
+	not as core as Key, UUID, Remote, but all over the code
+	Git
+		Repo
+		Ref
+		Branch
+		Sha
+		Tag
+		exercise
+			Ref, Branch, Sha, Tag are all aliases
+			not type safe!
+			no distinction at all between Commit, Tree, Object
+			split into separate types for type safety
+				perhaps Ref Tag, Ref Commit, Ref Tree, Ref Object
+				and Sha Tag, Sha Commit, Sha Tree, Sha Object
+		why is Git interface in git-annex at all?
+	GitConfig
+		exercise
+			add a new git config value to it
+	Annex
+			monad
+			"global" state
+				gitRepo
+				getGitConfig
+				remoteList
+	Types.Command
+discussion: designing new git-annex features (120 minutes)
+	discuss participants' feature ideas and think about designs

remove termcast
diff --git a/links/technical.mdwn b/links/technical.mdwn
index 6438c561..8a8ecd2e 100644
--- a/links/technical.mdwn
+++ b/links/technical.mdwn
@@ -5,6 +5,5 @@
 [[offgrid]]  
 [[talks]]  
 [[screencasts]]  
-[[termcasts|termcast]]  
 [[rfcs|rfc]]  
 [[boxen]]  

openid port
diff --git a/index.mdwn b/index.mdwn
index fe978e51..3c618ab0 100644
--- a/index.mdwn
+++ b/index.mdwn
@@ -52,4 +52,4 @@ show=5 feeds=no archive=yes]]
 """]]
 
 [[!meta openid="http://joeyh.name/"
-server="http://openid.kitenet.net:8081/simpleid/"]]
+server="http://openid.kitenet.net:8086/simpleid/"]]

rename
diff --git a/talks/git-annex-implementors-workshop/haskell-for-readers.mdwn b/talks/git-annex-developer-workshop/haskell-for-readers.mdwn
similarity index 100%
rename from talks/git-annex-implementors-workshop/haskell-for-readers.mdwn
rename to talks/git-annex-developer-workshop/haskell-for-readers.mdwn

update
diff --git a/offgrid/photovoltaic.mdwn b/offgrid/photovoltaic.mdwn
index 3ca3c7cc..0ddd3c91 100644
--- a/offgrid/photovoltaic.mdwn
+++ b/offgrid/photovoltaic.mdwn
@@ -22,6 +22,7 @@ which is a lean day and limits my use of the more power hungry stuff, but
 no problem from time to time. On a typical cloudy day they'll produce
 500+ watt-hours, which is all that I need to run everything.
 
-Total cost of my PV system was around $3000 in 2017.
+Total cost of my PV system was around $3000 in 2017. ($2000 after tax
+rebates.)
 
 [Graphs of my PV data are here](https://homepower.joeyh.name/).

link
diff --git a/offgrid.mdwn b/offgrid.mdwn
index bafd7921..3bbd4466 100644
--- a/offgrid.mdwn
+++ b/offgrid.mdwn
@@ -12,3 +12,5 @@ Here I'll go into detail about each of the offgrid systems of the house.
 * [[water system|water]]
 * [[internet]]
 * [[heating and cooling|hvac]]
+
+Also, see my blog posts tagged [[blog/solar]].

link
diff --git a/blog/solar.mdwn b/blog/solar.mdwn
index d81458ca..ee53e0b2 100644
--- a/blog/solar.mdwn
+++ b/blog/solar.mdwn
@@ -1,4 +1,4 @@
-Posts related to solar power and off the grid living.
+Posts related to solar power and [[offgrid]] living.
 
 [[!inline pages="blog/entry/* and link(solar) and !*/Discussion"
 actions=yes show=0]]

tweak
diff --git a/offgrid.mdwn b/offgrid.mdwn
index 6ed1145c..bafd7921 100644
--- a/offgrid.mdwn
+++ b/offgrid.mdwn
@@ -3,7 +3,7 @@ with only 1100 watts of solar power and only 4 golf cart batteries.
 
 I got here kind of by accident, see [[my_offgrid_story]].
 
-[[!img blog/pics/solar_upgrade/housepanels.jpg caption="house with solar panels" size=640x]]
+[[!img blog/pics/solar_upgrade/housepanels.jpg alt="house with solar panels" size=320x]]
 
 Here I'll go into detail about each of the offgrid systems of the house.
 

fix link
diff --git a/offgrid/fridge.mdwn b/offgrid/fridge.mdwn
index 0ccdf07b..5c297600 100644
--- a/offgrid/fridge.mdwn
+++ b/offgrid/fridge.mdwn
@@ -1,4 +1,4 @@
-Since I have a [[photovoltatic]] system with a purposefully
+Since I have a [[photovoltaic]] system with a purposefully
 undersized battery bank, refridgeration was a challenge. I succeeded.
 
 My fridge does not run from battery at all, only when the sun is shining.

updates
diff --git a/offgrid.mdwn b/offgrid.mdwn
index 8a14218c..6ed1145c 100644
--- a/offgrid.mdwn
+++ b/offgrid.mdwn
@@ -1,7 +1,10 @@
 My house is entirely offgrid and has an unusually small energy footprint,
 with only 1100 watts of solar power and only 4 golf cart batteries.
+
 I got here kind of by accident, see [[my_offgrid_story]].
 
+[[!img blog/pics/solar_upgrade/housepanels.jpg caption="house with solar panels" size=640x]]
+
 Here I'll go into detail about each of the offgrid systems of the house.
 
 * [[photovoltaic system|photovoltaic]]
diff --git a/offgrid/photovoltaic.mdwn b/offgrid/photovoltaic.mdwn
index 6547aa49..3ca3c7cc 100644
--- a/offgrid/photovoltaic.mdwn
+++ b/offgrid/photovoltaic.mdwn
@@ -1,4 +1,4 @@
-My house has a primary array of 4 260 watt solar panels. I 
+My house has a 1kw primary solar panel array. I 
 [[installed it|blog/entry/DIY_professional_grade_solar_panel_installation]]
 on the roof myself.
 
@@ -6,7 +6,7 @@ There's also an old array of 4 64 watt solar panels, though it's over 20
 years old and produces less than 128 watts now. 
 (Now used only for pumping [[water]]).
 
-The primary array is Astronergy 260 watt panels, mounted on
+The primary array is four Astronergy 260 watt panels, mounted on
 IronRidge XR100 rails.
 
 The charge controller is a Tracer4215BN. A modbus to usb adapter lets the
@@ -22,6 +22,6 @@ which is a lean day and limits my use of the more power hungry stuff, but
 no problem from time to time. On a typical cloudy day they'll produce
 500+ watt-hours, which is all that I need to run everything.
 
-Total cost of my PV system was around $3000.
+Total cost of my PV system was around $3000 in 2017.
 
 [Graphs of my PV data are here](https://homepower.joeyh.name/).

fix link
diff --git a/offgrid/my_offgrid_story.mdwn b/offgrid/my_offgrid_story.mdwn
index 2251b36e..5923db3e 100644
--- a/offgrid/my_offgrid_story.mdwn
+++ b/offgrid/my_offgrid_story.mdwn
@@ -19,7 +19,7 @@ though an adaption for a moister climate. It was mostly passively solar
 heated and cooled.
 
 I lived here first part-time and later full time for 7 years, did
-[[minor improvements|solar_charge_controller_adventure]] to the solar
+[[minor improvements|blog/entry/solar_charge_controller_adventure]] to the solar
 power system but mostly learned ways to live with
 [[very minimal power|blog/entry/solar_year]] while still working as a computer programmer.
 

fix link
diff --git a/offgrid/my_offgrid_story.mdwn b/offgrid/my_offgrid_story.mdwn
index 2e84bdee..2251b36e 100644
--- a/offgrid/my_offgrid_story.mdwn
+++ b/offgrid/my_offgrid_story.mdwn
@@ -21,7 +21,7 @@ heated and cooled.
 I lived here first part-time and later full time for 7 years, did
 [[minor improvements|solar_charge_controller_adventure]] to the solar
 power system but mostly learned ways to live with
-[[very minimal power|solar year]] while still working as a computer programmer.
+[[very minimal power|blog/entry/solar_year]] while still working as a computer programmer.
 
 Then I had to opportunity to purchase the house, and since then I've been
 upgrading its systems to the state described in these pages.

typo
diff --git a/offgrid/photovoltatic.mdwn b/offgrid/photovoltaic.mdwn
similarity index 100%
rename from offgrid/photovoltatic.mdwn
rename to offgrid/photovoltaic.mdwn