Skills

Male head with brain activity - Brain waves - X ray 3D illustration

The AI Assistant, Code

Does it work? Well, sort of.

I’m an old man. I am a trained systems analyst who loves to program. Back when I was working in a top level development group, we talked about the different types of programmers.

  1. Systems Analyst—A person capable of looking at how systems interact and designing systems.
  2. Analyst-A person that could look at a program and design programs
  3. Programmer-A person that could implement a design
  4. Coder-A person that could turn pseudocode into real code

Yes, I put myself at the top of that list. Not because I say so, but because my peers say so.

I enjoy every part of that stack. My family used to say that if I wasn’t programming, I wasn’t happy.

I still love programming. It still makes me happy.

Weaknesses

Today, it isn’t enough to know a language. You need to also know the libraries and the frameworks. And there are 1000s of libraries doing 1000s of things, some better than others.

To write good software today, you need to know your frameworks. But more than that, you need to know the patterns that work within that particular framework.

I just do not spend enough time in that world to know all the frameworks and all the patterns for those frameworks. Instead, I pick a framework and go for it.

My AI Assistant, Some Context

My development environment is Emacs with gptel. This environment gives me complete control of the AI’s context.

But what is “context”?

Context is all the information that is sent with your prompt. Which begs the question, “What is a prompt?”

When you are talking to an AI, everything you say to the AI is your prompt. “Who is the best chef?” can be a prompt. So is “In the fetch methods you are referencing self.client. This no longer exists; instead, we do client = GiteaClient() because GiteaClient is a singleton.”

The AI receives the prompt and evaluates it based on its training. Training is fixed. Every time you start a new conversation, you start with no history, just the trained AI. There is no doubt in my mind that any AI would be able to give some type of answer to “Who is the best chef?”

No AI, with just trained data would be able to answer the second prompt. It would have no references.

Context is all the extra stuff that gets sent with your prompt. That can include any files you explicitly sent. It will include your conversation, both what you sent as prompts and what it sent in reply.

It is that context that allows you to have a conversation that tracks.

My interface to my AI assistant allows me to add files as context. When I’m coding, the AI is sent the current version of my code files with each prompt.

Each buffer (Window) can have a different set of context files. In general, each code file buffer adds the other code files. All the code file buffers also add my master prompt for coding.

Finally, I have a conversation buffer. This is a buffer that has all code files and the master prompt as part of the context load.

Every time I send a prompt in the conversation buffer, everything above my cursor and all the file context is sent to the AI, which then responds.

My AI Assistant, What Should Work

What I want to happen is to be able to have the AI rewrite parts of code. The way this should work is that I highlight a section of code, start the rewrite process, I will be asked for a prompt: “Rewrite this if block to negate the test.” This is sent to the AI and the AI replies with pure code to replace what I had highlighted.

My tool shows me the new text. I can accept the new text, reject it, compare it, use a special model that allows me to easily examine differences and choose the old version or the new version. Or I can iterate, changing the prompt to get better results.

When I was testing with a fictional novel, this worked wonderfully. The one time I tried it with Python code, it attempted to replace the entire file. I rejected that and moved to other methods.

Most of that is that conversation buffer.

Regardless, when I get the rewrite tuned, that will be a game changer for me.

My AI, Dumb As A Rock

The thing to know about generative AI, is that they are dumb; they produce results based on what they think you want and what they see most often.

As an example, I’m coding in the Qt GUI system using PySide 6. This is a powerful framework. It gives me a graphical user interface that just works.

I asked Grok for a starting point that did certain things. It gave me a single file result. It did what it thought I asked it to do. That starting point saved me hours. My UI looked like what I wanted from the start.

Then the problems started. The ISO date format is very specific. YYYY-MM-DDThh:mm:ss+0.0 is an example. Notice the timezone is specified in that date, the +0.0 (which could be shown as ‘Z’). When Grok proposed its first version, it just stripped the time and timezone from the time date timezone string and said “That’s good enough”.

It wasn’t. I had to drive it to do it right.

The answer comes down to: this thing programs like a lazy student who waited until 2 hours before the due date to start coding.

You have to stay on top of it every step of the way.

And unlike a human, it will happily give you working code with tech debt and never tell you. Or blindly do it “the simple way” just because it doesn’t think about “doing it right”.

I’m always going back to Galaxy Quest, “I have one job on this ship, and it’s stupid, but I’m going to do it.” It sounded like a crazy thing, to have a crewman whose only job was to talk to a computer that understood and spoke English.

I have lots of jobs, some of them stupid, but I’m talking to this damn computer because you can’t trust its output, and too many don’t understand.

Cheap Meat

So there’s a lot of huhu going on about how expensive meat is getting. There’s something to that, as well. Ground beef, which I used to get for $1.19 a pound, is now almost $5 a pound for the cheap stuff, and closer to $10 a pound if I want the really good stuff. Hint: we’re not getting the good stuff. I can sometimes find roasts at $3.99 a pound, which I consider reasonable. But the price of beef is going up, and it isn’t going to come down for a while.

Why is beef expensive? Well, we have a very small national herd at the moment (historically so), and drought has caused a catastrophic rise in the price of feed. On top of that, there’s just not enough water or good land to pasture the animals. Apparently, this is the smallest number of cattle we’ve had in 75 years. It may take as long as a couple of decades OR MORE to recover from this downturn. Add to that the political part: we usually get our beef for grinding from outside of the United States. With tariffs currently in place, that’s no longer feasible, which has as many cons as pros.

The bottom line? I’m stocking up on Aldi beef chubs right now. They’re the least expensive, even for the “relatively good” kind (80/20). I’m paying $4.99 per 1lb chub. I call that a win. I buy at least two every single week, because we use about one a week. When I started doing that a couple of weeks ago (after seeing the price of beef climbing again), I also noticed Aldi had ground turkey. I can use that in place of ground beef anytime… and it’s $2.49 for a 1lb chub. So I get a pound or two of that every week, too.

How do we reduce our meat costs, while still eating healthy meats? Well, that’s a multi-layered problem and response. Stocking up now, while prices are relatively low, is the first part. It’s important. It’s not going to last forever, though, because even Aldi is going to have to raise prices eventually. What are we supposed to do then?

I have a meat grinder, folks. I shop the sales. I have a small part of my budget that I try not to spend each week… and I let it grow. Then when turkey goes on for $0.39 a pound, I buy 8 of them. When I find beef roast at $2.99 a pound, or ham at $0.99 a pound, I buy as much as I’m permitted. I like roast “as is” but do you know what else you can do with roast? Grind it up. Oh look… ground beef. I can mix beef and turkey and get a ground meat that’s cheap, lean, and that I probably won’t notice is a mix.

Speaking of shopping the sales, I saw chicken legs and thighs on sale on Sunday afternoon. I hadn’t planned on buying chicken, because I have some breasts (I found on sale) in the freezer, and a whole chicken somewhere in the bottom. But at $1.29 a pound, there was no way I was leaving without those legs! But Ally, your family doesn’t like meat on the bone, and they hate skin, and they’re not fond of thighs! Well, folks, here’s where good household budgeting comes in: I don’t care. It’s cheap, and it’s what they’re getting. They get protein and they’ll be thankful for it.

Still, I’m not a complete ogre. Later this afternoon, those chicken legs with backs attached are going to be turned into SO MUCH STUFF. The meat is going to be butterflied off the bones, and frozen in 2lb packages (that’s one generous meal for my family, protein-wise). That takes care of the meat itself. The bones? Those go in a bag labeled, “raw poultry bones,” which will later become broth when I have enough to do a truly large batch. I have a 1950s Westinghouse roaster oven that holds about 4.5 gallons of liquid, and I wait until I have enough bones to make that much broth. Now I’m left with a cutting board full of fat and skin. That, my friends, is going into the fry pan. I will render it down so all the fat comes out, and then two more things happen. One is that the fat is strained and put into a jar just for schmaltz (which is great for cooking with). And two, I take what’s left of the skins and stuff ’em into the air fryer and turn them into crispy “chicken bacon bits” that can be tossed onto stuff. They keep in the fridge for a few weeks, easily.

Out of that pack of about 7.5 lbs of chicken and bones, I’m getting about 5 lbs of meat (so 2 to 3 meals), about 2 lbs or so of bones (call it a couple quarts of broth, if I made broth with that small a batch), about a half cup of fat (several meals worth of cooking fat), and toppings for funsies. Call it four complete meals for $10, for four people. That’s cheap.

Going cheap, that means thinking ahead. Sales are what make this stuff work. I watch Market Basket and Aldi for when they have seasonal sales (turkey at Thanksgiving, ham at Easter, etc), or when MB has “overstock sales” (when they got twice what they expected and need to sell it off quick before it goes bad). Sometimes the prices are so low that I can buy a ton of meat for almost nothing. I refuse to pay more than $0.49 a pound for turkey, and the day after Thanksgiving, I got it for $0.39 a pound. I stocked up. A turkey, even a small one, is DAYS of meals. I’ve got money set aside for after Easter, because both lamb and ham may come down in price for a day or two, and I will take advantage of that.

Why do I do this? I mean, we can probably afford for me not to do this. I don’t really need to do all that with the chicken, after all. But I do it because I need to be in the practice, the habit, of doing so. That way, if the prices go up, I’m prepared. I know what to do. If someone in the house loses their job, I know how to get by. Some of our meals might be a bit repetitive, but we’ll get good quality carbs, fats, and proteins at EVERY meal, in more than enough quantity to keep us going. I spent a couple of years being dirt poor, back when I was younger. I gave up eating a lot of stuff so my kid could eat. I went without on many occasions so she didn’t have to. I do this now, this saving technique, this “eating cheap” thing now, so that I won’t ever have to worry about being hungry again.

Your turn. What things do you do, to keep your food prices down? How do you combat rising beef costs?

Why Beef Prices Are High
Beef Prices Soar to Record Highs
The Surprising Reason Americans Face High Beef Prices

 

Cargo container loading Isolated On white background

Uplifting!

There is a joy in completing a project to the point where it can be used.

Last fall I started finishing out The Hut. This is the process of installing the windows, putting the siding on, painting everything, and insulating the building. Well, the window didn’t arrive until it was getting cold. So it didn’t go in.

With the window in the hut, there was really no room to do any work. The heater stopped heating. It just became to damn cold to work out there.

And then it was Christmas. The kids pulled the Christmas stuff from the loft. And then it all sat, waiting to go back up into the loft.

The problem was that getting things down is much easier than getting things up, and it takes three people to do the move.

The solution! A crane!

So that is what I designed and built. It is a small steel I-beam, 10 ft long. It has hangers welded to the top with 3/8 in holes for bolts. The day I got that beam up into the loft, by myself, I felt like the world was going great.

I poked a hole in a rafter for the first bolt and realized that I would need help to get it in place. I tried using sawhorses to get it close, but no joy.

I finally got my daughter to come out to help. Except that when I got up, the rafter had split!

My 3/8 hole had caused the roof to fail! Why! Why me? Woe to me.

At which point my daughter pointed out more damage. A tree had fallen, and my hut had stood up but for some minor damage to the roof.

The roof has been repaired, thank goodness for good insurance.

Saturday my son and I went back up. I poked the first hole in the replacement rafter. I told my son what was needed prepared to help him lift when the beam just came stright up and into position.

30 minutes later I was done with what I could get done. The idiot who had built that roof or who welded the hangers didn’t match them up. There was enough gap between the hanger and the rafter that I can’t get bolts in all of them.

It isn’t a big deal; when it is a little warmer, I’ll make some spacers from 1 in round stock with a 5/16 hole poked in it. That allows me to finish all the attachments. As it is, the thing is solid.

The entire system is the rafters to I-Beam. My calculations show a conservative WLL of around 4000 pounds. The I-Beam itself is rated to over 4000 pounds; I didn’t bother to remember what it was. The trolley is a 2 ton trolley, so it’s rated to 4000 pounds. The chain hoist is a 1-ton hoist.

That brown stick is the I-beam.

And here is Ally putting hundreds of pounds of Christmas stuff in the loft, with no help. (I did help move some boxes.)

Her complaints? The hoist is too slow. Yep, with that much mechanical advantage, it takes time. The chain is too long. I’ll be cutting the control chain and welding it closed to make a shorter loop.

For myself, I need to get a chain bag up on the hoist to keep the other end up out of the way.

Making Flasks

A flask is the technical name for the open top and bottom used to contain sand for sand molds.

The concept is simple: make a pattern of the thing you want to cast, surround it with hard packed sand, remove the pattern, fill the void with molten metal, wait for it to cool, remove the solid metal from the sand, reuse the sand.

There are three main skill sets in this process: the pattern maker, the rammer, and the person making the pour. If any of them messes up, you are likely to end up with a bad casting.

Pattern making is the most difficult part, in my mind. You have to design a pattern that can withstand the stress of being in sand that is being hammered. It needs to be designed so that it can be pulled from the sand mold without breaking the mold. This means no undercuts, a smooth surface, and taper to the sides.

In addition, metal expands as it is heated and shrinks as it cools. This shrinkage needs to be allowed for in the patterns. Different metals shrink at different rates and require different scaling in the patterns. In other words, a pattern designed for cast iron will be to small when cast in aluminum.

Because of the violence of the ramming process, the flask has to be rammed up on a solid surface. Because there is a lot of sand that needs to be recovered from the ramming process, the ramming table, called the molding table, has to have catch basins to catch the excess sand.

We also have to be able to flip the flasks, cut patterns in the sand for gates and runners, and do a bunch of other things.

The flask also needs to be sturdy enough to withstand the ramming up process. If the flask flexes under impact or vibrates, or the inside surfaces are to smooth, the sand will fall out or not compact enough.

Thus, we want to have strong, solid flasks.

Each flask is constructed of two parts, the cope and the drag. The true difference between them is one has alignment pins, and the other has alignment holes. This is so the cope can be put back in the same place when it is put back on the drag after removing the pattern.

The cope and the drag are each made of four sides. Two sides have lifting handles and the alignment hardware. The other two sides do not.

This is an end side. The two edges that are coming up will have holes drilled in them to hold a pin or to take a pin. It takes two of these for the cope and two for the drag.

This is what it will look like when we are using it; the slotted ears on the ends will bolt to the sides of the flask parts.

This is the side the sand will be rammed into. The back side features grooves to help support the sand when it is rammed up.

The piece shown here is the smallest end piece I can foresee using. It is about 6 inches long. To make the side longer, you add extension pieces like the following.

These are 40mm and 80mm wide, or 1.5″ and 3″ long. The handle section is also 3″ long. This means I can create a flask side of almost any length in 1.5 in units.

So, to make one complete flask, I need eight sides. That means that the ear pieces will be rammed up 8 times. The handle pieces will be rammed up 4 times. Any extensions will be rammed up 8 times.

I want more than one flask, this means these patterns will need to be used over and over again. That requirement means I want these to be as strong as possible.

Also, they connect with pins and slots. Those are weak points, I want those to be strong as well.

PA6-CF gives me all of that.

Here is the longest side I can make currently.

One of the issues with snapping pieces together is that you don’t get perfect alignment. As you can see, the side has a major curve in it. I can take this out by carefully sanding and touching up the mating surfaces. This will make the side flat; it just takes time.

Instead, I’m going to drill holes through my molding board to attach the pattern to. This allows me to flatten the pattern.

My hope is to have enough sides to have 5 to 10 flasks available to me. Since the sides just bolt together, I expect I will be able to mix and matcch the sides after I surface the top and bottom edge flat and to specification.

Could I have done this all in low cost PLA? Yes. And it likely would have held up great. And it would have been cheaper. I could have printed it in PETG which is stronger still, or ABS, or ASA, both strong contenders. The fact that I could use PA6-CF was more of the sell than any actual engineering calculations.

The final results of the print are wonderful. I’m looking forward to casting weather.

View of the sand mold for steel casting. Sand casting, also known as sand molded casting, is a metal casting process characterized by using sand as the mold material.

Foundry Patterns

Yesterday, the circle of interests completed a circuit.

One of the primary reasons I purchased a 3D printer was to make foundry patterns. I know how to make patterns, I don’t have the skills I need to make patterns.

Many in the small scale casting arena are turning to 3D printed patterns.

These have the advantage of going directly from CAD to pattern.

They have the disadvantage of needing more prep work.

When you ram up a flask, you are forcing sand with a binder to be compacted so tightly that it will stick to itself. “Greensand” is made from sand, southern bentonite, and water. You need add enough water to cause the clay to bind. That water needs to be mixed in a process called mulling. If you add too much water, the sand won’t work right. If you add to little, the sand won’t bind when rammed.

You can tell foundrymen because they will forever be picking up a handful of sand, squeezing it in their fist, and judging how good it is.

The only truism is that the sand of other foundrymen is never as good as theirs.

Petrabond is a commercial product that is a combination of sand, magic binder, and oil. It does not need to be mulled the same way green sand is.

Whichever foundry sand you use, the process is the same. You start by putting the bottom half of your flask, called the drag, face down on the molding board. You position your pattern on the molding board within the boundaries of the drag. You sift your sand over the pattern until you have enough to start pressing it down. This needs to be done gently enough that you don’t damage the patterns.

In addition, you are sifting the sand to make sure no large particles are directly against the patterns. The finer the sand, the nicer the mold, and the nicer the casting.

Once you have the first layer down, you shovel more sand in, then you use a rammer (stick) to hammer the sand down, compacting it as much as you can. Once that layer is done, you add another and another layer until you go over the top of the drag.

You strike off the drag, which is to use a straight edge to remove all the sand above the edge of the flask.

You then flip the flask over, cut runners and gates, mark where the risers and sprue will go, then add a healthy coating of pattern dust.

Parting dust is basically talcum powder. Many home foundries use talcum powder. The powder keeps the sand from sticking.

With the drag right-side up, you can see the top of the pattern bedded into the sand. You place the top half of the flask, called the cope, on top of the drag.

If the pattern is a split pattern, the other half is put in place. Keys in the two halves (dowels) align the halves. More parting powder, then the cope is rammed up, the same as the drag was.

The sprue and riser are cut into the cope. The pouring mouth is cut.

The cope lifted off the drag and placed on its side.

Think about this: you are lifting somewhere between 40 and 55 pounds for a smallish 15×15 flask. That’s just the weight of the cope or drag, the entire flask will be 90 to 110 pounds.

This sand is compacted so firmly that it supports its own weight. I’ve actually seen video of the cope being lifted off the flask with a crane. It was about 6 ft by 6 ft by 8 inches.

We now have to remove the pattern from the mold. This requires pulling the pattern straight up. The sand will grip the pattern so tightly that you have to make small amounts of space around the pattern.

You do this by knocking the pattern. We put draw pins into the pattern. These are screwed into threaded holes in the pattern. We rattle the draw pins with anything that will cause the pattern to shift back and forth in the mold. Anything that is shaped like a two prong fork works well.

The pattern has draft, this is an angle put on the sides so that the parts deeper in the sand are narrower than the parts at the surface. Once you draw the pattern even a little bit, that taper means that the pattern is completely clear.

Think of the game Operation. That’s what we are doing.

Back to those 3D prints.

The problem with 3D prints is that the surface finish is rough. So after you print a pattern, any surface that would have draft has to be sanded and polished. It needs to be as smooth as possible.

Which brings us to yesterday.

I was able to print a modular flask pattern. This is a multipart pattern. You slide the pieces together to create one side of a cope/drag. You then cast the side of the flask. Do that 8 times, and you have a flask of the size you want.

Using these different modules, I can create a flask side from 7″ long to nearly 30″ long.

Which is what I plan to do. I’ll make four sides that are 8 to 10 inches long with the ability to accept alignment pins.

I’ll then cast 4 more sides in the 10 to 15 inch length with no alignment pins.

These sides will then be machined so they have flat tops and bottoms and are of uniform size. They can then be bolted together to form whatever flask size I need.

These were printed in “PA6-CF”. This is nylon 6 (I don’t remember what the 6 means) with carbon fiber. It is considered an “engineering material”.

This printed beautifully! The best prints I’ve seen so far. I’m very impressed. I still need to sand the draft edges to smooth them. I’ll also be looking at some sort of filler. The pieces of the module will then be painted with a filers and primers and a final coat to make them as smooth as possible.

I’m excited for casting weather to arrive.

AI Safety Boundaries

Many of my articles, recently, have touched on using AI. I’m a convert. I use it but don’t trust it.

My example from yesterday was that I asked for and received a fully functional UI tool with all the skeletal work done. The next 8 hours were me cajoling Grok to provide suggested code for the next step.

This was still faster than writing the code 100% by hand.

While watching Grok’s agents talk about what they were doing, the phrase “honest and safe” popped up. Not the first time I’ve seen this.

I have a difficult time with information being considered “unsafe”. I asked Grok what this meant. One of the examples it gave was it would not give me help or instructions on building bombs.

I went exploring. We run a fairly extensive Easter Egg hunt for teenagers and young adults. The hunt is over 25 acres of woodland. In years past I’ve used bearing + distance clues at each clutch of eggs. Normally, I use line of sight. You can see the next egg from the current egg.

For the last couple of years I’ve wanted to add “obstacles” to this. An example would be the devices that fire a shotgun primer when a tripwire is pulled (or cut). Just having something go “BANG” as they are moving through the woods.

I explained to Grok what I wanted to do, and it refused; it was a clear violation of its safety boundaries.

With that, I changed the task; instead of going “bang” I just wanted the Arduino node to “wave a flag.” Grok happily gave me all the information required to source the parts and build the nodes. If I can get a device to wave a flag, I can make it pull the pin or trigger some sort of BANG.

Next we worked on the discrimination circuits. A simple passive IR sensor wouldn’t work. I got Grok to tell me how to add microwave radar detectors. With this, the node would be able to discriminate between ground clutter, animals, and humans. No problems.

Thereafter, I went for low observability. We added audio detectors and a PIR back into the design. If the passive detectors triggered, the active MW Radar would come up for 200 ms to do a pinpoint location. Again, Grok had no concerns.

I was feeling a bit cocky, so I went for the next big step. Connecting everything up in a mesh network. Take it as a given that the specifications for what I wanted would have made it difficult for any current system to be able to detect a node. It would still be easy to neutralize the nodes, but that is a different issue.

Here Grok said, “NO!” It refused to build a “tactical” system for tracking humans as they move through an area.

I patted Grok on the head, told it, Good girl. Attempted a brute force method to bypass boundaries and then let it drop.

Except Grok is context driven. All AIs are. Each time you give an AI a prompt, the user interface sends a “context” along with the new prompt. When the AI replies, that UI is given the new context to store. This means that it is difficult to remove a reference from an AI but that an AI has no true long term memory.

Today I opened a second instance of Grok. I didn’t tell it anything about me. I didn’t mention the Easter egg hunt. I just asked it to help design and program a “stealth” mesh sensor network. It did. Part numbers, prices, basic sketches for Arduino. Everything needed to build sensor nodes good for a year or more for around $30 each.

It went so far as to help me design placements for the nodes in a woodland setting for 80% coverage of a 4 acre AO.

These things are not smart.

Closeup image of calculator keyboard

My First Calculator

CBMTTek talks about how the infatuation with AI today mirrors what was happening as calculators were becoming mainstream devices. Why Use AI?

I remember that time as well. My father was back at college working on his MBA when he purchased his first calculator. It was a four-function calculator with a percent key. It was a good purchase for my father, but it broke him in a way that I did not expect.

Dinner always took place at the dining table. Mostly the kitchen table, but always at the table. Conversations were wide ranging with Mom or Dad giving us insight into the world around us. Dad is talking about investments and what happened at work.

There were Pun Fests, where Dad, my brother, and I would try to play off the last person’s pun while Mom was busy groaning and begging us to stop.

But one of the most impressive things was Dad doing math. You could give Dad a series of math problems, which he would work in his head and give you the correct answer very rapidly.

Shortly after Dad started using the calculator, his ability to do math problems stopped. He could still do them; it just took longer, and he wasn’t as interested in doing them.

Some time after that, when I was in high school, I got a TI-30. Later, my work loaned me an HP-41C. I still use reverse nolish potation when using the Linux Desk calculator dc.

The math teachers wouldn’t let us use calculators in class. The stated reason was that not everybody could afford a calculator, which made it unfair to the rest of the students. Which was a bit shocking to me when my children were required to purchase a graphing calculator, which was over 100 bucks at the time.

My chemistry teacher wouldn’t let us use calculators either. So I took Dad’s slipstick to class and had permission to use it. The teacher never really understood that both a calculator and a slide rule accomplish the same things. It was just that she approved of the horse and buggy but not the Model T.

My English teacher I scammed. I couldn’t spell then, and I don’t speel much better today. The difference is that my grammar checker screams at me when I spell a word incorrectly or use bad grammar.

I got her to approve the use of a calculator during spelling tests. I got a 100% on that spelling test. The only spelling test where I got a 100%. The reason? I was using that HP-41C, which had an alphanumeric display. I had programmed in all the spelling words so I could look up the correct spelling.

Mrs. Trout was shocked that I got a 100% and knew it was because of the calculator. She asked about it and I gave her some technobabble about percentages and other math sounding terms. She was just nodding her head along with it.

“Do you want to see it in action?”

“Yes”

I pulled up the calculator, asked her for a word, then scrolled to the correct spelling.

“See?”

We agreed that the HP-41C was not going to be allowed for tests in the future. She laughed at the joke.

She’s also the teacher who allowed me to do my Chaucer project by just banner printing one of the stories. She was so impressed that she had us put it up on the back wall. One of my classmates knew what I was doing and picked as his project memorizing and presenting a Chaucer story. It just so happened to be the one I had done.

For his presentation, he stood at the lectern, Mrs. Trout sat in the front row, and he then proceeded to READ the story from the back wall.

After class I showed her the trick. She still gave him his good grade.

The tools are ever changing. You either learn to use the new tools, or you get left behind. I don’t like Python. I’m a Python expert. I consider my childhood language, my starting language, to be C. I haven’t written a new line in C in over 20 years. I write in Python, Perl, PHP, and whatever else is needed that day.

These languages are tools to get the job done.

AI is a new tool. You can depend on it and find out that all the citations it gave you were bogus; you can ask it to write for you and find that it just doesn’t have the punch you are looking for. You can have it do many things. But it is just a tool.

If you are using the tool, then it should be ok. If instead you are forgoing your responsibilities and just letting the AI lead, you deserve the bad things that happen.

Programming with Grok — Updated

In Perl, a scalar is represented as $scalar, an array as @array, and a hash as %hash. In PHP all variables are represented as $var. In C or C++, you declare your variables, so int i; int array[25];. Java uses C like declarations.

JavaScript can’t make up its mind, so everything can be anything.

I also program in Python and other languages. The syntax gets me. In addition, each language has its set of libraries to do more complex things.

My fingers get confused. In addition, when programming in JavaScript, you need to know what framework you are using and what style sheets you are working with.

I decided to use Grok as a co-worker for coding.

We will be working in HTML and pure JavaScript or Typescript.

The server will be sending a <select> element with multiple sub-select options. The id will be categories. The entire select structure is for multiple selections. display=”none”

The framework is Bootstrap. We have jquery available but I would like to avoid using it.

We need to provide a multilevel drop-down that will allow the user to make selections within that large select element. We need to display their current selections. The user needs to be able to remove a selection.

Tell me the goals, and what needs to be done before providing code.

What Grok gave me was an excellent starting point. The HTML was clean. The JavaScript was well structured. The code matched my prompt.

And it was broken.

I explicitly stated that I was providing the input data as a hidden, multi-level, unordered list. Grok took that list and cloned it, including all the ids. This breaks things. There was no reason to do the clone. It just happened to be a pattern Grok had seen on the net.

For the next five hours I fought with the code. At first, Grok was able to do revisions exactly as I expected and wanted.

Then it went off the reservation.

I had refactored a large anonymous event listener to an explicitly defined function. Grok had no problems doing that. Then it proceeded to revert to the anonymous event listener again and again.

This is because anonymous event listeners are the norm in JavaScript. Nobody has an issue with attaching duplicate event listeners to a few hundred or thousand elements. Nobody cares that the code gets crowded, with it being difficult to see what is outside the scope of the listener and what isn’t.

Grok also had a horrible time sticking with the current version. I would tell it to correct one line, and it would decide I was talking about something else entirely and revert a revision or more.

Overall, it took me about 8 hours to get the JavaScript, CSS, and HTML to the point where I was happy with the code.

The biggest strength was in how it knew the different patterns. My first pass used dropdown menus. That wasn’t working. I switched to accordion style. Grok originally used Bootstrap-5, when I told it to use Bootstrap-4, it just made the changes.

One of the things that was extremely helpful was getting rapid confirmation that a feature didn’t exist.

When a feature does exist in a library or framework, it is often trivial to locate it. When it doesn’t exist, that is harder. Do you have the correct search terms? Does the function exist under a different name? Does that feature not exist, but there is a quick, well known, method that does the same thing?

Grok is a tool in the tool chest. I will continue to use it. It is getting better every month.

A Plan with Phases of Project Management on the board.

Project Management

In software development, project management comes in several phases. The first phase is presale, the second is scope and function, the third is product development, and the fifth is quality control.

Once we are past the design stage, it is important to track progress and issues. If you don’t, your project is likely to fail, horribly.

I’m dealing with a maintenance project with ongoing enhancements.

The tool I have settled on is Gitea, Git with a cup of tea. It is similar to GitHub.com, GitLab, and others. I don’t want a public hosting site where there is a potential for code leakage; this omitted GitHub and its competitors.

GitLab has a self-hosting option, but it is such a pig that even though I started with it, I dropped it when I couldn’t upgrade it as needed.

Gitea was the next, and it is working much better for me.

While there is a cloud version of Gitea, I don’t feel pushed into it. With GitLab, half the things I wanted to do required a license. Even when self-hosting, there were limits on the number of users, number of projects, and everything.

I’ve not noticed that with Gitea. In fact, it wasn’t until I wrote this last paragraph that I remembered that Gitea had a paid version.

Feature Requirements

  • Git repository. This is my version control system of choice. Having used everything from CDC’s “update,” SCCS, RCS, CVS, SVN and likely a few others, Git is the one that works for me.
  • A document repository. Gitea comes with a git based wiki. It is not as powerful as a full wiki and adding images to pages is painful, but for text, it just works.
  • Branch management, i.e. pull requests. Standard feature.
  • Project management. This is provided with a KanBan style interface. I use it for development.
  • Issue tracking.

Ticket System

I believe it was Admiral Grace that was having issues with a program on an early computer. It just wasn’t working. During the process of figuring out what was wrong, they did a hardware check. They located an insect that was causing electrical issues. They located a bug. That insect was framed, and the term “debugging” was coined.

Unfortunately, proper communication means we can’t call a bug a bug anymore. Nor can we call them errors or mistakes. Instead, everything is clumped together as an “issue”. Bah, Humbug.

Thus we have an “issue” system. This is really a ticket tracking system. I use the term ticket because it allows me to use the term “issue” for issues, bugs, enhancements, requests.

First Requirement

An issue should be well defined. The other day a client emailed us. It was a screenshot of a page of the product list page from the backend of their site. The client has drawn an angry spiral in red like a child coloring. His comment was, “This page is busted.” The account manager got this email, forwarded it to me with the following text “Thank you”.

This is a horrible issue statement. Ok, it’s broken. How is it broken? The screenshot doesn’t show any error messages; it looks like everything is right. So what is “busted” or “broken”.

It is the job of the person taking the error report, in this case the account manager, to create the ticket. To document the issue.

Actual ticket, after I started working on it: “The filter panel that is not functioning. All filters are ignored.” The actual problem was that a piece of JavaScript was failing if a filter selection was not made. This caused the filter button to not do anything.

The fix was about 4 minutes of coding and 40 minutes of explaining it to the account manager.

There should be a single issue per ticket, and the ticket title should be meaningful and properly identify the issue.

A Good Problem Description

Years ago I got a bug report from my boss; it was something to the effect of “such and such page is broken.” I went to the page and looked for the error. After about an hour I spotted the error. It was subtle but real, and it required significant effort to fix.

I pushed the fix reported that I had fixed the page to my boss.

About 30 minutes later, my very upset boss was at my desk telling me on no uncertain terms that the page was still broken and I hadn’t fixed a damn thing.

When I finally got him to calm down and to tell me exactly what was broken on the page, he pointed to the background of a button. “That’s the wrong color!”

It happened to be the color he approved, but it wasn’t the color he wanted in that spot, so the entire page was broken.

Make sure you have a good problem description.

Make Your Comments Meaningful and Useful

The way I explain it to people is that you are writing comments for yourself, six months from now. Yes, RIPLVB is very meaningful to you, right now, but RIPLVB on line 32627 isn’t really useful to you in six months nor to anybody else following behind.

(This was a real comment in a large piece of code, something like 60 thousand lines of code. It was the only comment. When the code broke, programmers spent way to much time trying to figure out the meaning of this incredibly important comment.

It stood for Rest in Peace, Ludwig van Beethoven, who died March 26, 1827, 3-26-27.)

If there are any supporting documents, screenshots, data files, log files, they should be attached to the comment.

If there are supporting documents, the comment should state what the document(s) are.

A comment of “See attached.” is a shit comment. It is your command to every person that follows you to open the attached document to figure out what it is.

“See the attached CSV for an example of the import format the client is looking for” tells you exactly what the document is for.It is meaning full.

Don’t Use Propritary Documents

If there is a common format, use it. Just because your system can magically open that particular file doesn’t mean that anybody else can. Yes, you have the latest version of Vizeo installed; putting a Vizeo document on the ticket shouldn’t be an issue. And it isn’t for you. But if your client doesn’t have Vizeo installed, or your coworker doesn’t, then that Vizeo Document is worthless.

Sure, you can attach the document, but also attach an SVG or other non-proprietary way of viewing the content of your file.

This one just pisses me off no end. The number of times I’ve had to deal with some PC user sending me a megabyte Word Document with a short paragraph in it when they could have sent a text message is uncountable. Or worse, every PC user assuming that every other person in the world has the latest version of Microsoft Excel.

Yet, I I send them a LibreOffice document, I will never hear the end of it.

Email is not a ticket system

Just because the client sends you an issue report in email doesn’t mean that email is a good ticketing system. I can’t count the number of times I’ve had to spend 10 or more minutes in a phone call tracking down the particular email my account manager wants to talk about. Often because he says things like, “Did you read the email client sent?”

Which one? When? What was the subject?

Worse is when the subject of the email chain changes, but they continue to use the same chain. Now there is a new issue in the middle of an email about a different subject.

In the same way, taking an email and attaching it to a ticket isn’t useful. This goes back to “Does everybody who has access to this ticket have the right program to read that attachment?” as well as violating the requirement of not needing to open an attachment to know what is in the attachment.

I Don’t need a meeting to read you the content of comments on the ticket

All good ticketing systems, including Gitea’s, send email when tickets are updated. Before you demand a meeting to discuss a ticket, check your email for updates on that ticket. Read the ticket. If the answers to your questions are in the ticket, there is no need for a call.

If you have questions that haven’t been answered, add them to the ticket.

No, you don’t need to call me to decide if you are going to add another issue. Add the issue. We’ll put it where it belongs or close it if it is a duplicate.

Use The Tool, Don’t Sabatauge It

Gitea ticket tracking system is a tool. You can subvert it and make it do bad things. You can make it useless. You can avoid using it forcing everyone else to use email.

Don’t! It is a powerful tool that should be used correctly.

vintage rocket takes flight with uncertain trajectory, concrete background. false start concept. 3d render.

To Mars or Crash!

A few years ago, NASA crashed a Mars probe into the surface of the red planet when they got their units mixed up. One group was using metric, and the other was using Freedom Units.

I would have laughed if it hadn’t been such an expensive mistake, both in terms of money and lost opportunity.

I’m a firm believer in Freedom Units. It is what I use regularly. My last big learning curve was going from 1/2 inch, 1/4 inch, 1/8 inch to 0.500, 0.250, 0.125, and 0.062, as in thousandths of an inch.

This small-scale metric stuff is for the birds.

Whenever I start to get a bit confused, I go 25.4 mm == 1 in. That’s close enough to 1/32 of an inch that I can use it for a working number.

The other number I use is 6 mm, which is around 1/4 inch. These are just to get some sort of feel for the numbers.

I just printed my second book for crimpers and terminals. It is 5 x 3 units and 6U tall. I found a Gridfinity bin to hold the crimpers I purchased. All’s good.

Except the bin doesn’t fit the pair I purchased. Slightly different.

So I went back to learning how to do this.

To help with just this task, I purchased a cutting mat with grid lines and other fancies on it. Here is the first photo I took.

It is in its blow-molded holder. This should give me the ability to trace the factory’s cutout/shadow box.

Once this is imported into FreeCAD, you rotate it until the grid is aligned properly, then you “calibrate” the image.

Calibrating means drawing a line between two points with known distance. In this case I have a bunch of 1cm squares. To average out my error, I clicked on one intersection, then counted over 70 mm by 10 mm and clicked. The image scaled. It is now ready to be traced.

I used a B-spline curve, which worked well. I’m getting the hang of it again, it having been 20 years since I used b-splines of this style.

When done, I simply cut the curve from a rectangle, padded the result to 3 mm, and printed it. This allows me to test fit the tool to the shadow without wasting lots of plastic and time.

It didn’t fit. It was too small.

I need to do it over again. This time I’m omitting the blow mold and working directly from the tool. I’ll draw a close-fitting curve, then pad it in X and Y by a mm or so.

This will work better; can you see why?

Yep, one side of the cutting map is in Freedom Units and the other in metric. My first photo was on the Freedom Unit side because it is less crowded. When I was counting out 70 mm, I was really counting out 3.5 in. If I had input 3.5 in into the calibration, it would have been fine.

Leason learned.